首先,您应该始终详细说明此类问题的设置,因为内存布局取决于操作系统,内存分配器,平台和Redis版本.
在带有Redis 2.4的64位Linux机器上,1M项8字节键的容量为87 MB.
与密钥的大小相比似乎很多,但是支持对其项目的有效访问的任何动态数据结构都涉及开销.您的物品越小,开销越大.
使用Redis,使用单独的链接哈希表实现大型集合.每个条目由以下结构表示:
typedef struct dictEntry {
void *key;
void *val;
struct dictEntry *next;
} dictEntry;
Run Code Online (Sandbox Code Playgroud)
因为内存分配器(jemalloc)不支持24字节类,所以使用32个字节.在这个结构中,val被设置为NULL(这是一个集合),并且键指向一个对象,定义如下:
typedef struct redisObject {
unsigned type:4;
unsigned storage:2; /* REDIS_VM_MEMORY or REDIS_VM_SWAPPING */
unsigned encoding:4;
unsigned lru:22; /* lru time (relative to server.lruclock) */
int refcount;
void *ptr;
} robj;
Run Code Online (Sandbox Code Playgroud)
这种结构只需16个字节.它指向关键数据本身,由这个可变长度结构表示:
struct sdshdr {
int len;
int free;
char buf[];
};
Run Code Online (Sandbox Code Playgroud)
密钥是8个字节,加上一个nul char,因此每个密钥的大小为17个字节.下一个分配类是带有jemalloc的32个字节,因此这个结构需要32个字节.
总而言之,每件物品都要花费:32 + 16 + 32 = 80字节.它们有1M个.为哈希表本身添加一些空间(包含至少1M指向dictEntry结构的指针),你得到的结果非常接近我们可以在这个平台上测量的87 MB.
优化大型内存的占用空间并非易事.当集合很小(默认情况下少于512个项目)并且键实际上是整数时,Redis会执行优化.在此处查看更多信息.
一种可能的优化是增加set-max-intset-entries参数,并将该组拆分为多个部分.例如,可以对项目键进行散列以在各种集合上分发项目.而不仅仅是myset,你有myset:0,myset:1,myset:2 ... myset:n.要检查给定项目是否是设置,在密钥上计算哈希值以找到正确的myset:X条目,然后检查此特定条目.目的是使所有这些集合的大小保持在set-max-intset-entries参数之下,以便从内存优化中受益.当然,它使得在集合上完成的所有操作更加复杂,因此它实际上是复杂性和内存占用之间的权衡.
归档时间: |
|
查看次数: |
1632 次 |
最近记录: |