技术分享 《大话redis设计实现》

        这次又给朋友公司 (Naver) 做了一次技术分享,主题是《大话redis设计实现》 ,  里面的内容来自 学习《redis设计与实现》 和 阅读redis源码的心得。   话说, 我用redis的历史也有些时间了, 应该有4、5 年了。  运维方面从最开始单机扩展成主从,从单主从到proxy方案,现在用redis官方的cluster方案。 至于开发方面,那些数据类型差不多都用个遍。

        对于Redis的开发实现细节还是有些不清,记得年前起就一直看redis源码,多少有些心得。趁着这个机会正好分享下。   内容涵盖了几个方面, 协议, 数据结构, 事件, pubsub,  brpop ,rdb ,aof , 事务, 主从 。


废话不多说了, 直接帖内容及地址了。 有时间我会把这PPT转述成文章。 没有视频, 上次讲python gil的时候,说好要录制视频的,结果不幸出了点问题。 


#xiaorui.cc
大话redis设计实现
1. 大话Redis设计实现 “峰云就她了” - xiaorui.cc v 2016.6.5
2. redis协议 set name fengyun *3rn $3rn SETrn $4rn namern $7rn fengyunrn if OK: +OKrn else: -1rn get name *2rn $3rn GETrn $4rn namern if OK: $7rn fengyunrn else: $-1rn 消息体数 字节数
3. 数据结构 string (sds) list (deque) hash (hash table) set (intset + dict) zset (skip list + hash table)
4. String (sds) struct sdshdr { int len; int free; char buf[]; }; 获取字符串长度, 常数复杂度 增长时空间预分配 惰性回收 shshdr free 0 len 5 buf R E D I S O
5. Hash table 通过渐进式rehash解决kv过多造成服务阻塞 流程: 给ht[1]分配至少2倍于ht[0]的空间 将ht[0]数据分批迁移到ht[1] 清空ht[0], 将ht[0]指针指向ht[1],ht[1]指针指向ht[0] 每次rehash 100个桶 渐进式rehash del find update in ht[0] and ht[1] insert in ht[1]
6. dictht table size 4 sizemask 3 userd 2 dict type … ht rehashidx -1 dictht table size 8 sizemask 7 userd dictEntry*[4] 0 1 2 3 dictEntry*[8] … 4 5 … dictEntry k6 v6 dictEntry k2 v2 dictEntry kx vx dictEntry k3 v3 null null null null ht[O] ht[1] null null
7. redisDB dict expires watch … dict “string” “list” “hash” “set” … server … db … string object List object Hash object Set object “this is string” “t1” “t2” “null” name xiaorui age 18 a b c d … 0 1 2 3 … RedisDB 内部结构
8. Redis event 事件类型 时间类型 (serverCron aof rdb expires) 文件类型 (client reuqest repl) 串行 epoll_create , epoll_ctl , epoll_wait 先文件类型, 再时间类型 (100ms cs)
9. io事件 io事件 io事件 io事件 定时器 IO事件表 定时事件表 定时器 定时器 event loop
10. Redis Rdb RDB是Redis物化数据,保证宕机恢复的一个 手段(会丢一部分最新数据) 每个Redis实例只会存一份rdb文件 可以通过Save以及BGSAVE 来调用 二进制文件, lzf
11. “redis rdb” “version” “Data” “Data” “Data” … EOF CHECKSUM “expireTime” “value type” “key” “value” RDB Format
12. rdbSave 遍历每个db, 遍历每个db的dict, 获取每一个dictEntry 获取Key之后查询expire, 如过期, 就舍弃 将数据key, value, type, expiretime 等写入文件 计算checksum, 通过rename交换旧的RDB文件
13. rdbLoad 遍历RDB文件的每一条数据 读取key, value, expiretime等信息,插入dict字典以及expire字典 校验checksum
14. Redis Aof 类似于BINLOG机制, 可以做到不丢数据 how ? 每次数据操作都会调用flushAppendOnlyFile来刷新aof 每次操作都需要fsync, 前台线程阻塞 aof的内容就是redis标准协议 *3rn$5rnHMGETrn$5rnHENRYrn$10rnxiaorui.ccrn
15. Aof 意义 ? 将同一个key的反复操作,全部转为最后的值或multi集合 ( < 64) no-appendfsync-on-rewrite yes 正导出rdb快照的过程中,要不要停止同步fsync auto-aof-rewrite-min-size 3000mb aof文件,至少超过3000M时, 再执行aof重写 auto-aof-rewrite-percentage 80 aof文件大小比起上次重写时的大小,增长率80%时,执行aof重写
16. AOF ReWrite的实现: Fork一个子进程进行重写 打开一个tmp aof文件准备写入 遍历每个DB 及DICT中的每对key value, 同时忽略过期键 以协议命令的方式写入tmp aof文件中 主进程中新的操作内容写到aof rewrite buffer中 子进程重写完后, 向主进程发送信号, 主进程serverCron中将buffer的内容刷到新的 aof文件中 最后以rename的方式替换旧的aof文件
17. brpop/blpop redisDB dict blocking_keys expires_keys watch_keys … client blocking_keys xiaorui hello … client fd client fd client fd interpreter brpop/blpop
18. pubsub pubsub_channels channel_1 hello worker … “client_fd” “client_fd” “client_fd” producer pub consumer sub redisServer pubsub_channels pubsub_patterns pubsub_patterns hello_* worker_*
19. expire realize 懒惰清理 当发生读写的时候, 会检查是否过期 主动清理 定期轮询expire dict中的键是否过期 slave屏蔽懒惰和主动清理, 只等待psync .
20. Expires Dict 0 1 2 D key value next blog time RedisDB expires_keys … expire realize
21. watch multi watch 乐观锁 multi 原子性 流程 事务标记开始 命令入队 事务执行 无rallback 、 无Lock
22. command 事务状态? exec,discard,watch,multi push cmd queue return queued run command 返回执行结果 否 否 是 是 if watch: do cas 客户端
23. 主从同步 fork bgsave ? fork child block ? bgsave block ? psync vs fullsync 区别 ? run_id标识slave, 为毛不适用fd ? offset replication backlog vs replication buffer 两个slave同时fullsync , 共用一个RDB及buffer
24. 连接主机 psync runid offset backlog runid offset 返回 event + runid + offset 等待接收事件 bgsave Transfer RDB no yes 返回 event 等待接收事件 传输backlog repl buffer transfer
25. 改进 transfer rdb, copy效率| 断连 | 落地 sendfile | 断点 | 内存 expires keyes, random check 二叉堆 ?
26. “Q & A” – 2016. 06. 05

在线PDF分享:

http://xiaorui.cc/rediscode.pdf

在线PPT分享:

ppt扔到slideshare里了,需要翻墙才可以看到的。 http://www.slideshare.net/rfyiamcool/redis-62948731


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc

1 Response

  1. victor 2016年6月13日 / 下午5:00

    点了4个

发表评论

电子邮件地址不会被公开。 必填项已用*标注