《深入理解redis》之三:内存管理的建议与技巧
2019独角兽企业重金招聘Python工程师标准>>>
配置redis
如果想要运行一个内存高效的redis数据库,首先要理解那些在 redis.conf 配置文件中所有内存相关的指令。
redis.conf 为大多数指令提供了丰富的内联文档,大多数redis配置指令可以在运行时通过CONFIG SET进行设置。
rdbchecksum ,默认是yes,将65位循环冗余校验码(CRC64)放置在RDB快照文件的末尾,作为防止文件损坏的一种手段。当redis产生一个子进程将快照保存至磁盘时,对RDB快照进行CRC64校验会增加10%的内存使用。
redis中的主哈希表将主键与对应的值进行关联,若activerehashing=yes,那么该主哈希表每个100毫秒会重新哈希。重新哈希的过程将释放删除了的键占用的操作系统内存。activerehashing 发生在非工作时间,对客户端连接额影响最小。
主从复制
采用主从复制的方式提供高度可靠性、可伸缩性。在集群环境中,通过slave-of 指令将redis实例切换到从模式,此时 从实例 被允许从另一个被指派为主实例的redis中复制数据。内存 和 来自硬件和网络的延迟会直接影响主从实例的性能。
repl-disable-tcp-nodelay 指令可以用来更好地处理redis主从实例间的网络流量拥塞。通过对主从间的密集数据同步和更少的网络流量之间进行权衡,这种复制能够改善高流量情况下的网络性能。
32位redis
在redis.io网站上的官方文档内存优化中,其中有一条建议是在32位模式下编译redis替代默认的64位实例。对于同样小于3GB的数据集,其在32位redis实例中要比在64位版本中的redis中小。
如果应用程序使用整数集合,只要总内存不超过4GB的最大限制,那么32位版本节省的内存是相当可观的。当存入不同大小和类型的值时,redis的32位和64位版本之间的百分比差异意味着节省的内存数量显著降低。对于那些使用集合的应用程序来说,它们较多的使用了字符串,因为64位的redis可能是更好的选择。这是因为在64位版本中的字符串拥有额外的空间及更高效的编码。
对于哈希数据结构来说,32位和64位redis实例并没有特别大的差异:
对于32位版本的redis列表来说,在32位限制之下,列表非常适合存储整数和浮点数:
对于redis集合的测试如下:
1) 32位的redis并未在redis用户群中进行广泛部署和测试,因此相较于64位版本可能会有未发现的bug。
2) 诸如bittop、bitcount这样的位操作基于redis的64位版本进行了优化,因此相较于32位则没有那么高效。
3) 在32位redis中设置maxmemory参数更加困难,如果在32位版本的redis中的maxmemory值设置的过于靠近最大值4GB,那么通信、主从复制、I/O缓存都有可能随时导致redis崩溃。
info meory
10.143.128.165:6379> info memory
# Memory
used_memory:819312
used_memory_human:800.11K
used_memory_rss:1904640
used_memory_peak:2282784
used_memory_peak_human:2.18M
used_memory_lua:36864
mem_fragmentation_ratio:2.32
mem_allocator:jemalloc-3.6.0
used_memory 分配的字节数大小
used_memory_human 将used_memory格式化为人类可读的值
used_memory_rss 常驻集大小(resident set size) 操作系统中看到的内存分配,
以及top显示的结果
used_memory_peak redis使用的峰值内存
used_memory_peak_human 将used_memory_peak可视化
used_memory_lua redis的lua子系统使用的字节数
mem_fragmentation_ratio used_memory_rss与used_memory的比率
mem_allocator 在编译器redis使用的分配器
键过期
保证redis数据库不会超过可用内存---为键设置超时时间,一旦过了键的超时时限,键就会被自动驱逐。
当在键上调用EXPIRE命令设置过期时间时,该超时只能通过删除或者替换键的方式清除。之后,任何改变值的命令都是无法更改或者清楚之前设置的超时的。
10.143.128.165:6379> set name yinn
OK
10.143.128.165:6379> expire name 60
(integer) 1
10.143.128.165:6379> get name
"yinn"
10.143.128.165:6379> ttl name
(integer) 53
10.143.128.165:6379> append name nana
(integer) 8
10.143.128.165:6379> get name
"yinnnana"
10.143.128.165:6379> get name
(nil)
如果在设置了超时的键上调用set或者getset(键过期之前),那么超时会被清除,键不会从数据库中驱逐:
10.143.128.165:6379> set name yin
OK
10.143.128.165:6379> expire name 30
(integer) 1
10.143.128.165:6379> set name xian
OK
10.143.128.165:6379> ttl name
(integer) -1
也可以使用 persist 命令清楚键上的超时设定:
10.143.128.165:6379> set name yinn
OK
10.143.128.165:6379> expire name 60
(integer) 1
10.143.128.165:6379> ttl name
(integer) 51
10.143.128.165:6379> persist name
(integer) 1
10.143.128.165:6379> ttl name
(integer) -1
在一个已经设置过超时的键上调用expire命令将会清楚并重新设定超时:
10.143.128.165:6379> expire name 90
(integer) 1
10.143.128.165:6379> ttl name
(integer) 87
10.143.128.165:6379> expire name 20
(integer) 1
10.143.128.165:6379> ttl name
(integer) 17
10.143.128.165:6379> get name
(nil)
LRU键驱逐策略
通过maxmemory指令将最大内存设置为1MB以创建一个小内存的redis实例。maxmemory指令允许设定内存大小的硬性上限,运行时的redis实例受限于此。
10.143.128.165:6379> flushall ##清楚数据库
OK
10.143.128.165:6379>config set maxmemory 1024
OK
当redis内存耗尽时,默认生效的是永不过期策略(noeviction policy):
默认的maxmemory-policy策略是永不过期。在noeviction策略中,没有键设置为过期。如果redis没有可用内存,任何写操作都会导致redis错误。
10.143.128.165:6379> config get maxmemory
1) "maxmemory"
2) "1024
10.143.128.165:6379>config get maxmemory-policy
1) "maxmemory-policy"
2) "noeviction"
第一种过期LRU策略名为 volatile-lru,它将最近较少使用的键驱逐出去。这些键必须通过 expire set 命令设置了超时的。当redis内存耗尽时,redis开始删除那些设置了过期时间的键,即便该键仍然有剩余时间。
下一个策略是 allkeys-lru ,会删除redis中任何一个键,而且没有办法限制哪些键被删除。
redis的LRU算法是不准确的,因为redis并不会自动选择最佳的候选键来驱逐,例如最少使用的键或者最早访问的键。相反,redis默认行为是选取5个键的samples,并驱逐当中最少使用的那个。如果想要增加LRU算法的精确性,可以更改redis.conf文件中的maxmemory-samples指令,或者在运行时通过config set maxmemory-samples命令进行设置。
将maxmemory-samples增加到10,从而提升redisLRU算法的性能,效果接近真实LRU算法,但是副作用就是消耗更多的CPU计算能力。将maxmemory-samples降至3,从而减少了redisLRU算法的精确性,不过相应地加快了处理速度。
接下来是两种最大内存驱逐策略:volatile-random和allkeys-random。它们与volatile-lru和allkeys-lru相似,但是不采用LRU算法。volatile-random 基于键上设置的过期状态随机驱逐一个键,需要O(n)时间复杂度的操作来计算创建的这些键是否已被驱逐。对于allkeys-random,整个键空间都是开放的。
最后一个最大内存策略是volatile-ttl,redis会尝试根据键的剩余时间(TTL)清除键。
创建内存高效的redis数据结构
小巧的哈希、列表、集合、有序集合
对于哈希、列表、有序集合来说,这种特殊编码方法基于ziplist(压缩列表):
压缩列表是一种特殊的双向链表,专为内存高效进行设计的。它存储了字符串和整数值,其中整数是以真正的整数值而非字符串形式进行存储的。它允许在列表的任意一端以O(1)时间复杂度进行push和pop操作。但是,由于每次操作都需要为ziplist使用的内存进行重新分配,实际上的复杂度与ziplist所使用的内存大小有关。
根据大小、类型以及数据结构的内容,ziplist编码方式为redis数据库极大地节约了内存使用。
redis中ziplist的实现通过为每个节点只存储3份数据实现较小的内存占用:第一份是前一个节点的长度,第二份是当前节点的长度,第三份是存储的值。
对于哈希表来说,hash-max-ziplist-entries 指令设置了总共有多少字段是可以被特殊编码为ziplist,默认是512。hash-max-ziplist-value指令设置了从ziplist转变为哈希表所要达到的最大大小,默认64.
把位、字节和redis字符串用作随机访问数组
在集合中通过使用整数代替字符串,可以将集合的大小显著地降低,但是 位图仍然要比集合小一个数量级、更节省内存。
优化哈希,高效存储
待续P90
转载于:https://my.oschina.net/u/1862478/blog/1935253
《深入理解redis》之三:内存管理的建议与技巧相关推荐
- 【死磕 Redis】------ 理解 Redis 的内存
原文:https://www.topjava.cn/category/1391389927996002304 『chenssy』 我们知道 Redis 的所有数据都存储在内存中,内存是我们系统中的一个 ...
- 深入redis内部--内存管理
2019独角兽企业重金招聘Python工程师标准>>> 深入redis内部--内存管理 博客分类: 缓存 1. Redis内存管理通过在zmalloc.h和zmalloc.c中重写c ...
- C语言文件联系人管理碎片整理,深入理解C语言内存管理.docx
深入理解C语言内存管理 之前在学Java的时候对于Java虚拟机中的内存分布有一定的了解,但是最近在看一些C,发现居然自己对于C语言的内存分配了解的太少. 问题不能拖,我这就来学习一下吧,争取一次搞定 ...
- redis 数据结构 内存管理 持久化
为什么80%的码农都做不了架构师?>>> Redis 内存数据结构与编码 OBJECT encoding key.DEBUG OBJECT key 简单动态字符串(simple ...
- (转载)深入理解Linux中内存管理---分段与分页简介
首先,必须要阐述一下这篇文章的主题是Linux内存管理中的分段和分页技术. 来回顾一下历史,在早期的计算机中,程序是直接运行在物理内存上的.换句话说,就是程序在运行的过程中访问的都是物理地址.如果这个 ...
- 【软件开发底层知识修炼】三 深入浅出处理器之三 内存管理与内存管理单元(MMU)
学习交流加 个人qq: 1126137994 个人微信: liu1126137994 学习交流资源分享qq群: 962535112 上一篇文章学习了中断的概念与意义,以及中断的应用-断点调试原理.点击 ...
- Android内存管理优化建议
OOM(OutOfMemory) 前面我们提到过使用getMemoryClass()的方法可以得到Dalvik Heap的阈值.简要的获取某个应用的内存占用情况可以参考下面的示例( 关于更多内存查看的 ...
- 深入理解Linux内核---内存管理zone
转载:https://blog.csdn.net/gatieme/article/details/52384529 https://blog.csdn.net/gatieme/article/deta ...
- C语言与JAVA内存管理_深入理解C语言内存管理
之前在学Java的时候对于Java虚拟机中的内存分布有一定的了解,但是最近在看一些C,发现居然自己对于C语言的内存分配了解的太少. 问题不能拖,我这就来学习一下吧,争取一次搞定. 在任何程序设计环境及 ...
最新文章
- 替换 RHEL5的yum源为CentOS5源,亲测线上系统可用
- 缩短网址将成微博的重要安全性问题
- 【DIY】联想单板机、联想UPS电源、联想屏幕打造笔记本电脑
- 题目3:文本文件单词的检索与计数(实现代码)
- java swing 案例详解_《Java Swing图形界面开发与案例详解》PDF_IT教程网
- 中断函数 printf_嵌入式中断服务函数的一些特点
- 三星要带头了!考虑明年手机不送充电器
- 电脑无法读取移动硬盘_移动硬盘U盘提示:文件或目录损坏且无法读取如何解决?...
- python画曲线图-python怎么画曲线图
- latex_列表和表格环境_给tabular加lable标签问题
- 半功率点为啥是-3dB
- ARIMA模型的定阶原理与建模分析
- 人工智能时代孩子该学点什么?
- RT-Thread 4.1.0 开启 PM 电源管理框架
- SpringCloud微服务注册和消费模式总结
- 放榜!腾讯iOA、腾讯天幕入选国内数字化可信服务首批认证产品
- 技术揭秘12306改造(二):探讨12306两地三中心混合云架构
- 国产数据库岁末大盘点
- Fiddler 的几个用法
- Android File System安卓文件系统(安卓存储分区,/data /storage /sdcard)
热门文章
- 获取的字段值是空值或者为null,而你自己的需求就是想要获取的字段为一个 * 默认的值
- 已解决mybatis报错:Invalid bound statement (not found)
- 基因组注释1. 重复序列repeatmasker, trf
- 与思科交换机三层链路聚合连接 ❀ 飞塔 (Fortinet) 防火墙
- b站网页html,bilibili注册页面html简单分析
- 公交管理系统的设计与实现
- 实战五十三:基于机器学习随机森林的购房贷款违约预测(完整代码+数据集)
- 北航计算机学院保研占比,许明杰:CSP助力保研入北航
- win10如何设置pdf默认打开方式
- AT指令(中文详解版)(二)