分类 Redis 中的文章

幂次定律在Redis中的应用

幂次定律 如果某件事的发生频率和它的某个属性成幂关系,那么这个频率就可以称之为符合幂次定律。幂次定律的表现是少数几个事件的发生频率占了整个发生频率的大部分, 而其余的大多数事件只占整个发生频率的一个小部分。幂次定律 Redis中的应用 在Redis中的跳表内容中有一个zslRandomLevel函数,返回一个随机的层级 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 /* Returns a random level for the new skiplist node we are going to create. * The return value of this function is between 1 and ZSKIPLIST_MAXLEVEL * (both inclusive), with a powerlaw-alike distribution where higher * levels are less likely to be returned.……

阅读全文

redis lua script注意点

脚本死循环 Redis 的指令执行是个单线程,这个单线程还要执行来自客户端的 lua 脚本。如果 lua 脚本中来一个死循环,在脚本没有对 Redis 的内部数据状态进行修改时,可以使用script kill指令用于动态杀死一个执行时间超时的 lua 脚本。因为 Redis 不允许 script kill 破坏脚本执行的原子性。比如脚本内部使用了 redis.call(“set”, key, value) 修改了内部的数据,那么 script kill 执行时服务器会返回错误。 Script Kill 的原理 lua 脚本引擎功能太强大了,它提供了各式各样的钩子函数,它允许在内部虚拟机执行指令时运行钩子代码。比如每执行 N 条指令执行一次某个钩子函数,Redis 正是使用了这个钩子函数。 1 2 3 4 5 6 7 8 9 10 11 12 13 void evalGenericCommand(client *c, int evalsha) { ... // lua引擎每执行10w条指令,执行一次钩子函数 luaMaskCountHook lua_sethook(lua,luaMaskCountHook,LUA_MASKCOUNT,100000); ... } ……

阅读全文

Redis源码阅读之quicklist

数据结构 quicklistNode 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 /* quicklistNode is a 32 byte struct describing a ziplist for a quicklist. * We use bit fields keep the quicklistNode at 32 bytes. * count: 16 bits, max 65536 (max zl bytes is 65k, so max count actually < 32k).……

阅读全文

Redis字典扩张算法

源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 /* This is the initial size of every hash table */ #define DICT_HT_INITIAL_SIZE 4 /* Our hash table capability is a power of two */ static unsigned long _dictNextPower(unsigned long size) { unsigned long i = DICT_HT_INITIAL_SIZE; if (size >= LONG_MAX) return LONG_MAX + 1LU; while(1) { if (i >= size) return i; i *= 2; } } 结论 Redis的dict会从4开始扩张,最大到达LONG_MAX + 1LU……

阅读全文

Redis源码阅读之动态字符串

数据结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 typedef char *sds; /* Note: sdshdr5 is never used, we just access the flags byte directly.……

阅读全文

Redis源码阅读之内存分配

zmalloc是什么 zmalloc是redis内存分配的基本操作,相当于包了一层malloc的操作,分配出来的内存不只是裸露的 API 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 void *zmalloc(size_t size); void *zcalloc(size_t size); void *zrealloc(void *ptr, size_t size); void zfree(void *ptr); char *zstrdup(const char *s); size_t zmalloc_used_memory(void); void zmalloc_set_oom_handler(void (*oom_handler)(size_t)); size_t zmalloc_get_rss(void); int zmalloc_get_allocator_info(size_t *allocated, size_t *active, size_t *resident); void set_jemalloc_bg_thread(int enable); int jemalloc_purge(); size_t zmalloc_get_private_dirty(long pid); size_t zmalloc_get_smap_bytes_by_field(char *field, long pid); size_t zmalloc_get_memory_size(void); void zlibc_free(void *ptr); 内存分配zmalloc,zcalloc 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 void *zmalloc(size_t size) { void *ptr = malloc(size+PREFIX_SIZE); if (!……

阅读全文

Redis源码阅读之字典(二)——Rehash

历史文章 Redis源码阅读之字典(一) Redis Rehash是什么? 在我们日常使用redis的过程中,随着key不断的增加,dict的size也在不断的增加,当dict.used == dict.size或者used*100/size < HASHTABLE_MIN_FILL,HASHTABLE_MIN_FILL一般为10,也就是说,要么容量不够,要么容量使用率小于10%了,就会调用dictExpand进行重新分配内存,这个时候就会触发rehash了。但是rehash不行一次性就操作完成了,试想一下,如果一个dict里面含有数百万的key,rehash一次可能会很久,就可能造成服务假死的情况。所以rehashing是一个长时间的过程,每一次可能只进行几个key的迁移。 哪些操作会触发rehashing的step dictRehashMilliseconds redis server的定时任务会去执行dictRehashMilliseconds,但是都是传入的ms==1,主要是rehashing一下redis的dict和expired相关的键 dictAddRaw 在给dict增加key的时候,新增的key会直接放入dict.ht[1]中 dictGenericDelete 删除key时 dictFind 查找key dictGetRandomKey 和 dictGetSomeKeys 获取随机key dictScan 遍历dict 每次rehash的过程 源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 /* Performs N steps of incremental rehashing.……

阅读全文

Redis源码阅读-dict

数据结构 字典的基本单元——dictEntry 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 typedef struct dictEntry { void *key; union { void *val; uint64_t u64; int64_t s64; double d; } v; struct dictEntry *next; } dictEntry; dictEntry是Redis中的哈希表数据接口的基本单元,有一个指向key的指针,还有一个联合体v,代表的是字典的值,它可以是一个数字(浮点或者有符号整型或者无符号整型),还有一个next字段指向下一个dictEntry的指针。说明了一个问题,dictEntry其实是一个链表节点。 哈希表——dictht 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 /* This is our hash table structure.……

阅读全文

Redis源码阅读之字典(一)

数据结构 字典的基本单元——dictEntry 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 typedef struct dictEntry { void *key; union { void *val; uint64_t u64; int64_t s64; double d; } v; struct dictEntry *next; } dictEntry; dictEntry是Redis中的哈希表数据接口的基本单元,有一个指向key的指针,还有一个联合体v,代表的是字典的值,它可以是一个数字(浮点或者有符号整型或者无符号整型),还有一个next字段指向下一个dictEntry的指针。说明了一个问题,dictEntry其实是一个链表节点。 哈希表——dictht 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 /* This is our hash table structure.……

阅读全文

redis源码解读--动态字符串SDSHDR

阅读源码: sds.h sds.c SDSHDR 全称 Simple Dynamic Strings Header sds char *的别名 1 2 3 typedef char *sds; sdshdr sdshdr有好几个类别,它们分别是:sdshdr5,sdshdr8,sdshdr16,sdshdr32,sdshdr64,其中sdshdr5是不使用的 源码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 /* Note: sdshdr5 is never used, we just access the flags byte directly.……

阅读全文