mirror of
https://github.com/CyC2018/Interview-Notebook.git
synced 2026-10-31 19:13:42 +00:00
Update Redis.md
调整 GEO 查询中心格与邻格的说明,补充 listpack、混合持久化和 Redis 8 的版本说明;参考资料中的书目去掉已失效的链接,调整两张配图的说明。
This commit is contained in:
+7
-7
@@ -314,7 +314,7 @@ HyperLogLog(HLL)用于估计一个集合中不同元素的个数,例如页
|
||||
|
||||
例如 100 万个不同的元素,PFCOUNT 返回 999674(误差 −0.03%),HLL 占 12 KB,同样的元素用 SET 保存要 30 MB;30 组各 100 万个元素的误差均方根为 0.80%,最大为 2.0%(Redis 7.4 实测,见[附录 A8](#a8-hyperloglog-的误差和内存))。
|
||||
|
||||
GEO 用于“附近的门店”这类查询:GEOADD 保存经纬度,GEOSEARCH 查找某个点一定半径或矩形内的成员并按距离排序,GEODIST 计算两点间的距离。它底层就是一个 ZSET,经纬度交错编码成 52 位的 Geohash 整数作为分值,相邻的点分值相近,查询时只需查找覆盖查询范围的 9 个区域对应的分值区间;代价是距离和范围有误差,官方文档说明最坏可达 0.5%。
|
||||
GEO 用于“附近的门店”这类查询:GEOADD 保存经纬度,GEOSEARCH 查找某个点一定半径或矩形内的成员(加 ASC 时按距离由近到远排序),GEODIST 计算两点间的距离。它底层就是一个 ZSET,经纬度交错编码成 52 位的 Geohash 整数作为分值。同一个格子里的点分值落在一段连续的区间内,但格子边界两侧的点即使相距很近,分值也可能相差很远,所以查询时要查中心格和周围 8 个格子(最多 9 个分值区间),再逐个计算距离过滤;代价是有误差:距离按球面模型计算,官方文档说明由此产生的误差最坏可达 0.5%,经纬度编码成整数时也有精度损失。
|
||||
|
||||
## 三、使用场景 🔥
|
||||
|
||||
@@ -400,7 +400,7 @@ Set 可以实现交集、并集等操作,从而实现共同好友等功能。
|
||||
|
||||
转换后内存明显增加:512 个字段的 HASH 用 listpack 约占 10 KB,再写入一个字段转为 hashtable 后约占 40 KB(Redis 7.4 实测,见[附录 A14](#a14-hash-编码的转换))。
|
||||
|
||||
Redis 7.0 之前用的是压缩列表(ziplist),每个元素要记录前一个元素的长度,这个长度占 1 或 5 个字节,在中间插入或删除元素时可能让后面的元素依次变长,称为连锁更新;listpack 的每个元素只记录自己的长度,避免了这个问题。
|
||||
Redis 7.0 之前,HASH、ZSET 和 quicklist 的节点用的是压缩列表(ziplist),每个元素要记录前一个元素的长度,这个长度占 1 或 5 个字节,在中间插入或删除元素时可能让后面的元素依次变长,称为连锁更新;listpack 的每个元素只记录自己的长度,不会连锁更新,但在中间插入时仍要移动后面的数据。小的 LIST 直接用 listpack、SET 的 listpack 编码是 7.2 起才有的。旧的配置名(例如 hash-max-ziplist-entries)在 7.x 中仍可作为新配置名的别名使用。
|
||||
|
||||
字符串的内容保存在简单动态字符串(Simple Dynamic String, SDS)中,它在字符数组前面记录了已用的长度 len 和分配的容量 alloc:
|
||||
|
||||
@@ -559,7 +559,7 @@ Redis 7.0 起 AOF 由多个文件组成:重写生成的基础文件,以及
|
||||
|
||||
<div align="center"> <img src="pics/redis-aof-rewrite.png" width="760px"/> </div><br>
|
||||
|
||||
配置项 aof-use-rdb-preamble 默认开启,重写生成的基础文件使用 RDB 格式,称为混合持久化:重启时先载入 RDB 部分,再重放增量文件中的命令,兼顾了 RDB 恢复快和 AOF 丢失数据少的优点。两种持久化都开启时,重启后使用 AOF 恢复,因为它的数据通常更完整。
|
||||
配置项 aof-use-rdb-preamble 在 4.0 引入、5.0 起默认开启,重写生成的基础文件使用 RDB 格式,称为混合持久化:重启时先载入 RDB 部分,再重放增量文件中的命令,兼顾了 RDB 恢复快和 AOF 丢失数据少的优点。两种持久化都开启时,重启后使用 AOF 恢复,因为它的数据通常更完整。
|
||||
|
||||
两种方式的对比:
|
||||
|
||||
@@ -664,7 +664,7 @@ Redis 6.0 加入的 I/O 多线程(io-threads,默认关闭)分担的也是
|
||||
|
||||
从服务器第一次连接时进行全量复制:
|
||||
|
||||
1. 从服务器发送 PSYNC,主服务器 fork 一个子进程生成 RDB 快照发给从服务器,并在这期间把新执行的写命令记在缓冲区中。Redis 7.0 起默认不写磁盘文件,子进程直接把快照通过网络发送(repl-diskless-sync yes);
|
||||
1. 从服务器发送 PSYNC,主服务器 fork 一个子进程生成 RDB 快照发给从服务器,并在这期间把新执行的写命令记在缓冲区中。Redis 7.0 起默认不写磁盘文件,子进程直接把快照通过网络发送(repl-diskless-sync yes)。Redis 8.0 起从服务器默认另开一条连接接收快照,期间新的写命令直接发给从服务器、由从服务器先缓存,载入快照后再执行,减轻了主服务器的内存压力;
|
||||
2. 从服务器清空旧数据,载入快照,再执行缓冲区中的写命令;
|
||||
3. 之后主服务器每执行一条写命令,就把它发给从服务器。
|
||||
|
||||
@@ -740,7 +740,7 @@ Redis Cluster 不需要哨兵,节点之间通过集群总线(端口号加 10
|
||||
|
||||
需要注意的是,主从之间是异步复制,主节点宕机前刚写入、还没有复制到从节点的数据会丢失,所以 Redis Cluster 不保证[强一致性](分布式.md#一致性)。网络分区时,少数派一侧的主节点超过 cluster-node-timeout 后拒绝写入,所以它在这之前接受的写入可能丢失;默认配置下读请求也会被拒绝(cluster-allow-reads-when-down 默认为 no)。
|
||||
|
||||
扩容时要把一部分槽迁移到新节点。迁移以键为单位进行,期间一个槽的键一部分在源节点、一部分在目标节点,客户端靠 ASK 重定向找到它们。以把槽 5712 从 7002 迁移到 7003 为例(Redis 7.4 实测,见[附录 A13](#a13-槽迁移与-ask-重定向)):
|
||||
扩容时要把一部分槽迁移到新节点。迁移以键为单位进行,期间一个槽的键一部分在源节点、一部分在目标节点,客户端靠 ASK 重定向找到它们。Redis 8.4 起还可以用 CLUSTER MIGRATION 整槽迁移:先复制整个槽的快照和增量写入,追上后短暂暂停这些槽的写入,一次性切换归属,下面以键为单位的流程仍然可用。以把槽 5712 从 7002 迁移到 7003 为例(Redis 7.4 实测,见[附录 A13](#a13-槽迁移与-ask-重定向)):
|
||||
|
||||
- 先把 7003 上的槽 5712 标记为 IMPORTING、7002 上的标记为 MIGRATING,再用 MIGRATE 把键一批批搬到 7003,每个键在同一时刻只存在于其中一个节点;
|
||||
- 客户端仍然先访问 7002:键还在 7002 就直接处理,例如 {user:1001}:cart 正常返回;键已经迁走或者不存在,返回 ASK 5712 127.0.0.1:7003;
|
||||
@@ -784,7 +784,7 @@ Redis 没有关系型数据库中的表这一概念来将同种类型的数据
|
||||
|
||||
## 附录:实测
|
||||
|
||||
以下实验的环境均为 Apple M1 Pro(10 核)、macOS,客户端和服务器在同一台机器上,Redis 7.4.1 从源码编译,使用默认配置,不开启持久化。
|
||||
以下实验的环境均为 Apple M1 Pro(10 核)、macOS,客户端和服务器在同一台机器上,Redis 7.4.1 从源码编译,使用默认配置,不开启持久化。macOS 上编译默认使用 libc 的内存分配器(INFO 中 mem_allocator 为 libc),Linux 上默认是 jemalloc,内存占用的数字会有差别。
|
||||
|
||||
### A1 MySQL 与 Redis 的主键查询
|
||||
|
||||
@@ -1340,7 +1340,7 @@ maxmemory 默认 = 0
|
||||
## 参考资料
|
||||
|
||||
- Carlson J L. Redis in Action [M]. Manning, 2013.
|
||||
- [黄健宏. Redis 设计与实现 [M]. 机械工业出版社, 2014.](http://redisbook.com/index.html)
|
||||
- 黄健宏. Redis 设计与实现 [M]. 机械工业出版社, 2014.
|
||||
- [REDIS IN ACTION](https://web.archive.org/web/20210421115011/https://redislabs.com/ebook/foreword/)
|
||||
- [Skip Lists: Done Right](https://ticki.github.io/blog/skip-lists-done-right/)
|
||||
- [论述 Redis 和 Memcached 的差异](http://www.cnblogs.com/loveincode/p/7411911.html)
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 190 KiB After Width: | Height: | Size: 147 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 129 KiB |
Reference in New Issue
Block a user