“这是我参与「第五届青训营 」伴学笔记创作活动的第 18 天”
1 Redis是什么?
1.1 需求
1、单机->集群
- 数据量增长;读写数据压力不断增加
2、提升访问速度
- Redis将数据存储到内存中,访问速度提升
1.2 Redis基本工作原理
1、redis如何保证数据不丢失
- 1)client使用java或golang从redis读取数据,通过RESP协议;
- 2)redis在读写内存之前,会产生日志AOF(append on file)文件;将日志存到硬盘中,持久化存储;如果发生服务端宕机,就读取AOF日志(操作命令),进行未执行命令的重放;
- 3)先读取RDB文件(保存redis实例的所有文件),判断是否有还未读取的AOF文件;
- 4)以此保证,每次启动redis保持状态一致;
2、redis单线程处理所有操作命令
- 排队处理命令,顺序执行;
2 Redis应用案例
2.1 连续签到
1、业务逻辑
- increase原来基础+1;
- expireAt设置过期时间;
2、string数据结构
- sds指针,左移获取元信息;右移获取value;
2.2 消息通知
1、用list作为消息队列
2、list数据结构Quicklist
- Quicklist由一个双向链表和listpack实现;
- redis为了节省内存,会在一个链表节点上存储多个数据;将其压缩到一个listpack;
3、listpack数据结构
- 其中两个信息,tot-bytes整体长度,num-elements,元素个数,进行地址切割取出每个元素;
2.3 计数
1、哈希结构存储
- 将信息放在redis,提高读取速度;
- 写的时候,一次redis连接,使用pipeline一次写入多个用户信息,减少网络交互的,提高效率;
2、Hash数据结构list
- 当一个槽位上的链过于长时(哈希冲突),效率也低,此时会进行槽位的扩容,会发生rehash;
- 扩容同时也需要保持正常响应redis;
1、rehash
- ht[0]指向原来的hash table;用户还是访问这个,当访问到某一个数据时,顺便完成数据迁移;一段时间后,就完成全部数据迁移;
- ht[1]指向新的hash table;
2.4 排行榜
1、业务逻辑
- 如果是mysql就需要维护一个百万数量级的表单,当用户查询自己的排名时,开始遍历;效率低;
- 且当数据发生变更,要重新维护排序;服务器会挂;
- 适合redis的zset数据结构,用来实现;
2、zset数据结构 zskiplist
- 跳表,比如快速的找到7
- 跳表+dict;图中的dict;
- 通过跳表找到了该元素,知道key对应的分数,key-value;
- backward就可以快速实现倒排;
- 注意图中socre分数排序;
2.5 限流
- 1)防止脚本文件;
- 2)保护服务器负载;
- 3)使用key-value;
2.6 分布式锁
- redis的setnx的实现,有两个特性前提:
- 1)redis是单线程执行命令;
- 2)setnx只有未设置过才能成功;
- setnx并不能一定保证高并发安全;
- 1)业务超时解锁,导致并发问题;业务执行时间超过锁超时时间;
- 2)redis主备切换临界点问题。主备切换后,A持有的锁还未同步到新的主节点,B可在新主节点获取锁;
- 3)redis集群脑裂,导致出现多个主节点;