1. 什么是Redis
- 内存型数据库,对数据读写都在内存中完成,读写速度快
- 有多种数据类型来支持不同的业务场景
- 执行命令由单线程负责,不存在并发竞争
2. 为什么用Redis作为MySQL的缓存
- 因为redis具备高性能
- 用户第一次访问mysql中的数据比较慢,因为是从硬盘上读取的,之后将用户访问的数据缓存在redis中,下次一次再访问就可以直接从缓存中获取,速度快
- 因为redis具备高并发
- 单台设备redis的qps是mysql的10倍,直接访问 Redis 能够承受的请求是远远大于直接访问 MySQL 的
3. Redis数据结构
3.1 String
- value最多容纳数据长度是512M
- String 类型的底层的数据结构实现主要是 int 和 SDS(简单动态字符串)
- SDS可以保存本文数据和二进制数据
- 获取字符串长度的时间复杂度是O(1)
- redis的SDS API是安全的,拼接字符串不会造成缓冲区溢出
- 应用场景:
- 缓存对象
- 直接缓存整个对象的 JSON,如:`SET user:1 ‘{“name”:“xiaolin”, “age”:18}’
- 采用将 key 进行分离为 user:ID:属性,采用 MSET 存储,用 MGET 获取各属性值,如:
MSET user:1:name xiaolin user:1:age 18 user:2:name xiaomei user:2:age 20
- 常规计数
- 因为redis处理命令是单线程,所以执行命令的过程也是原子的,适合计数场景
- 分布式锁:
- 如果 key 不存在,则显示插入成功,可以用来表示加锁成功;
- 如果 key 存在,则会显示插入失败,可以用来表示加锁失败。
- 还会对分布式锁加上过期时间,如:
SET lock_key unique_value NX PX 10000
- 共享session信息:
- 在分布式系统中,借助 Redis 对这些 Session 信息进行统一的存储和管理,这样无论请求发送到那台服务器,服务器都会去同一个 Redis 获取相关的 Session 信息,这样就解决了分布式系统下 Session 存储的问题
3.2 List
- 按照插入顺序排序,可以从头部或尾部向 List 列表添加元素。每个列表支持超过40亿个元素
- List 类型的底层数据结构是由双向链表或压缩列表实现的
- 如果列表的元素个数小于
512
个,列表每个元素的值都小于 64
字节,使用压缩列表 - 否则使用双向链表
- 在redis 3.2后,统一使用 quicklist 实现
- 应用场景:
- 消息队列
- 消息队列在存取消息时,必须要满足三个需求,分别是消息保序、处理重复的消息和保证消息可靠性。
- 消息保序:List 本身就是按先进先出的顺序对数据进行存取的
- 处理重复消息:
- 要满足两个要求:一个是每个消息都有一个全局ID,另一个是消费者要记录处理过的ID,当收到一条消息后可以通过对比ID来判断消息是否被处理
- 我们需要自行为每个消息生成一个全局唯一ID
- 消息可靠性:出现故障能恢复
- List 类型提供了
BRPOPLPUSH
命令,作用是让消费者程序从一个 List 中读取消息,同时,Redis 会把这个消息再插入到另一个 List(可以叫作备份 List)留存。
- 缺点:List 不支持多个消费者消费同一条消息,因为一旦消费者拉取一条消息后,这条消息就从 List 中删除了,无法被其它消费者再次消费。
3.3 Hash
- Hash 特别适合用于存储对象。
- 底层数据结构是由压缩列表或哈希表实现的
- 如果哈希类型元素个数小于
512
个,所有值小于 64
字节,使用压缩列表 - 否则使用哈希表
- redis 7.0中,压缩列表由 listpack 代替
- 应用场景:
- 缓存对象
- Hash 类型的 (key,field, value) 的结构与对象的(对象id, 属性, 值)的结构相似
- 购物车
- 以用户 id 为 key,商品 id 为 field,商品数量为 value,恰好构成了购物车的3个要素
3.4 Set
- 无序并唯一,它的存储顺序不会按照插入的先后顺序进行存储。
- Set 类型除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集。
- 底层数据结构是由哈希表或整数集合实现的
- 如果集合中的元素都是整数且元素个数小于 512,使用整数集合
- 否则使用哈希表
- 应用场景:
- 点赞
- Set 类型可以保证一个用户只能点一个赞,这里举例子一个场景,key 是文章id,value 是用户id
- 共同关注
- Set 类型支持交集运算,所以可以用来计算共同关注的好友、公众号等。key 可以是用户id,value 则是已关注的公众号的id。
- 抽奖活动
- 存储某活动中中奖的用户名 ,Set 类型因为有去重功能,可以保证同一个用户不会中奖两次。key为抽奖活动名,value为员工名称。
3.5 ZSet
- 每个存储元素相当于有两个值组成的,一个是有序集合的元素值,一个是排序值。
- 集合不能有重复成员,分值可以重复,有序集合中的元素可以排序
- 底层数据结构是由压缩列表或跳表实现的
- 如果有序集合的元素个数小于
128
个,并且每个元素的值小于 64
字节时,使用压缩列表 - 否则使用跳表
- redis 7.0 压缩列表替换为 listpack
- 应用场景:
- 排行榜
- 例如学生成绩的排名榜、游戏积分排行榜、视频播放排名、电商系统中商品的销量排名等
- 电话、姓名排序
3.6 BitMap
- 位图,是一串连续的二进制数组(0和1),可以通过偏移量(offset)定位元素。BitMap通过最小的单位bit来进行
0|1
的设置,表示某个元素的值或者状态,时间复杂度为O(1)。 - 底层数据结构用string类型来实现
- 应用场景:
- 签到统计:我们只用记录签到(1)或未签到(0)
- 判断用户登录状态
3.7 HyperLogLog
- HyperLogLog 提供不精确的去重计数,是基于概率完成的,不是非常准确
- 优点:在输入元素的数量或者体积非常非常大时,计算基数所需的内存空间总是固定的、并且是很小的(非常节省空间)
- 应用场景:
3.8 GEO
- 主要用于存储地理位置信息,并对存储的信息进行操作
- 直接使用了 Sorted Set 集合类型作为底层数据结构
- 应用场景:
3.9 Stream
- 专门为消息队列设计的数据类型,它支持消息的持久化、支持自动生成全局唯一 ID、支持 ack 确认消息的模式、支持消费组模式等,让消息队列更加的稳定和可靠。
- 应用场景: