计算Redis容量,并不只是仅仅计算key占多少字节,value占多少字节,因为Redis为了维护自身的数据结构,也会占用部分内存,本文章简单介绍每种数据类型(String、Hash、Set、ZSet、List)占用内存量,供做Redis容量评估时使用。当然,大多数情况下,key和value就是主要占用,能解大部分问题
在看这里之前,可以先看一下底层 - 数据结构 这篇文章
jemalloc内存分配规则
jemalloc是一种通用的内存管理方法,着重于减少内存碎片和支持可伸缩的并发性,做redis容量评估前必须对jemalloc的内存分配规则有一定了解。
jemalloc基于申请内存的大小把内存分配分为三个等级:small,large,huge:
- Small Object 的size以8字节,16字节,32字节等分隔开,小于页大小;
- Large Object 的size以分页为单位,等差间隔排列,小于chunk的大小;
- Huge Object 的大小是chunk大小的整数倍。
对于64位系统,一般chunk大小为4M,页大小为4K,内存分配的具体规则如下:
jemalloc在分配内存块时会分配大于实际值的2^n的值,例如实际值时6字节,那么会分配8字节
数据类型占用量dicEntry主要包括3个指针,key、value、哈希冲突时下个指针,耗费容量为8*3=24字节,jemalloc会分配32字节的内存块dict结构88字节,jemalloc会分配 96 字节的内存块redisObjecttype(4bit)、encoding(4bit)、lru(24bit)、int(8byte)、ptr指针(8byte)。因此redisObject结构占用(4+4+24)/8 +4+8 = 16字节。key_SDSkey的长度 + 9,jemalloc分配 >= 该值的2^n的值val_SDSvalue的长度 + 9,jemalloc分配 >= 该值的2^n的值key的个数所有的key的个数bucket个数大于key的个数的2^n次方,例如key个数是2000,那么bucket=2048指针大小8 byteSDS中的主要包括两个表示长度int占用大小为8字节,redis中字符串还用“/0”表示结束占用1字节,所以 sds占用大小为9字节 + 数据长度
dict结构 这里会分配96 字节的内存块?为什么不是128?
内存划分
Redis内存占用主要可以划分为如下几个部分:
<ul>数据:Redis数据占用内存dataset.bytes包括key-value占用内存、dicEntry占用内存、SDS占用内存等。
数据所占内存 = 当前所占总内存total.allocated - 额外内存overhead.total
初始化内存:redis启动初始化时使用的内存startup.allocated,属于额外内存overhead.total的一部分。
主从复制内存:用于主从复制,属于额外内存一部分。
缓冲区内存:缓冲内存包括客户端缓冲区、复制积压缓冲区、AOF缓冲区等;其中,客户端缓冲存储客户端连接的输入输出缓冲;复制积压缓冲用于部分复制功能;AOF缓冲区用于在进行AOF重写时,保存最近的写入命令。在了解相应功能之前,不需要知道这些缓冲的细节;这部分内存由jemalloc分配,因此会统计在used_memory中。
内存碎片:内存碎片是Redis在分配、回收物理内存过程中产生的。例如,如果对数据的更改频繁,而且数据之间的大小相差很大,可能导致redis释放的空间在物理内存中并没有释放,但redis又无法有效利用,这就形成了内存碎片。
<blockquote>内存碎片率 = Redis进程占用内存 / 当前所占内存total.allocated
内存碎片涉及到内存碎片率fragmentation,该值对于查看内存是否够用比较重要:
<ul>该值一般>1,数值越大,说明内存碎片越多。
如果 |
|
|
|
相关推荐
|
|