2020年8月16日
脚本死循环 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); ... } ……
阅读全文
2020年5月27日
例如有一个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.……
阅读全文
2020年5月21日
数据结构 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).……
阅读全文
2020年5月16日
源码 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……
阅读全文
2020年5月15日
源码地址:src/runtime/map.go
描述 Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。
……
阅读全文
2020年5月10日
数据结构 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.……
阅读全文
2020年4月25日
超文本传输协议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公钥进行解密)……
阅读全文
2020年4月22日
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 (!……
阅读全文
2020年4月21日
历史文章 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.……
阅读全文
2020年4月21日
数据结构 字典的基本单元——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.……
阅读全文