redis设计与实现-阅读笔记

 

Redis进阶
一、 命令:
a) info replication#查看当前redis实例在集群中的信息
b) raft算法选举领头哨兵
c) 配置参数requirepass password
d) 客户端连接后需要发送auto password
e) dbsize#查看数据库字典的键值对个数
f) expire ttl; pexpire ttl;expireat timestamp;pexpireat timestamp;p为毫秒数
g) persist key;#持久化一个键
h) cluster replicate <node_id>;#可以使得接收命令的节点成为node_id的从节点
二、 事务
1. redis的事务命令 multi 开始 exec结束。如果语法错误则全部命令不执行,运行期错误(如操作sadd 命令用于string类型)会执行所有的正确命令,忽略错误命令.
2. 没有回滚功能
3. 语法错误在开发期避免,运行期错误主要是保持key的不重复,不冲突
4. Watch 一个key时,如果在事务之前修改了key值,则watch会阻止一个事务的执行
5. 可以使用unwatch取消监控
6. sort可以排序列表、集合和有序集合.
sort key1 [by [key2*|key2*->field]] [limit offset count][asc|desc] [get [key2*|key2*->field|#]]
可以使用by参数获取key1的值填入pattern第一个*的位置,再次获取值,根据值排序,pattern匹配的key2/3类型是字符串或者hash类型的字段)get参数可以获取排序完的值,key2*为获取pattern匹配的内容,key2*->field可以获取hash类型的字段,#为获取key1本身
7. incr 等修改健值的操作不会影响过期时间
8. 支持pipeline,一次执行发送多条命令,减少单次执行的往返耗时。
9. 支持队列,使用BRPOP/BLPOP,brpop key1 [key2…] timeout 可以监听多个key,每次从第一个key开始依次访问是否有任务。Timeout = 0为一直阻塞,否则等待到timeout时间结束
10. 支持订阅/发布模式 使用subscribe channel[channel…]. 使用publish channel value,想订阅者发布消息
11. Redis的内部结构:redisObject—键值的结构

12. 持久化数据:
a) RDB(快照方式保存内存的值)
i. 调用save或者bgsave命令保存当前数据的快照
ii. 根据配置规则进行自动快照
iii. 执行flushall命令
iv. 执行复制(replication)时
v. 有两种方式:1.使用主线程保存内存的值,fork主线程,后台线程保存值,并缓存保存过程的中命令

b) AOf(append on file)
i. appendonly yes参数开启aof
ii. appendfilename appendname.aof为保存的文件名
iii. 提供参数达到设定阈值对aof文件进行覆盖重写。重新读取内存中的键生成aof文件,避免长时间追加aof文件过大
iv. 记录修改值的命令,保存到系统的硬件缓存中,系统的硬件缓存是隔一段时间刷盘到磁盘, 提供参数appendfsync everysec/always/no控制刷盘的时间。
13. 集群:
a) 在redis的配置参数中用slaveof <masterip> <masterport>设置当前服务为从服务器。
b) 从服务器启动时,会想主服务器节点发送sync命令,主服务器会RDB保存快照,采用fork主线程形式,并缓存保存过程中的修改值的命令,完成后,把快照和缓存的命令发送到从服务器,从库加载快照并执行缓存的命令实现同步。以上过程称为复制初始化,初始化后,主服务器在收到修改值的命令后,会同步到从服务器
c) 主从同步架构,哨兵机制、增量复制、无硬盘复制(网络直接发送数据)
d) 增量复制,
i. 从服务器发送psync命令发送实例运行唯一id和断开前最新的命令偏移量,主服务器判断是否与自己的运行id一致,防止错误读取。
ii. 主服务器搜索积压队列,如果从服务器的最新命令在队列中,则执行增量复制,否则全量
iii. 积压队列的大小和所有从服务器与主服务器断开后,完全释放积压队列需要的时间间隔。
e) 哨兵:
i. 监控主服务器和从服务器是否正常运行。
ii. 主服务器出现故障时,自动将从服务器提升为主服务器
iii. 一个哨兵可以监控多个主从系统,也可以监控其他哨兵
iv. 单哨兵架构

v. 多哨兵架构

