Redis内存问题的学习之一


背景

前几天帮同事看redis的问题
发现info memory 显示 60GB
但是实际上 save出来的dump文件只有 800M
然后导入到其他的redis之后, info memory只有 2G左右的内存. 

所以感觉比较奇怪. 认为 redis 的info memory 在某些特殊情况下可能存在误判.
所以想研究一下内存部分的使用. 

第二天晚上发现PG的一个公众号正好讲解了 pmap -d 感觉正好对胃口 就一起学习和使用一下.

这里参考他的部分内容, 地址为: 
https://mp.weixin.qq.com/s/W8hy31GWFZ_5qCAFnvTyag

第一部分内存的分类

搞清 PSS/USS/RSS/VSS 这类指标的差异:

VSS (reported as VSZ from ps) is the total accessible address space of a process. 
    This size also includes memory that may not be resident in RAM like mallocs 
    that have been allocated but not written to or mmap()ed files on disk, etc
RSS is the total memory actually held in RAM for a process. 
    RSS can be misleading, because it reports the total all of the shared libraries that the process uses, 
    even though a shared library is only loaded into memory once regardless of how many processes use it. It also counts all other shared pages, 
    such as the copy-onwrite pages still shared with the parent after fork(), an important usecase for current LHC multicore usage.
PSS differs from RSS in that it reports the proportional size of its shared pages
USS is the total private memory for a proces, i.e. that memory that is completely unique to that process.

关于pmap的理解

pmap -h

Usage:
 pmap [options] PID [PID ...]

Options:
 -x, --extended              show details
 -X                          show even more details
            WARNING: format changes according to /proc/PID/smaps
 -XX                         show everything the kernel provides
 -c, --read-rc               read the default rc
 -C, --read-rc-from=<file>   read the rc from file
 -n, --create-rc             create new default rc
 -N, --create-rc-to=<file>   create new rc to file
            NOTE: pid arguments are not allowed with -n, -N
 -d, --device                show the device format
 -q, --quiet                 do not display header and footer
 -p, --show-path             show path in the mapping
 -A, --range=<low>[,<high>]  limit results to the given range

 -h, --help     display this help and exit
 -V, --version  output version information and exit

关于pmap -d

-d, --device                show the device format

可以查看类型. 我这边开一个redis ,里面加载了60万个key 进行显示:
127.0.0.1:26379> dbsize
(integer) 648463
127.0.0.1:26379> info memory
# Memory
used_memory:2175437480
used_memory_human:2.03G
used_memory_rss:2255552512
used_memory_rss_human:2.10G

看到内存显示其实是  2.03G左右
pmap -d 636234
mapped: 3643584K    writeable/private: 3424448K    shared: 0K
然后使用 top -Hp 636234

top - 08:24:45 up 345 days, 17:50,  9 users,  load average: 0.59, 1.03, 1.54
Threads:   5 total,   0 running,   5 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.2 us,  0.1 sy,  0.0 ni, 99.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem : 1045898.+total, 464319.4 free, 287949.9 used, 293629.4 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used. 460899.2 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 636234 root      20   0 3643584   2.1g   3456 S   0.0   0.2   6:52.71 redis-server
 636236 root      20   0 3643584   2.1g   3456 S   0.0   0.2   0:00.00 bio_close_file
 636237 root      20   0 3643584   2.1g   3456 S   0.0   0.2   0:00.00 bio_aof_fsync
 636238 root      20   0 3643584   2.1g   3456 S   0.0   0.2   0:00.00 bio_lazy_free
 636239 root      20   0 3643584   2.1g   3456 S   0.0   0.2   0:00.01 jemalloc_bg_thd

发现 mapped 的内存与 VIRT的数值是可以完全对应的
但是RES与 writeable/private 的内存却不能对应. 

这一块有点奇怪, 感觉需要后续继续排查一下.

关于内存的进一步了解

之前总结了 java内存的使用情况, 其实算是宏观层次的理解, 并不微观
也总结过 pcacher工具. 可以看到 buffer和cache相关的内容. 

之前对性能其实有误解. 
CPU是很快的. 但是内存比CPU慢了两个数量级. 

比如一个 8通道 DDR4 4000 的2路20核心 合计 四核心的2.5Ghz的服务器来说. 

内存的延迟一般是 60ns左右.  CPU的一般是 0.4nm, 实际上那个是差了 150倍
关于贷款. 理论上 40核心 2.5Ghz的带宽 不算MIMD 单指令也至少哟 100Ghz*64/8 也就是至少 800GB/S的能力. 
其实实质上因为MIMD的原因, 还会更高. 
内存来说 8*4*8  256G的贷款到顶.  而且还需要不停的充放电, 
带宽层面CPU至少也是内存的三倍以上. 甚至更高. 

所以内存相比CPU是很慢的, 尤其是申请和释放大量的内存, 如果夸numa节点访存,性能其实更差.

Redis内存使用情况

其实键值对 需要设置过期时间
并且增加内存的淘汰策略 
并且设置最大使用内存才是redis使用的基本套路. 

如果不设置最大内存, 可能会有比较严重的风险, 导致宕机
如果不设置过期的策略, 可能对过期键值对的处理存在风险. 

redis还是必须要监控起来. 不建议使用内存大于一半的内存数量. 
另外强烈建议redis使用高主频的服务器. 核心数可以不多, 但是主频一定要高.