Redis降低内存占用(一)
本文最后更新于:2024年7月6日 早上
引子
深圳,雨,单休周末。午觉醒来,重新打开许久没看的《redis实战》,今天下午就看看 redis 性能优化部分。
降低Redis的内存占用所带来的好处:
- 减少创建、加载快照的耗时
- 提升载入、重写AOF文件的效率
- 缩短从服务器的同步耗时
- 提高Redis的内存使用效率
书中所提到的主要优化策略有:
- 短结构
- 分片结构
- 打包存储二进制位和字节
下面一一道来。
一、 短结构
在列表、散列和有序集合的长度较短或者体积较小的时候,Redis 可以选择使用一种名为压缩列表的(ziplist)的紧凑存储方式来存储这些结构。
压缩列表
是列表、散列和有序集合这三种不同类型的对象的一种非结构化表示:
普通情况下,Redis中数据结构的底层实现方式(这一部分知识在《redis实战》一书中提及的很少,在《redis设计与实现》一书中有比较详细的阐述):
- 列表——双链表
- 散列——散列表
- 有序集合——散列表+跳跃表
启用压缩列表的情况下:
- 序列化的方式保存数据
- 每次读取需要解码
- 每次保存需要重新编码
- 可能对内存中的数据进行移动
1. 压缩列表的实现
不使用压缩列表的额情况下,以列表数据结构为例:
- 用来实现列表的双向链表,由于需要保存前后节点的指针信息,以及当前数据指针,加上保存自己的数据长度、剩余空间的两个整数。
- 举个例子:在32位系统上。一个列表中的一个长度为3个字节元素,需要至少21字节的额外空间
而启用压缩列表的情况下:
- 压缩列表是由节点组成的序列。每个节点需要两个额外的描述数据:一个用来记录上一个节点长度,一个用来记录当前节点的长度
- 举个例子:在32位系统上。一个列表中的一个长度为3个字节元素,只需要2字节的额外空间
显而易见的,Redis中当保存的每个数据长度都很短时,如果不做处理,那么Redis用来描述这个数据位置的数据可能远远大于数据的本身,这就是为什么需要使用压缩列表。
启用压缩列表
1 |
|
列表、散列、有序集合可以使用压缩列表实现,而集合则不太相同。
2. 集合的整数集合编码
集合当满足以下条件时可以进行优化:
- 所有成员都可以被解释成十进制整数
- 处于平台的有符号整数范围之内
- 集合成员足够少
满足上述条件的集合,Redis将会以整数集合
这种底层数据结构来实现当前集合。
1 |
|
超过以上设置的集合会被换为用散列表来实现。
3. 不成熟的优化所带来的的问题
在开始的时候我们提到过压缩列表需要额外的编码、解码过程。
可以看到加入我们错误的设置了一个阈值,比如将一些很长的数据用压缩列表来保存,而且同时这一部分的数据属于热点数据,读写次数高。
那么每次编码解码所带来的性能损失,将大于空间占用的降低。
参考资料
《Redis实战》源码:https://github.com/huangz1990/riacn-code/blob/master/ch09_listing_source.py
后续将介绍分片、打包,待续。。。