一文理解 Redis 的核心原理与技术
一、Redis 基础数据结构
Redis 里的字符串是动态字符串,会根据实际情况动态调整。类似于 Go 里面的切片-slice,如果长度不够则自动扩容。至于如何扩容,方法大致如下:当 length 小于 1M 的时候,扩容规则将目前的字符串翻倍;如果 length 大于 1M 的话,则每次只会扩容 1M,直到达到 512M。
Redis 里的 List 是一个链表,由于链表本身插入和删除比较块,但是查询的效率比较低,所以常常被用做异步队列。Redis 里的 List 设计非常牛,当数据量比较小的时候,数据结构是压缩链表,而当数据量比较多的时候就成为了快速链表。
Redis 中的 zset 是一个比较特殊的数据结构(跳跃列表),也就是我们了解到的跳表,底层由于 set 的特性保证了 value 唯一,同时也给了 value 一个得分,所谓的有序其实就是根据这个得分来排序。至于跳跃表如何插入,其实内部采用了一个随机策略:L0:100%-L2:50%-L3:25%-....Ln:(n-1)value/2%。
二、Redis 进阶使用
1. 布隆过滤器
(1)命令使用
bf.add
bf.exists
bf.madd
bf.mexists
(2)原理
2. 分布式锁
命令
setnx lock:mutex ture #加锁
del lock:mutex #删除锁
三、深入原理
1. IO模型
Redis IO 处理模型
2. 通信协议
3. 持久化
(1)RDB
(2)AOF
(3)混合持久化
4. 主从同步
同步过程:
-
建立连接,然后从库告诉主库:“我要同步啦,你给我准备好”,然后主库跟从库说:“收到”。
-
从库拿到数据后,要把数据保存到库里。这个时候就会在本地完成数据的加载,会用到 RDB 。 主库把新来的数据 AOF 同步给从库。
5. Sentinel
6. Redis集群工作原理
set key value
集群中每个主节点都会定时发送信息到其他主节点进行同步,如果其他主节点在规定时间内响应了发送消息的主节点,则发送消息的主节点认为响应了消息的主节点正常,反之则认为响应消息的主节点疑似下线,则发送消息的主节点在其节点上将其标记“疑似下线”。
四、Redis为什么变慢了
-
执行 SET、DEL 命令耗时也很久; -
偶现卡顿,之后又恢复正常了; 在某个时间点,突然开始变慢了。
原因分析
-
由于 Redis 在 IO 操作和对键值对的操作是单线程的,所以直接在客户端 Redis-cli 上执 行的 Redi s 命令有可能会导致操作延迟变大; -
使用复杂的命令会让 Redis的处理变慢,以及CPU过高,例如 SORT、SUNION、ZUNIONSTORE 聚合类命令(时间负责度O(N) ); -
查询的数据量过大,使得更多时间花费在数据协议的组装和网络传输过程中; -
大 key 查询,比如对于一个很大的 hash、zset 等,这样的对象对 Redis 的集群数据迁移带来了很大的问题,因为在集群环境下,如果某个 key 太大,会导致数据迁移卡顿; -
另外在内存分配上,如果一个 key 太大,那么当它需要扩容时,会一次性申请更大的一块内存,这也会导致卡顿。如果这个大 key 被删除,内存会一次性回收,卡顿现象会再一次产生。 -
集中过期,变慢的时间统一,所以业务中的 Key 过期时间尽量在统一的一个时间点加上一个随机数时间; -
内存使用达到上限,当内存达到内存上限的时候,就不许淘汰一些数据,这个时候也可能导致 Redis 查询效率低; -
碎片整理,Redis 在 4.0 版本后会自动整理碎片(由于内存回收过程中存在大量的碎片空间,不整理会导致 Redis 的空间少量浪费),而在整理碎片的过程中会消耗 CPU 的资源,从而影响了请求得到性能; -
网络带宽,Redis 集群和业务混部,或者并发量过大以及每次返回的数据也很大,网卡带宽跑满的情况容易导致网络阻塞; -
AOF 的频率过高,由于 AOF 需要将全部的写命令同步,如果同步的间隔比较短,也会影响到 Redis 的性能; Redis 提供了 flushdb 和 flushall 指令,用来清空数据库,这也是导致 Redis 缓慢的操作。
五、Redis安全
- EOF -
1、
2、
3、
觉得本文有帮助?请分享给更多人
推荐关注「算法爱好者」,修炼编程内功
算法爱好者
算法是程序员的内功!「算法爱好者」专注分享算法相关文章、工具资源和算法题,帮程序员修炼内功。
Official Account
点赞和在看就是最大的支持❤️