Redis总结

数据结构:

SDS(简单动态字符串):

1.杜绝缓冲区溢出

2.减少修改字符串长度时所需的内存分配次数

3.二进制安全

4.兼容部分C字符串函数

链表:

平平无奇的链表实现

dict(字典):

1.使用MurmurHash算法来计算键的hash的哈希值

2.哈希表使用链地址法来解决键冲突,被分配到同一个索引上的多个键值对会连接成一个单向链表(被分配到同一个索引上的键值对使用next指针将现有的和已存在的连接在一起,新添加的总是排在已有节点的前面)

3.在对哈希表进行扩展或收缩时,程序将现有的哈希表包含的键值对rehash到新的哈希表里面,这个rehash过程并不是一次性完成的而是采用渐进式

skiplist(跳跃表)

1.skiplist是一种随机化的数据结构底层是个双向有序链表,大多数情况下,插入、删除、查找的复杂度均为O(logN)(最坏情况下为O(N))

2.由很多层结构组成,且每一层都是一个有序链表,最底层的链表包含所有元素,如果一个元素出现在 Level i 的链表中,则它在 Level i 之下的链表也都会出现。

3.skiplist的性能可以和红黑树媲美,并且实现和维护简单

intset(整数集合):

1.底层实现为数组,以有序或无序的方式保存元素,在有需要时程序会根据新添加的元素类型改变数组的类型(int16_t  -> int32_t  -> int64_t)

2.升级操作为整数集合带来了操作上的灵活性,尽可能的节约了内存

3.整数集合只支持类型升级不支持降级操作

ziplist(压缩列表):

1.经过特殊编码的双向链表,提高存储效率

2.包含多个节点,每个节点可以保存一个字节数组或整数值

3.添加新节点或删除节点肯能会引发连锁更新操作(previous_entry_length属性记录了前一个节点的长度,当节点大于大于254字节时previous_entry_length使用5字节表示,从而引发所有节点previous_entry_length更新)

数据库:

redis是一个键值对数据库服务器

redis数据库结构基于字典,因此数据库增删改查都是对字典操作来实现的

键过期时间:使用一个单独的字典存储键的过期时间,

过期删除策略:redis使用惰性删除和定期删除两种策略删除过期的键

1)惰性删除:放任键过期不管,每次从数据库获取键时,检查键是否过期,如果过期则删除,未过期则返回

2)定期删除:每隔一段时间程序对数据库进行一次检查,删除过期的键

持久化:

1)RDB持久化

 redis使用rdb持久化功能将内存中的数据保存到磁盘里避免数据丢失,该功能可以手动执行,也可以定期在某个时间点上自动执行,RDB文件是一个经过压缩的二进制文件

手动执行:   

SAVE:生成RDB文件,该命令会阻塞redis进程,直到RDB文件创建完毕

BGSAVE:生成RDB文件,该命令使用子进程执行命令,不会影响主进程

自动执行:

可以通过配置设置BGSAVE命令的执行频率(save选项配置),默认为:900秒内至少一次修改、300秒内至少10次修改、60秒内至少10000次修改  才会触发BGSAVE命令

Redis没有专门用于载入RDB文件的命令,RDB文件的载入是在服务启动的时候自动执行的     注:如果服务器开启了AOF持久化,则优先使用AOF文件还原数据库状态,未开启才会使用RDB文件还原

2)AOF持久化

AOF持久化是通过保存Redis服务器所执行的命令进行记录,服务器在执行一个写命令后把执行的命令追加到aof缓冲区末尾,由缓冲区写入到文件的频率为1秒

AOF还原时服务器创建伪客户端将AOF文件中的命令重新执行一遍即可还原数据库状态

AOF持久化流程中的文件同步策略(默认使用eversec,通过appendfsync选项配置)

always:每次写入缓存区都要同步到AOF文件中,硬盘的操作比较慢,限制了Redis高并发,不建议配置。

no:每次写入缓存区后不进行同步,同步到AOF文件的操作由操作系统负责,每次同步AOF文件的周期不可控,而且增大了每次同步的硬盘的数据量。

eversec:每次写入缓存区后,由专门的线程每秒钟同步一次,做到了兼顾性能和数据安全。是建议的同步策略,也是默认的策略。

AOF重写:

为了解决AOF文件膨胀问题,Redis提供了AOF重写功能,使用子进程读取数据库当前状态生成相应的命令写入到新文件中,并替换旧的AOF文件

在AOF重写期间,服务器收到新的命令会被放到缓冲区,等到重新完成服务器将缓冲区命令写入到AOF文件尾部

主从复制:

通过从服务器执行SLAVEOF命令将自己设置成从节点并与主节点连接、同步, 如:SLAVEOF 129.03.222.1 6379

当主服务器第一次收到从服务器发来的SLAVEOF命令时会执行BGSAVE命令,并将生成的RDB文件、服务器ID,当前偏移量发送到从服务器,发送完毕后主服务器检查缓冲区中是否存在未同步的命令,存在则将缓冲区中命令发送给同服务器,至此完成同步。当主服务器执行客户端命令时修改自身偏移量并同时主服务器作为从服务的客户端向从服务器发送命令及偏移量数据,从服务器偏移量执行  当前偏移量 + 本次偏移量

复制积压缓冲区:固定长度队列,默认大小1M,里边保存着一部分最近执行过的命令

部分重同步:

场景:从服务器与主服务器断开连接一段时间,这段时间内主服务器持续执行客户端命令,当从服务器与主服务器重连

1.重连成功主服务器检查从服务器保存的服务器ID与自己是否相同,如果不相同则执行全量同步,相同检查偏移量

2.主服务器检查从服务器当前偏移量与自己相同,不相同,则检查从服务器偏移量之后的命令是否在自己的积压缓冲区

