一、内存空间
删除数据后释放的内存会交给内存分配器,并不会直接返还给操作系统—导致Redis仍然持有这些内存,但实际不能使用。(跟MySQL一样明明删除了数据还是没有显示释放内存,需要经过内存整理操作系统才能获得该部分内存)
1. 内存碎片产生的原因
- 操作系统分配内存机制:操作系统每次都是按照固定大小分配内存,8、16、32字节等,会预分配一些内存给程序(为了减少内存分配操作次数);
- Redis业务复杂,每次增删改查的数据所需内存空间不一致,数据删除修改时会导致内存空间的移动。
2. Redis碎片自动清理机制
涉及内存拷贝,由Redis的主线程执行,会和Redis主线程争夺CPU资源,影响Redis对外提供服务,一般会设置碎片清理线程占用CPU时间在一定范围内,同时设置只有碎片空间超过某一阈值时才触发,减少碎片清理的次数。(可以使用INFO memory指令查看当前碎片率。)
二、缓冲区
1. 输入输出缓冲区(与客户端交互)
Redis给每一个客户端设置了一个输入和输出缓冲区,收发数据都是暂存在这两个缓冲区中的。
2. 输入输出缓冲区溢出的原因:(本质是三个原因)
- bigkey操作,一次性写入大量数据(数据传输过快过大);
- Redis主线程经常阻塞,来不及消费缓冲区请求(数据处理较慢);
- 持续使用MONITOR命令,会持续监听redis的指令执行情况,但是会持续向输出缓冲区写入数据(缓冲空间过小)。
3. 输入输出缓冲区溢出解决方法:
- 避免使用bigkey;
- 生产环境避免持续使用MONITOR指令;
- 设置合理的缓冲区大小。
4. 主从复制时的缓冲区
- 要控制主节点RDB文件的大小,避免从库复制RDB文件耗时过久,主节点的缓冲区溢出(全量复制);
- 不要有太多的从节点,主从使用输出缓冲区,会占用主库和客户端链接的输出缓冲区大小;
- 设置合理的复制积压缓冲区大小(增量复制时用到),主库会将更新操作实时记录到环形的复制积压缓冲区(主从库闪断后从库读取该缓冲区进行与主库的数据同步),当该缓冲区溢出后会触发全量复制。
缓冲区相关可以由以下图解释:
参考文章:
https://time.geekbang.org/column/article/292285