127.0.0.1:6380> info memory
# Memory
used_memory:4189334840
used_memory_rss:4692721664
mem_fragmentation_ratio:1.12
mem_allocator:jemalloc-3.6.0
used_memory: Total number of bytes allocated by Redis using its allocator (either standard libc, jemalloc, or an alternative allocator such as tcmalloc).
used_memory最大值是由config set maxmemory xx设置的。
127.0.0.1:6380> config get maxmemory
1) "maxmemory"
2) "9277800448"
used_memory_rss: Number of bytes that Redis allocated as seen by the operating system (a.k.a resident set size). This is the number reported by tools such as top(1) and ps(1).
used_memory_rss该值同top的RES(%MEM),ps的%MEM。
top:
RES - Resident size (kb) The non-swapped physical memory a task is using.
%MEM - Memory usage (RES) A task’s currently used share of available physical memory.
# top -p 2896 -n 2 -d 3 -b | egrep 'COMMAND|redis-server'
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2896 root 20 0 14.5g 4.4g 1160 S 39.8 37.2 6060:55 redis-server
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2896 root 20 0 14.5g 4.4g 1160 S 32.6 37.2 6060:56 redis-server
# grep 'MemTotal' /proc/meminfo
MemTotal: 12330736 kB
SQL> select 12330736 * 0.372 * 1024 from dual;
12330736*0.372*1024
-------------------
4697122603(同used_memory_rss:4692721664)
SQL> select 12330736 * 0.372 / 1024 / 1024 from dual;
12330736*0.372/1024/1024
------------------------
4.37453632(同4.4g)
ps:
%MEM - ratio of the process’s resident set size to the physical memory on the machine, expressed as a percentage.
两者的关系是used_memory_rss / used_memory = mem_fragmentation_ratio(Ratio between used_memory_rss and used_memory)。
SQL> select 4692721664 / 4189334840 from dual;
4692721664/4189334840
---------------------
1.12015913(同mem_fragmentation_ratio:1.12)
mem_fragmentation_ratio可接受的取值范围是[1,1.5],其大于1,是由于内存碎片的存在,这和内存分配器的实现有关,和Redis本身关系不大。从官方文档https://redis.io/topics/memory-optimization的【Memory allocation】部分,可看到碎片的产生情况。
Redis will not always free up (return) memory to the OS when keys are removed. This is not something special about Redis, but it is how most malloc() implementations work. For example if you fill an instance with 5GB worth of data, and then remove the equivalent of 2GB of data, the Resident Set Size (also known as the RSS, which is the number of memory pages consumed by the process) will probably still be around 5GB, even if Redis will claim that the user memory is around 3GB. This happens because the underlying allocator can't easily release the memory. For example often most of the removed keys were allocated in the same pages as the other keys that still exist.
Redis实际使用中used_memory_rss比较大是常见的,config set maxmemory xx只能设置used_memory的大小,不能限制内存碎片的大小,什么情况下碎片会被回收呢?
Jemalloc (and several other libraries) allocate arenas of sizes larger than an original request, then uses that arena to satisfy similarly-sized requests until the arena is all used. As memory is freed, portions of the arena are re-used as requested. If an arena is 100% empty, the Jemalloc will free it to the operating system. If an arena is 1% used, Jemalloc cannot free it to the operating system.
使用Redis时,如何避免碎片的产生呢,虽无100%的保证,但也有方法可依:数据对齐和安全重启(Redis的内存消耗)。另外Redis 4.0引入了Active defragmentation的特性,可在线减少碎片,细节可查看redis.conf。
有时也可能出现mem_fragmentation_ratio小于1的情况,一般的说法是使用了swap。该链接给了一个小于1,但没用到swap的情况,https://github.com/antirez/redis/issues/946。
参考链接:
https://redis.io/topics/memory-optimization
https://hashnode.com/post/what-is-the-difference-between-used_memory-and-used_memory_rss-in-redis-ciibz8fks01d5j3xty0sgi9dk
https://github.com/antirez/redis/issues/4057
https://mp.weixin.qq.com/s?__biz=MzI1ODc4NzU5Mg==&mid=2247483978&idx=1&sn=62d8fb3efd6de009de46517fcd9e220b&chksm=ea03922ddd741b3bd3bf70ddb870e0262e3fd5a16973f215ccd1e5798dcd8e91d3cb73bc5ee9&token=1714442028&lang=zh_CN#rd
https://raw.githubusercontent.com/antirez/redis/4.0/00-RELEASENOTES
https://github.com/antirez/redis/issues/946