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); ... } ……

阅读全文

Golang map数据结构接受json中的uint64数据

例如有一个json数据: 1 2 3 4 5 6 7 8 9 { "name": "小明", "money": 1111111111111111111 } 但是小明很有钱,他的钱用int64是存储不下来的,如果我们用一个结构体来接受数据就很简单,例如: 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 package main import ( "encoding/json" "fmt" ) type Info struct { Name string `json:"name"` Money uint64 `json:"money"` } func main() { info := &Info{} json.……

阅读全文

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……

阅读全文

Golang源码阅读之map

源码地址:src/runtime/map.go 描述 Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。 Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。 ……

阅读全文

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.……

阅读全文

HTTP 与 HTTPS 的区别

超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此,HTTP协议不适合传输一些敏感信息,比如:信用卡号、密码等支付信息。 为了解决HTTP协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS,为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。 基本概念 HTTP 是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。 HTTPS 是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 主要作用 建立一个信息安全通道,来保证数据传输的安全 另一种就是确认网站的真实性。 HTTP与HTTPS区别 https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。 http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。 http和https使用的是完全不同的连接方式,默认端口也不一样,前者是80,后者是443。 http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。 SSL加密方式 SSL协议既用到了对称加密也用到了非对称加密(公钥加密),在建立传输链路时,SSL首先对对称加密的密钥使用公钥进行非对称加密,链路建立好之后,SSL对传输内容使用对称加密。 对称加密 速度高,可加密内容较大,用来加密会话过程中的消息 公钥加密 加密速度较慢,但能提供更好的身份认证技术,用来加密对称加密的密钥 HTTPS工作原理 单向验证与双向验证的区别 单向验证: 指客户端验证服务器端证书,服务器并不需要验证客户端证书。 双向验证:指客户端验证服务器端证书,而服务器也需要通过CA的公钥证书来验证客户端证书。 单向认证 Https在建立Socket连接之前,需要进行握手,具体过程如下: 客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息; 服务端给客户端返回SSL协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,即公钥证书; 客户端使用服务端返回的信息验证服务器的合法性,包括: 证书是否过期; 发行服务器证书的CA是否可靠;(通过查询浏览器或本机内的CA证书) 返回的公钥是否能正确解开返回证书中的数字签名;(通过使用本机或浏览器内置的CA公钥进行解密)……

阅读全文

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.……

阅读全文