3.检查复制积压缓冲区中是否存在从服务器偏移量之后执行过的命令,存在则将这部分命令发送给从服务器,不存在则执行全量同步

哨兵:

Sentinel(哨兵)是运行在特殊模式下的Redis服务器,Redis 的高可用性解决方案:由一个或多个Sentinel 实例组成的Sentinel 系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器。使用redis-sentinel sentinel.cfg方式启动哨兵

1.哨兵以每 10 秒一次的频率向主服务器发送INFO命令来获得主服务器下的所有从服务器信息,监测同一个主服务器的哨兵相互之间会互相发现

2.每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令 

3.如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。

4.如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。 

5.当哨兵判定当前服务器为主观下线时,会向同时监测这个主服务器的其他哨兵进行询问,当达到指定的确认数量后(大于等于配置文件指定的值)判定服务器为客观下线

6.当服务器被标记为客观下线状态监测这个主服务器的sentinel会选举一个leader进行故障转移

7.选取从服务器中状态良好的置为主服务器,并将其他从服务器切换到复制当前主服务器,将已下线的主服务器设置为新主服务器的从服务器

注:复制偏移量越大的从服务器意味着保存着最新的数据,变成主服务器的机率也就越大

集群:

Redis提供的分布式数据库方案,集群通过分片来进行数据共享,并提供复制和故障转移功能

1.服务器通过配置cluster-enable 为yes决定是否开启服务器集群模式,使用CLUSTER NODES可以查看集群信息

2.使用CLUSTER MEET [IP] [PORT]来添加节点,当前服务器向命令指向的服务器发起握手,指定服务器响应成功后将其添加的当前集群当中

3.集群数据库被分为16384个槽,当16384个槽都有节点处理时,集群处于上线状态,如果有任何一个槽没有得到处理,集群都处于下线状态

4.相应客户端使用CLUSTER ADDSLOTS [sore…] 命令指派当前客户端处理那些槽(0-16383)

5.集群当中各个节点通过消息进行传播,当添加节点成功、处理槽设置成功等信息经过一段时间即可被集群中所有节点识别

6.当集群上线后执行命令,所连接服务器会先计算要处理键的槽是否属于自己,属于则执行并返回结果,不属于则向客户端返回MOVED错误(包含:键的所属槽、处理该槽的服务器信息)指引客户端至正确的节点并执行命令,使用CLUSTER KEYSLOT <key>可以查看键属于那个槽

7.当所有槽都被处理时添加新的节点或修改服务器处理的槽可以进行重新分片,相关槽的所属键值对会从源节点移动到目标节点,重新分片时,集群不需要下线,并且源节点和目标节点都可以继续处理命令请求

8.当重新分片期间,服务器收到客户端命令先检查自己的槽中是否有这个键,如果没有则代表已迁移到新节点中,这时服务器会返回一个ASK错误(包含:键的所属槽、处理该槽的服务器信息)指引客户端至正确的节点并执行命令

9.使用CLUSTER REPLICATE <node_id>设置节点为指定节点的从节点,并开始对主节点进行复制,当设置成功,该操作会在集群中进行传播,所有节点都会知道某个从节点正在复制某个主节点

10.集群中的每个节点都会定期的向及群众的其他节点发送ping消息,如果对方没有在指定时间内容回复则会将对方标记为疑似下线状态,集群中通过消息交互个节点的状态信息,当半数的主节点都认为某个节点为疑似下线状态时会将该节点标记为已下线状态,并进行故障转移

11.在下线的主节点的从节点中选取一个成为新的主节点,代替下线节点进行处理响应的槽,并将剩余的从节点切换复制当前主节点

发布与订阅:

SUBSCRIBE订阅某个频道、UNSUBSCRIBE退订频道、PUBLISH发送消息

1.客户端订阅某个频道时服务器检查频道(例:news.it)是否存在,不存在创建频道并将当前客户端信息添加到订阅者队列尾部,存在则直接添加到队列尾部

2.客户端向频道发送消息时,服务器获取当前频道订阅队列,并推送给所有人

3.客户端退订频道时将该客户端在订阅队列删除,如果这时队列为空则将频道一并删除

PSUBSCRIBE订阅模式、PUNSUBSCRIBE退订模式

1.客户端订阅某个模式时服务器检查模式(例:news.*)是否存在,不存在创建模式并将当前客户端信息添加到模式订阅者队列尾部,存在则直接添加到队列尾部

2.客户端向频道发送消息时,检查是否存在与之匹配的模式,存在则推送给频道订阅者和模式订阅者

3.客户端退订频道时将该客户端在订阅队列删除,如果这时队列为空则将频道一并删除

PUBSUB CHANNELS当前被订阅的频道、PUBSUB NUMSUB [channel]当前频道订阅数量、PUBSUB NUMPAT [channel]当前模式订阅数量

注:redis不对消息尽心持久化,一旦消息被发送,如果没有订阅者接收,那么消息就会丢失,并且没有确认机制

事务:

Redis 事务的本质是一组命令的集合支持一次执行多个命令。在事务执行过程,按照串行化执行队列中的命令(注:redis事务支持ACID,redis事务不支持回滚)

Redis天生具有隔离性,因为它是单线程串行执行客户端命令的

MULTI开启事务、EXEC提交事务、WATCH乐观锁

1.使用MULTI命令开启事务,接着将多个命令放到事务中(事务中存在一个命令队列)

2.使用EXEC命令提交事务,事务会被服务器串行执行,服务器检查命令是否存在语法错误,如果有则返回失败,如果存在执行时错误服务器不会中断事务,会继续执行事务中其他命令

3.使用WATCH命令可以在开启事务前监视任意数量的key,在提交事务时,如果这些key发生改变(被其他客户端修改或过期)服务器则返回失败

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值