Redis之小对象压缩

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: Redis之小对象压缩

32bit 与 64bit

Redis使用32bit进行编译,内部所有的数据结构使用的指针占用空间会比64bit少一半,如果Redis可使用的内存在4GB以内可以用32bit编译。

小对象压缩存储

ziplist

当Redis数据结构中的数据量比较少时,将会使用紧凑存储形式压缩,例如HashMap原本是一个二维结构(数组+链表),但是内部元素较少时,使用二维结构会比较浪费空间,

此时可以直接用一维数组进行存储,并且此刻使用数组进行遍历查找可以比HashMap本身查找更快。

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

image.png

如果ziplist中存储的是hash结构,那么key和value会作为两个entry被相邻存储,如下面demo所示,对hello这个字典结构增加了

127.0.0.1:6379> hset hello a 1

(integer) 1

127.0.0.1:6379> hset hello b 2

(integer) 1

127.0.0.1:6379> object encoding hello

"ziplist"

如果存储的是zset结构,那zset的value和score会作为两个entry相邻存储。

127.0.0.1:6379> zadd world 1 a

(integer) 1

127.0.0.1:6379> zadd world 2 b

(integer) 1

127.0.0.1:6379> object encoding world

"ziplist"

可以看到,数据量很小的时候,不管是hash还是zset,实际的存储结构都是ziplist。

intset

intset是一个紧凑的整数数组结构,专门用于存储整数元素并且元素个数较少的情况。

如果新加入的整数可以用uint16表示,那么encoding就用uint16表示,如果不够就是用uint32, 还不够就是uint64。

image.png

127.0.0.1:6379> sadd hello 1 2 3

(integer) 3

127.0.0.1:6379> object encoding hello

"intset"

如果set中存储字符串,那么intset将立刻变成hashtable。

127.0.0.1:6379> sadd hello hi

(integer) 1

127.0.0.1:6379> object encoding hello

"hashtable"

晋级条件

当数据结构中的元素触发条件时,数据结构将晋升为标准数据结构。

hash

  1. hash元素个数超过512。
hash-max-ziplist-entries 512
  1. hash中任意元素的key/value长度超过64。
hash-max-ziplist-value 64

list

  1. list元素个数超过512。
list-max-ziplist-entries 512
  1. list任意元素长度超过64。
list-max-ziplist-value 64

zset

  1. zset元素个数超过128。
zset-max-ziplist-entries 128
  1. zset任意元素长度超过64。
zset-max-ziplist-value 64

set

  1. set的整数元素个数超过512。
set-max-intset-entries 512

如下demo,可以看到hash的元素超过512时变成了hashtable,之前都是ziplist。

image.png

同样,当key/value超过64位时, 也发生了变化。

image.png

源码地址:https://github.com/qiaomengnan16/redis-demo/tree/main/redis-zip-struct

内存回收机制

redis并不会将空闲的内存及时还给操作系统,因为操作系统将内存划分为一个一个的页作为基本单位,只要页上还留有一个key,那么这个页就不能被回收,

如果你发现删除了很多的key,内存并没有降下来,这说明还有很多零散的key分散在这些页中导致内存无法回收,如果使用flushdb,内存将会被回收,因为该操作将所有页上的key都删除了。

redis无法保证立即回收已删除的key的内存,但是它会重复利用这些内存,当有新数据来时,redis将会分配在这些空闲的内存上。

内存分配算法

redis自身没有实现内存分配管理,而是交给了第三方内存分配库实现,目前redis默认使用的是jemalloc库管理内存,也可以切换为tcmalloc,前者性能要比后者稍好一些。

通过 info memory 指令可以看到redis正在使用的mem_allocator是什么。

image.png

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
存储 NoSQL API
【Redis源码】ziplist压缩表(八)
【Redis源码】ziplist压缩表(八)
87 0
|
2月前
|
存储 消息中间件 NoSQL
Redis 数据结构与对象
【10月更文挑战第15天】在实际应用中,需要根据具体的业务需求和数据特点来选择合适的数据结构,并合理地设计数据模型,以充分发挥 Redis 的优势。
60 8
|
2月前
|
JSON 缓存 NoSQL
Redis 在线查看序列化对象技术详解
Redis 在线查看序列化对象技术详解
48 2
|
1月前
|
存储 NoSQL Redis
Redis常见面试题:ZSet底层数据结构,SDS、压缩列表ZipList、跳表SkipList
String类型底层数据结构,List类型全面解析,ZSet底层数据结构;简单动态字符串SDS、压缩列表ZipList、哈希表、跳表SkipList、整数数组IntSet
|
7月前
|
存储 缓存 NoSQL
深入浅出Redis(一):对象与数据结构
深入浅出Redis(一):对象与数据结构
|
7月前
|
存储 NoSQL 网络协议
redis主从同步对象模型学习笔记
redis主从同步对象模型学习笔记
83 0
|
4月前
|
缓存 NoSQL 算法
【Azure Redis 缓存】Redis导出数据文件变小 / 在新的Redis复原后数据大小压缩近一倍问题分析
【Azure Redis 缓存】Redis导出数据文件变小 / 在新的Redis复原后数据大小压缩近一倍问题分析
|
5月前
|
存储 NoSQL 容灾
Redis问题之压缩列表zipList在Redis中有哪些应用场景
Redis问题之压缩列表zipList在Redis中有哪些应用场景
|
5月前
|
存储 Java
Redis08命令-Hash类型,也叫散列,其中value是一个无序字典,类似于java的HashMap结构,Hash结构可以将对象中的每个字段独立存储,可以针对每字段做CRUD
Redis08命令-Hash类型,也叫散列,其中value是一个无序字典,类似于java的HashMap结构,Hash结构可以将对象中的每个字段独立存储,可以针对每字段做CRUD
|
6月前
|
缓存 NoSQL Java
redis系列之------对象
redis系列之------对象