参考书籍:redis设计与实现(第二版)
第一部分:数据库结构
1.Redis字典:Redis的字典使用哈希表作为底层实现。
a) 结构:redis字典中包含两个hash表ht[0]和ht[1]。
b) 一个哈希表中有多个哈希表节点,每个哈希表节点中保存一个键值对。
c) 键冲突(多个哈希表节点被分配到同一个索引上):将不同的哈希表节点通过单项链表连接起来,新节点加入链表表头
d) 扩容规则:size>=ht[0].used*2;size=2ⁿ;ht[1]为符合条件的最小的值size的值。
收缩规则:size>=ht[0].used;size=2ⁿ;ht[1]为符合条件的最小的值size的值。
e) Rehash操作:将ht[1]进行扩容与收缩操作;‚将ht[0]中的所有键值对(哈希表节点)rehash到ht[1]上面(注:处理过程中需要对ht[0]的中数据中的键值重新计算索引并放到对应ht[1]上);ƒht[0]中数据全部rehash到ht[1]中后,释放ht[0],将ht[1]设置为ht[0],并创建新hash表作为ht[1],为下次rehash操作做准备。
第二部分单机数据库
1.数据库实现。
a) 数据库结构:redisServer(服务器状态结构)中包含redisDb[],dbnum;其中redisDb[]为数据库数组,dbnum表示数据库的个数。
b) 切换数据库(使用select命令),通过改变redisClient结构中目标数据库指针,指向redisServer中redisDb[]中的不同元素,从而实现切换数据库。
c) 数据库主要有dict和expires两个字典构成,dict(键空间)用于保存键值对,expires用于保存过期时间。
d) 对数据库的操作是建立在字典操作之上的。
e) Redis数据库的键为字符串,值可以为任何一种redis对象,包括字符串、哈希表、列表、集合、有序集合,分别对应字符串键、哈希表键、列表键、集合键、有序集合键。
f) Expires用于保存过期时间,expires字典的键指向数据库中的某个键(和dict中指向同一个键),值记录了该数据库键的过期时间(以毫秒为单位的UNIX时间戳)。
g) Redis使用惰性删除和定期删除两种策略删除过期键。
h) 3种删除策略:定时删除:通过定时任务删除数据,定时任务查询到数据立即删除(内存压力小,cpu压力大)‚惰性删除:放任过期数据不处理,当查询获取数据时,判断要查询的数据是否有需要删除的数据,如果有过期数据,删除(内存压力大,cpu压力小)ƒ定期删除:以上两种方式的折中,定期删除数据,隔一段时间,对数据库进行检查,检查多少个数据库,删除多少数据由算法决定可以控制。
i) 执行save命令或者bgsave命令生成的新的rdb文件,不包含已经过期的键。
j) 当主服务器删除一个过期键之后,会向从服务器发送del命令,显示的删除过期键。
k) 当从服务器发现过期键之后不会删除,而是等主服务器发送del命令,从而保证主从服务器的数据的一致性
l) 可以通过配置,当redis对服务器进行修改后,对客户端发送数据库通知。
2.RDB持久化
a) RDB文件用于保存和还原Redis服务器数据库状态和键值对数据。
b) Save命令由服务器进程执行,会阻塞服务器。
c) Bgsave命令由服务器子进程执行,不会阻塞服务器。
d) 服务器状态中可以配置save选项,从而控制bgsave自动执行(可以设置多个条件,当其中一个条件符合的时候就会自动执行bgsave命令)
e) Rdb文件是一个经过压缩的二进制文件,由多部分组成。REDIS+db_version+databases+EOF+check_sum
f) 对于不同类型的键值对,rdb会以不同的方式来保存。
3.AOF持久化
a) AOF文件通过保存所有操作redis数据库的写命令来记录数据库的状态
b) AOF文件中的命令以redis命令请求协议的格式保存,是可以在redis服务器执行的命令。
c) 命令请求会先保存到AOF缓冲区里面,再定期写入同步到AOF文件中。
d) Appendfsync的设置方式,对AOF持久化功能的服务器性能和安全性有影响(always、everysec、no)。
e) 服务器只需要载入并执行AOF持久化文件中的命令,就可以恢复数据库。
f) AOF文件重写会生成一个新的AOF文件,两个文件保存的数据库状态一致,但是新的AOF文件体积更小(多条命令合并成为一条命令)。
g) AOF重写,并非在原来AOF文件的基础上进行读入和分析,而是通过读取数据库中的键值对来生成新的AOF文件。
h) AOF_REWRITE命令和BGREWRITEAOF命令。执行BGREWRITEAOF命令的时候,redis服务器会维护一个aof重写缓冲区,在子进程创建aof文件过程中,记录redis此过程中执行的写命令。在子进程创建aof文件结束后,会把重写缓冲区中的内容追加到aof文件的末尾,使新旧两个aof文件保持一致。
第三部分多机数据库
1.主从复制
a) Redis2.8以前的复制方式不能有效处理断线后重复制。处理方式,1:从服务器发送sync命令,2.主服务器生成rdb文件,并开辟缓存区存储生成rdb文件之后的写命令3.发送rdb文件,4.发送缓冲区写命令;redis2.8以后的部分重同步可以实现。处理方式:1.从服务器发送psync命令,2.主服务器判断同步方式(1>完整重同步【和原来一样】;2>部分重同步【将断线后主服务器的命令发送给断线的从服务器执行】)
b) Redis2.8以后psync命令实现:
Psync + <runID> + <offset> 主服务器进行判断(1.runID是否为当前主服务器ID;2.offset偏移量是否+1在复制积压缓冲区是否有相对应内容)是否返回“+continue”,如果返回+continue则进行部分重同步,如果返回“+fullersync”执行完整重同步,如果返回-err表示版本在redis2.8以下,无法识别psync命令。
c) 心跳检测:从服务器每一秒钟发送replconf ack+ <offset>命令给主服务器
作用:1.如果超过1秒未接收到从服务器的命令,说明主从服务器连接异常
2.辅助实现min-slaves命令实现。
3.检测命令是否丢失,如果offset偏移量不一致说明出现命令丢失情况,在复制积压缓冲区找到命令传给从服务器。
2.哨兵(sentinel)
a)哨兵是redis的高可用性解决方案。作用:监视任意多个主服务器以及主服务器下的所有从服务器,在某个主服务器进入下线状态时,自动将下线主服务器下的某个从服务器升级为主服务器。
b)
3.集群