最近学习redis,发现redis源码和它的名气一样优秀,忍不住深入学习了一把(由于本人工作不涉及C语言,为此还专门下了一本linux网络编程的书来补充必要知识,以加深对redis思想的理解),为了加深理解,这里做下学习记录,后续随着学习的深入会持续更新。
redis对外体现5种对象:字符串对象、列表对象、哈希对象、集合、有序集合。5种对象各有不同的命令操作集。
为了高效实现,这5种对象的底层实现可能不只一种数据结构,下面作总结:
以上5种对象的底层数据结构可能随着数据的变化而发生切换,下面一一列出:
输入为整数时,字符串对象才有int存储,如果修改该对象值为字符串,则对象实现切换为原始字符串(sds)
输入为小于等于32字符的字符串,则使用嵌入式字符串对象表示,如果修改该对象,则对象实现切换为原始字符串
输入为大于32字符的字符串,则直接使用原始字符串实现
初始数据结构是压缩列表,当列表元素的值长度>=64字节或者列表元素个数>=512,则切换为普通列表实现
初始数据结构是压缩列表,当列表元素的值长度>=64字节或者列表元素个数>=512,则切换为哈希表实现(哈希表采用字典实现)
如果输入为整数,则使用整数集合,否则使用哈希表实现。如果是整数集合,当集合元素>=512个时,则切换为哈希表实现
初始数据结构为压缩列表,当列表元素个数>=128或者元素值的长度>=64字节时切换为跳跃列表实现
对象类型 | 支持的命令 |
---|---|
字符串对象 | SET/GET/APPEND/...... |
列表对象 | LPUSH/RPUSH/LPOP/RPOP/LINDEX/LLEN...... |
哈希对象 | HSET/HGET/HDEL/HLEN/...... |
集合对象 | SADD/SCARD/ISIMEMBER/SMEMBERS/SPOP...... |
有序集合对象 | ZADD/ZCARD/ZCOUNT/ZRANGE/ZRANK...... |
SAVE/BGSAVE
RDB文件直接存储redis的kv数据,通过命令SAVE可以阻塞服务器生成RDB文件,BGSAVE命令基本和SAVE命令一样,但是生成RDB文件是由子进程执行的,所以不会阻塞主服务器的对外服务。这里抛出一个问题:在线服务的redis如果已经满载运行,内存使用率超过50%,RDB持久化是否会失败?
AOP:append only file,存储的是redis命令,通过执行AOP文件中的命令,redis数据库也能达到加载RDB文件的效果。
同一条记录经过多次修改,可能产生多条AOP记录,导致AOP文件膨胀很大。但实际上,这些多条记录产生的最终数据只有一个状态,也就是最后修改后的状态,如果只存储一条同等效果的命令,将会节省很大空间,因此AOP持久化部分有个AOP重写功能,根据当前数据库状态生成AOP文件,避免了普通AOP占据空间过多的问题
sentinel也成为哨兵,用于监控主从redis服务器、故障转移等。redis的哨兵采用raft来选领头sentinel。
sentinel会分别和被监控的主服务器和从服务器创建两个网络连接:命令连接、订阅连接
sentinel以每10秒一次的频率向主服务器发送INFO命令,通过INFO命令的返回信息,sentinel可得知主服务器的信息以及该主服务器下管理的从服务器信息
sentinel以每10秒一次的频率向从服务器发送INFO命令,通过INFO命令的返回信息,sentinel可更新从服务器信息
sentinel以2秒一次的频率向主服务器和从服务器发送PUBLISH命令,广播__subscribe__:hello频道,公布自己的IP、端口、主服务器IP、主服务器端口等信息
sentinel通过订阅连接发送SUBSCRIBE命令,订阅__subscribe__:hello频道,其他sentinel广播时,通过广播信息来更新本sentinel的主服务器信息以及更新其他sentinel在本sentinel中维护的信息,并且会创建连接其他sentinel的命令连接
sentinel以1秒一次的频率向主服务器、从服务器、其他sentinel发送PING命令,其他节点收到PING命令后,可能返回如下值:
如果各个节点在超过一定时间内连续返回无效回复,则该sentinel会判定该节点为主观下线(包括主服务器、从服务器、其他sentinel),如果是主服务器被判定为主观下线,则该sentinel会咨询其他sentinel将该主服务器弄成客观下线,如果同意的sentinel个数超过配置值,则设置该主服务器为客观下线。然后监控这个主服务器的sentinel会使用raft算法协商谁来当领头sentinel,只有某个sentinel收到超过一半的其他sentinel的同意,则它升级为领头sentinel,并负责主服务器的故障转移
主从复制相关命令:SLAVEOF、SYNC、PSYNC
客户端执行SLAVEOF命令向从服务器发起复制请求,然后从服务器使用SYNC/PSYNC向主服务器发起复制请求。PSYNC是SYNC的优化版,支持增量复制,为了增量复制,需要几个关键变量:
从服务器复制基本流程:
1.通过SLAVEOF命令参数得到主服务器的IP和端口
2.创建套接字连接主服务器
3.发送PING命令试探主服务器健康状态
4.发起身份验证(如果配置了masterpass选项)
5.向主服务器发送自身侦听的端口信息
6.向主服务器发送PSYNC命令,开始同步
7.同步完成之后,主服务器通过广播命令即可保证主从同步
8.同步完成后,从服务器以1秒一次的频率向主服务器发送REPLCON ACK 命令