diff --git a/日常学习/中间件/redis/5种基础数据结构详解.md b/日常学习/中间件/redis/5种基础数据结构详解.md index 51cde45..1f321e7 100644 --- a/日常学习/中间件/redis/5种基础数据结构详解.md +++ b/日常学习/中间件/redis/5种基础数据结构详解.md @@ -47,6 +47,7 @@ index可以为负数,index=-1表示倒数第一个元素,同理index=-2表 ### 2.2底层数据结构(quicklist) 实际上Redis的list并不是一个简单的linkedlist,而是quicklist(快速链表)。 在元素较少情况下,会使用一块连续的内存存储,这个结构是ziplist(压缩列表)。将所有的元素彼此紧挨着存储,也可以看作是数组结构。当数据量比较多的时间才会变成quicklist,因为普通的链表需要的附加指针空间(前后指针),所以Redis将链表和ziplist结合组成quicklist,将多个ziplist使用双向指针连接使用。 +quicklist内部默认单个ziplist长度为8kb,超过这个字节数,就会另启一个ziplist ![[Snipaste_2023-02-22_16-10-55.png]] ## 3.hash Redis字典相当于Java的HashMap,属于无序字典,在数据结构上使用的是数组+链表也就是散列表结构。 @@ -99,4 +100,7 @@ hash结构可以结构化存储用户信息,相比于json存储,可以单独 ![[Snipaste_2023-02-23_10-00-41 7.png]] ### 5.2 底层数据结构(跳跃列表) -查看数据结构相关文档 \ No newline at end of file +查看数据结构相关文档 + +### 5.3 假如元素score值相同 +zset的排序元素不只看score值,如果score相同还会比较value值(字符串比较) \ No newline at end of file diff --git a/日常学习/中间件/redis/内存回收机制.md b/日常学习/中间件/redis/内存回收机制.md new file mode 100644 index 0000000..e3c3f84 --- /dev/null +++ b/日常学习/中间件/redis/内存回收机制.md @@ -0,0 +1,3 @@ +redis并不是总将空闲内存立即归还给操作系统。 +操作系统是以页为单位来回收内存,这个页上只要有一个Key在使用,那么它就不能被回收。Redis虽然删除了1GB的key,但是这些key被分散到了很多页中,每个页有其他key存在,这就导致了内存不会被立即回收。 +可以执行flushdb删除所有的key,这个操作很危险且能有效回收内存。 \ No newline at end of file diff --git a/日常学习/中间件/redis/小对象压缩ziplist.md b/日常学习/中间件/redis/小对象压缩ziplist.md index 68b3704..f0e8d4f 100644 --- a/日常学习/中间件/redis/小对象压缩ziplist.md +++ b/日常学习/中间件/redis/小对象压缩ziplist.md @@ -6,3 +6,14 @@ Redis的ziplist是一个紧凑的字节数组结构,每个元素之间都是 + 如果set里存储的是字符串,那么sadd会升级为hashtable结构(HashSet) # 存储界限 +当集合对象的元素不断增加,或者某个value值过大,这种小对象存储也会被升级为标准结构 +| 序号 | 规则 | +| ---- | ------------------------------------- | +| 1 | hash的元素个数超过512 | +| 2 | hash的任意元素的key/value的长度超过64 | +| 3 | list 的元素个数超过512 | +| 4 | list的任意元素的长度超过64 | +| 5 | zset 的元素个数超过128 | +| 6 | zset的任意元素的长度超过64 | +| 7 | set 的整数元素个数超过512 | + diff --git a/日常学习/中间件/redis/过期策略.md b/日常学习/中间件/redis/过期策略.md new file mode 100644 index 0000000..53a81b5 --- /dev/null +++ b/日常学习/中间件/redis/过期策略.md @@ -0,0 +1,19 @@ +Redis会将设置了过期时间的key放入一个独立字典中,由定时任务及惰性删除策略来删除过期key。 +所谓惰性删除就是在客户端访问这个Key的时候,Redis对key的过期时间进行校验,如果过期了就删除 +# 一、定期扫描 +redis默认每秒进行10次过期扫描,它不会遍历字典中的所有Key,而是采用了贪心策略,步骤: +1. 从过期字典中随机选出20个key +2. 删除这20个key中已经过期的 +3. 如果过期key的比例超过1/4,那就重复步骤1 +为了保证过期扫描不会出现循环过度,导致线程卡死,算法还增加了扫描时间的上线,默认不超过25ms。 + +Redis会持续扫描过期字典,直到字典中的过期Key变得稀疏(不超过1/4)才会停止。这就导致线上读写出现明显的卡顿,这种卡顿的另外一种原因是内存管理器需要频繁回收内存页,产生了CPU消耗。 +所以如果有大批量的key过期,要给过期时间设置一个随机范围,而不能全部在同一时间过期。 + +## 1.1 从节点的过期策略 +从节点不会进行过期扫描,从节点对过期的处理是被动的。主节点在Key到期时会在AOF日志中添加del命令,同步到所有从节点,从节点通过执行命令进行删除,这就导致了主从数据不一致。 + +# 二、惰性删除 +大部分情况下del命令执行很快,如果删除一个包含成千上万元素的Hash,那么删除会导致单线程卡顿。 +Redis为了解决这个问题引入了unlink指令,它能对删除操作进行懒惰处理,交给后台其他线程来异步回收内存。 +这个命令不会导致线程安全问题,可以将整个Redis内存里面的有效数据想象成一颗树,当使用unlink时,它只是把其中一个树枝剪断了扔到旁边,在离开树的一瞬间,它就再也无法被主线程中的其他指令访问。 \ No newline at end of file