第1篇 基础和应用篇 1
1.1授人以鱼不如授人以渔 1
1.1.1由Redis面试想到的 1
1.1.2本书的内容范围 2
1.1.3 Redis可以做什么 3
1.1.4小结 3
1.1.5扩展阅读 4
1.2万丈高楼平地起——Redis基础数据结构 4
1.2.1 Redis的安装 5
1.2.2 5种基础数据结构 6
1.2.3容器型数据结构的通用规则 17
1.2.4过期时间 17
1.2.5思考&作业 17
1.3千帆竞发——分布式锁 18
1.3.1分布式锁的奥义 18
1.3.2超时问题 20
1.3.3可重入性 21
1.3.4思考&作业 24
1.4缓兵之计——延时队列 24
1.4.1异步消息队列 24
1.4.2队列空了怎么办 26
1.4.3阻塞读 26
1.4.4空闲连接自动断开 26
1.4.5锁冲突处理 27
1.4.6延时队列的实现 27
1.4.7进一步优化 30
1.4.8思考&作业 31
1.5节衣缩食——位图 31
1.5.1基本用法 31
1.5.2统计和查找 34
1.5.3魔术指令bitfield 35
1.5.4思考&作业 38
1.6四两拨千斤——HyperLogLog 38
1.6.1使用方法 39
1.6.2 pfadd中的pf是什么意思 41
1.6.3 pfmerge适合的场合 42
1.6.4注意事项 42
1.6.5 HyperLogLog实现原理 42
1.6.6 pf的内存占用为什么是12KB 49
1.6.7思考&作业 50
1.7层峦叠嶂——布隆过滤器 50
1.7.1布隆过滤器是什么 51
1.7.2 Redis中的布隆过滤器 51
1.7.3布隆过滤器的基本用法 52
1.7.4注意事项 59
1.7.5布隆过滤器的原理 60
1.7.6空间占用估计 61
1.7.7实际元素超出时,误判率会怎样变化 62
1.7.8用不上Redis 4.0怎么办 63
1.7.9布隆过滤器的其他应用 63
1.8断尾求生——简单限流 64
1.8.1如何使用Redis来实现简单限流策略 64
1.8.2解决方案 65
1.8.3小结 67
1.9一毛不拔——漏斗限流 68
1.9.1 Redis-Cell 71
1.9.2思考&作业 72
1.9.3扩展阅读:Redis-Cell作者介绍 72
1.10近水楼台——GeoHash 73
1.10.1用数据库来算附近的人 73
1.10.2 GeoHash算法 74
1.10.3 Geo指令的基本用法 75
1.10.4注意事项 78
1.11大海捞针——scan 79
1.11.1 scan基本用法 80
1.11.2字典的结构 82
1.11.3 scan遍历顺序 82
1.11.4字典扩容 83
1.11.5对比扩容、缩容前后的遍历顺序 84
1.11.6渐进式rehash 85
1.11.7更多的scan指令 85
1.11.8大key扫描 85
第2篇 原理篇 87
2.1鞭辟入里——线程IO模型 87
2.1.1非阻塞IO 87
2.1.2事件轮询(多路复用) 88
2.1.3指令队列 90
2.1.4响应队列 90
2.1.5定时任务 90
2.1.6扩展阅读 90
2.2交头接耳——通信协议 90
2.2.1 RESP 91
2.2.2客户端→服务器 92
2.2.3服务器→客户端 92
2.2.4小结 95
2.2.5扩展阅读 95
2.3未雨绸缪——持久化 95
2.3.1快照原理 96
2.3.2 fork(多进程) 96
2.3.3 AOF原理 97
2.3.4 AOF重写 98
2.3.5 fsync 98
2.3.6运维 98
2.3.7 Redis 4.0混合持久化 99
2.3.8思考&作业 100
2.4雷厉风行——管道 100
2.4.1 Redis的消息交互 100
2.4.2管道压力测试 101
2.4.3深入理解管道本质 102
2.4.4小结 104
2.5同舟共济——事务 104
2.5.1 Redis事务的基本用法 104
2.5.2原子性 105
2.5.3 discard(丢弃) 106
2.5.4优化 106
2.5.5 watch 107
2.5.6注意事项 108
2.5.7思考&作业 110
2.6小道消息—— PubSub 110
2.6.1消息多播 110
2.6.2 PubSub 111
2.6.3模式订阅 113
2.6.4消息结构 114
2.6.5 PubSub的缺点 115
2.6.6补充 115
2.7开源节流——小对象压缩 115
2.7.1 32bit VS 64bit 116
2.7.2小对象压缩存储(ziplist) 116
2.7.3内存回收机制 120
2.7.4内存分配算法 120
第3篇 集群篇 122
3.1有备无患——主从同步 122
3.1.1 CAP原理 122
3.1.2最终一致 123
3.1.3主从同步与从从同步 123
3.1.4增量同步 124
3.1.5快照同步 124
3.1.6增加从节点 125
3.1.7无盘复制 125
3.1.8 wait指令 125
3.1.9小结 126
3.2李代桃僵——Sentinel 126
3.2.1消息丢失 128
3.2.2 Sentinel基本用法 128
3.2.3思考&作业 129
3.3分而治之——Codis 130
3.3.1 Codis分片原理 131
3.3.2不同的Codis实例之间槽位关系如何同步 132
3.3.3扩容 132
3.3.4自动均衡 133
3.3.5 Codis的代价 133
3.3.6 Codis的优点 134
3.3.7 mget指令的操作过程 134
3.3.8架构变迁 135
3.3.9 Codis的尴尬 135
3.3.10 Codis的后台管理 136
3.3.11思考&作业 136
3.4众志成城——Cluster 137
3.4.1槽位定位算法 138
3.4.2跳转 138
3.4.3迁移 138
3.4.4容错 140
3.4.5网络抖动 140
3.4.6可能下线(PFAIL)与确定下线(Fail) 141
3.4.7 Cluster基本用法 141
3.4.8槽位迁移感知 142
3.4.9集群变更感知 143
3.4.10思考&作业 143
第4篇 拓展篇 144
4.1耳听八方——Stream 144
4.1.1消息ID 145
4.1.2消息内容 145
4.1.3增删改查 145
4.1.4独立消费 147
4.1.5创建消费组 148
4.1.6消费 150
4.1.7 Stream消息太多怎么办 152
4.1.8消息如果忘记ack会怎样 153
4.1.9 PEL如何避免消息丢失 153
4.1.10 Stream的高可用 153
4.1.11分区Partition 154
4.1.12小结 154
4.2无所不知——Info指令 154
4.2.1 Redis每秒执行多少次指令 155
4.2.2 Redis连接了多少客户端 156
4.2.3 Redis内存占用多大 156
4.2.4复制积压缓冲区多大 157
4.2.5思考&作业 158
4.3拾遗补漏——再谈分布式锁 158
4.3.1 Redlock算法 158
4.3.2 Redlock使用场景 159
4.3.3扩展阅读:redlock-py的作者 160
4.4朝生暮死——过期策略 160
4.4.1过期的key集合 160
4.4.2定时扫描策略 160
4.4.3从节点的过期策略 161
4.5优胜劣汰——LRU 162
4.5.1 LRU算法 163
4.5.2近似LRU算法 164
4.5.3思考&作业 165
4.6平波缓进——懒惰删除 165
4.6.1 Redis为什么使用懒惰删除 165
4.6.2 flush 166
4.6.3异步队列 166
4.6.4 AOF Sync也很慢 166
4.6.5更多异步删除点 166
4.7妙手仁心——优雅地使用Jedis 167
4.7.1重试 171
4.7.2思考&作业 172
4.8居安思危——保护Redis 172
4.8.1指令安全 172
4.8.2端口安全 173
4.8.3 Lua脚本安全 174
4.8.4 SSL代理 174
4.8.5小结 174
4.9隔墙有耳——Redis安全通信 175
4.9.1 spiped原理 176
4.9.2 spiped使用入门 176
4.9.3思考&作业 179
第5篇 源码篇 180
5.1丝分缕析——探索“字符串”内部 180
5.1.1 embstr VS raw 181
5.1.2扩容策略 184
5.1.3思考&作业 184
5.2循序渐进——探索“字典”内部 184
5.2.1 dict内部结构 184
5.2.2渐进式rehash 186
5.2.3查找过程 187
5.2.4 hash函数 188
5.2.5 hash攻击 188
5.2.6扩容条件 188
5.2.7缩容条件 189
5.2.8 set的结构 189
5.2.9思考&作业 189
5.3挨肩迭背——探索“压缩列表”内部 190
5.3.1增加元素 192
5.3.2级联更新 192
5.3.3 intset小整数集合 194
5.3.4思考&作业 195
5.4风驰电掣——探索“快速列表”内部 195
5.4.1每个ziplist存多少元素 197
5.4.2压缩深度 198
5.5凌波微步——探索“跳跃列表”内部 198
5.5.1基本结构 199
5.5.2查找过程 199
5.5.3随机层数 200
5.5.4插入过程 201
5.5.5删除过程 202
5.5.6更新过程 203
5.5.7如果score值都一样呢 203
5.5.8元素排名是怎么算出来的 203
5.5.9思考&作业 204
5.5.10题外话 204
5.6破旧立新——探索“紧凑列表”内部 205
5.6.1级联更新 207
5.6.2取代ziplist尚需时日 207
5.6.3思考&作业 207
5.7金枝玉叶——探索“基数树”内部 207
5.7.1应用 208
5.7.2结构 210
5.7.3思考&作业 213
5.8精益求精——LFU VS LRU 213
5.8.1 Redis对象的热度 213
5.8.2 LRU模式 213
5.8.3 LFU模式 214
5.8.4为什么Redis要缓存系统时间戳 217
5.8.5 Redis为什么在获取lruclock时使用原子操作 217
5.8.6如何打开LFU模式 218
5.8.7思考&作业 218
5.9如履薄冰——懒惰删除的巨大牺牲 218
5.9.1懒惰删除的最初实现不是异步线程 219
5.9.2异步线程方案其实也相当复杂 219
5.9.3异步删除的实现 221
5.9.4队列安全 224
5.9.5思考&作业 225
5.10跋山涉水——深入字典遍历 225
5.10.1一边遍历一边修改 226
5.10.2重复遍历的难题 227
5.10.3迭代器的结构 227
5.10.4迭代过程 229
5.10.5迭代器的选择 231
5.10.6思考&作业 232