redis.server生成RDB文件时,会对各种数据类型进行编码(各种类型编码方式不一样)和压缩(LZF算法压缩),所以生成的RDB文件会比 used_memory_human 小很多。
以字符串对象写入RDB的代码为例:
/* Save a string object as [len][data] on disk. If the object is a string * representation of an integer value we try to save it in a special form * * 以 [len][data] 的形式将字符串对象写入到 rdb 中。 * * 如果对象是字符串表示的整数值,那么程序尝试以特殊的形式来保存它。 * * 函数返回保存字符串所需的空间字节数。 */ int rdbSaveRawString(rio *rdb, unsigned char *s, size_t len) { int enclen; int n, nwritten = 0; /* Try integer encoding * * 尝试进行整数值编码 */ if (len <= 11) { unsigned char buf[5]; if ((enclen = rdbTryIntegerEncoding((char*)s,len,buf)) > 0) { // 整数转换成功,写入 if (rdbWriteRaw(rdb,buf,enclen) == -1) return -1; // 返回字节数 return enclen; } } /* Try LZF compression - under 20 bytes it's unable to compress even * aaaaaaaaaaaaaaaaaa so skip it * * 如果字符串长度大于 20 ,并且服务器开启了 LZF 压缩, * 那么在保存字符串到数据库之前,先对字符串进行 LZF 压缩。 */ if (server.rdb_compression && len > 20) { // 尝试压缩 n = rdbSaveLzfStringObject(rdb,s,len); if (n == -1) return -1; if (n > 0) return n; /* Return value of 0 means data can't be compressed, save the old way */ } // 执行到这里,说明值 s 既不能编码为整数 // 也不能被压缩 // 那么直接将它写入到 rdb 中 /* Store verbatim */ // 写入长度 if ((n = rdbSaveLen(rdb,len)) == -1) return -1; nwritten += n; // 写入内容 if (len > 0) { if (rdbWriteRaw(rdb,s,len) == -1) return -1; nwritten += len; } return nwritten; }而在redis server中,除了非压缩的实际数据大小,还有使用各种数据结构来维护管理各种数据类型的key所消耗的内存。这两者的内存使用就是用 used_memory_human 来表示的。
RDB分析工具show出来的内存使用量是RDB文件中各种类型key解压解码后的统计分析,相当于展示的只是一个文本数据的大小。
RDB分析工具地址:https://github.com/xueqiu/rdr https://github.com/sripathikrishnan/redis-rdb-tools
简单使用:https://www.cnblogs.com/cheyunhua/p/10598181.html
综上所述:
RDB文件大小 < RDB分析工具显示的内存大小 < used_memory_human