Redis小对象压缩

小对象压缩存储

如果Redis内部管理的集合数据结构很小,他会使用紧凑存储形式压缩存储。

Redis的ziplist是一个紧凑的字节数组结构,如下图所示,每个元素之间都是紧挨着的。

如果他存储的是hash结构,那么key和value会作为两个entry相邻存在一起。

如果他存储的是zset,那么value和score会作为两个entry相邻在一起。

Redis的intset是一个紧凑的整数数组结构,他用于存放元素都是整数的并且元素个数较少的set集合。

如果整数可以用uint16表示,那么intset的元素就是16位的数组,如果新加入的整数超过了uint16的表示范围,那么就使用uint32表示,如果新加入的元素超过了uint32,那么就使用了uint64。Redis支持set集合动态从uint16升级到uint32,在升级到uint64。

如果set里存储的是字符串,那么sadd立即升级为hashtable结构。

存储界限

当集合对象的元素不断增加,或者某个value值过大,这种小对象存储也会被升级为标准结构。Redis规定在小对象存储结构的限制条件如下

hash-max-zipmap-entries 512 # hash 的元素个数超过 512 就必须用标准结构存储

hash-max-zipmap-value 64 # hash 的任意元素的 key/value 的长度超过 64 就必须用标准结构存储

list-max-ziplist-entries 512 # list 的元素个数超过 512 就必须用标准结构存储

list-max-ziplist-value 64 # list 的任意元素的长度超过 64 就必须用标准结构存储

zset-max-ziplist-entries 128 # zset 的元素个数超过 128 就必须用标准结构存储

zset-max-ziplist-value 64 # zset 的任意元素的长度超过 64 就必须用标准结构存储

set-max-intset-entries 512 # set的整数元素个数超过512就必须用标准结构存储

Redis内存回收机制

Redis并不总是可以将空闲内存立即返回给操作系统。

如果当前Redis内存有10G,当删除了1GB的key后,再去观察内存,会发现内存变化不会太大,原因是操作系统回收内存是以页为单位,如果这个页上只要有一个key还在使用,那么他就不能被回收。Redis虽然删除了1GB的key,但是这些key分散到了很多页面中,每个页面都还有key存在,这就导致了Redis内存不会立即被回收。

不过,如果执行了flushdb,然后在观察内存会发现内存确实被回收了。原因是所有的key都被删除掉了,大部分之前使用的页面都完全干净了。

Redis虽然无法保证立即回收已经删除的key的内存,但是他会重用那些尚未回收的空闲内存。

内存分配算法

内存分配是一个非常复杂的课题,需要适当的算法划分内存页,需要考虑内存碎片,需要平衡性能和效率。Redis为了保持自身结构的简单,在内存分配这里直接使用了第三方内存分配库,如使用jemalloc(facebook)库来管理内存,也可以切换到tcmalloc(google)。因为jemalloc相比tcmalloc性能稍好,所以Redis默认使用了jemalloc。

相关推荐
2301_7816686113 分钟前
Redis 面试
java·redis·面试
吐泡泡_19 分钟前
Redis(缓存)
redis
要一起看日出30 分钟前
MVCC-多版本并发控制
数据库·mysql·mvcc
Hx__31 分钟前
MySQL InnoDB 的 MVCC 机制
数据库·mysql
速易达网络32 分钟前
ASP.NET MVC 连接 MySQL 数据库查询示例
数据库·asp.net·mvc
无名客042 分钟前
redis分布式锁为什么采用Lua脚本实现。而不是事务
redis·分布式·lua·事务
玉衡子1 小时前
MySQL基础架构全面解析
数据库·后端
梦中的天之酒壶1 小时前
Redis Stack扩展功能
数据库·redis·bootstrap
GreatSQL1 小时前
GreatSQL分页查询优化案例实战
数据库
Leo.yuan2 小时前
不同数据仓库模型有什么不同?企业如何选择适合的数据仓库模型?
大数据·数据库·数据仓库·信息可视化·spark