vi. ./redis-sentinel ../sentinel.conf 启动哨兵 (sentinel.conf的简单配置内容: sentinel monitor mymaster 127.0.0.1 6379 1)(sentinel monitor identify-master-name master-ip master-port quorum)quorum参数用于多少个哨兵认为主服务器主观下线就认定为客观下线
vii. 哨兵实现原理
1. 会使用两条与主数据库的连接,1条订阅_sentinel_:hello频道获取其他哨兵的信息。另外一条定时向主数据库发送info等命令获取主数据库本身的信息
2. 订阅了其他哨兵的信息会与其他哨兵建立一条连接,定时发送ping命令
3. Info命令获取主数据的信息,解析从数据库,再建立两条与主数据库功能相同的连接
4. 哨兵每个down-after-millisenconds参数指定的时间发送ping命令到各个服务器,如果down-after-millisenconds内未回复,则认为主观下线,如果是主数据库,哨兵发送sentinel is-master-down-by-addr询问其他哨兵是否认为主观下线,如果超过quorum数量的哨兵认为主观下线,则认定为客观下线
5. 使用raft算法选举领头哨兵,进行故障恢复。
a) 选举从数据库优先级高的 slave-prioprity
b) 相同优先级则选择最新命令的偏移量大的
c) 相同偏移量则选运行id小的
14. Redis过期键删除策略:
a) 定时删除
i. 执行pexpireat的时候创建一个定时器,到时间立即删除
ii. 内存友好型,cpu不友好型
b) 惰性删除
i. 当获取或者设置命令(set/lrangg/sadd/hget/keys)执行前,检查当前key是否过期,过期则删除,再执行命令函数
ii. CPU友好型,内存不友好型
c) 定期删除
i. 每个一定时间,服务器遍历所有的expire字典,检查需要删除的键值
ii. 内存和CPU均衡型
d) Redis采用策略:
i. 惰性删除:
ii. 定期删除:
1. 每个一段时间,选择几个数据库,随机访问几个expire字典的值,删除需要删除,可以指定定期删除的时间和定期删除的频率。
iii. Aof和rdb和复制功能
1. Aof:过期键在删除的时候会添加del记录在aof文件
2. Rdb:rdb在保存内存的快照时,会忽略已经过期的键
3. 复制功能:服务器运行在复制模式下,从服务器在等到过期键的时候已经返回数据,直到主服务器删除过期键时,发送del命令到从服务器的时候删除键。
15. 持久化:
a) Save,bgsave,bgrewriteaof命令
i. 三者都无法两两共同运行
ii. Save 900 1;save 300 10 ,save 60 10000;配置bgsave执行的周期,定期检查(距离上次成功后的修改次数,上次保存的时间戳)
b) aof持久化
i. 子线程对数据所有的键值读取,写入到临时的aof文件。
ii. 在子线程读取过程中,主线程接收到的命令,会添加一份到原有aof文件缓冲区,再添加一份到aof重写文件缓冲区
iii. 子线程读取完毕后,通知主线程,执行新旧aof文件覆盖,保障原子性。执行主线程收到通知后进行替换才会阻塞其他事件

16. 事件
a) Redis是事件驱动模型
i. 文件事件
1. 服务器对套接字操作的抽象
ii. 时间事件
1. 给定的时间点执行
b) 文件事件处理器
i.
ii. 客户端和服务端通信的过程
iii.
c) 时间事件:
i. Redis的时间事、件采用无序链表实现,在主线程执行时间事件时,遍历整个链表,如果时间到达执行时间,则调用相应的事件处理器执行,根据处理器返回的值来判断是定时事件还是周期事件
ii. 时间事件的数据结构可以优化为小根堆来实现,每次只需要访问根节点就可以判断是否需要执行。
d) 命令请求的过程:
i. 根据输入的命令,查找命令表(字典),封装请求的内容为redisCommand结构。
ii. 执行命令前,进行预备操作,检查命令是否找到,参数个数是否符合要求,是否需要auth认证,如果打开maxMemory,检查内存是否达到设定值,是否需要回收、等等之类。
iii. 执行命令函数
iv. 执行后续工作,打开了慢查询功能,则添加本命令到慢查询日志中,记录当前命令的耗时,开启了aof则添加aof记录,有从服务器,则发送命令到从服务器
v. 执行完成后,客户端的套接字会变成writeable状态,命令回复处理器执行回复命令
e) 服务器启动到能处理客户端的命令请求需要执行以下步骤:
i. 初始化服务器状态
ii. 载入服务器配置
iii. 初始化服务器数据结构
iv. 还原数据库状态
v. 执行事件循环
17. 集群
a) 在配置文件中修改cluster-enabled yes;cluster-config-file file-name;#同目录下保证唯一
b) 使用cluster meet ip port;让集群之间建立连接
c) 使用./redis-cli –p port cluster addslots {0..5000};#分配槽位,总共16384个槽位,分配完成才能集群才能使用
d) 使用./redis-cli –c –p port;客户端使用集群模式连接服务器
e) 使用CRC16计算hash值,用16384来确定槽点,进行切片。
f) 在重新分片的过程中,如果客户端在发送命令获取一个键时,原服务器首先在自己库中查找是否存在,存在则响应命令,否则发送ASK错误,重定向到正在迁移槽位的目标服务器执行。
g) 集群中的从服务器复制主服务器的数据,在主服务下线后替代,实现高可用(容灾)
h) 集群中的节点定期向其他节点发送ping命令,如果超时未返回pong命令,记录并向其他节点发送目标主机疑似下线的消息。如果半数以上的主节点认为目标主机已经下线,则目标主机状态为已经下线。在集群中广播该消息
i) 故障转移:
i. 下线主节点的所有从节点中选举一个节点
ii. 执行slaveof no one 成为主节点
iii. 新的主节点撤销对旧主节点的所有槽指派,并将这些槽指派给自己
iv. 新的主节点向集群广播一条pong消息,告知已经接管原先的槽位
v. 开始接收和处理自己负责的槽位,故障转移结束
j) 集群通过发送和接收消息来通信,常见的消息有MEET PING PONG PUSHLISH FAIL五种

 

 

posted @ 2019-03-13 17:21  少年郎dj  阅读(389)  评论(0编辑  收藏  举报