Redis数据类型
键设计
键命名规范:建议使用冒号分隔,如 user:1001:info,这样在 Redis 客户端中查看时层次更清晰
String

缓存对象
使用 String 来缓存对象有两种方式:
- 直接缓存整个对象的 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 处理命令是单线程,所以执行命令的过程是原子的。因此 String 数据类型适合计数场景,比如计算访问次数、点赞、转发、库存数量等等。
分布式锁
SET 命令有个 NX 参数可以实现「key不存在才插入」,可以用它来实现分布式锁:
上锁

释放锁

为什么需要lockvalue?因为A线程还没执行完,锁过期,B线程过来拿到锁,A线程执行完删除锁就把B的锁删了;通过获取锁时从ThreadLocal存储的值和Redis中的lockvalue比较,自己线程的锁才删
Redisson
1. 看门狗机制核心原理
- 在获取锁成功后,创建一个定时任务
- 定时任务每隔 10 秒(默认超时时间的 1/3)执行一次
- 通过 Lua 脚本检查锁是否还存在并延长过期时间
2. 可重入锁原理
数据结构设计,用Hash:

加锁:

解锁:

List

基本操作
1 | 将一个或多个值value插入到key列表的表头(最左边),最后的值在最前面 |
- 分页查询
- 最新N条记录
以上都可以LRANGE实现
1 | 返回列表key中指定区间内的元素,区间以偏移量start和stop指定,从0开始 |
1 | 从key列表表头弹出一个元素,没有就阻塞timeout秒超时(timeout=0是一直阻塞) |
消息队列
利用List的阻塞式获取可以实现消息队列

消息保序:使用 LPUSH;
阻塞读取:使用 BRPOP;
重复消息处理:生产者自行实现全局唯一 ID;
消息的可靠性:使用 BRPOPLPUSH
由于网络波动,BRPOP了可能还没执行客户端就挂了,可以用BRPOPLPUSH(这个命令的作用是让消费者程序从一个 List 中读取消息,同时,Redis 会把这个消息再插入到另一个 List(可以叫作备份 List)留存),重启时,会先从备份 List获取数据消费
Stream
专门用来实现消息队列的
发布订阅
Redis 的发布订阅(Pub/Sub)是一种消息通信模式,用于解耦消息发送者和接收者,实现一对多的实时消息通知
使用专业的MQ工具的话,Stream和发布订阅就不要用了
Hash

一般对象用 String + Json 存储,对象中某些频繁变化的属性可以考虑抽出来用 Hash 类型存储
1 | # 语法:HSET key field1 value1 field2 value2 ... |
Set

1 | uid:1 用户对文章 article:1 点赞 |
Set 类型支持交集运算,所以可以用来计算共同关注的好友、公众号
Zset
Zset 类型(有序集合类型)相比于 Set 类型多了一个排序属性 score(分值)
1 | arcticle:1 文章获得了200个赞 |
BitMap
Bitmap,即位图,是一串连续的二进制数组(0和1),可以通过偏移量(offset)定位元素。BitMap通过最小的单位bit来进行0|1的设置,表示某个元素的值或者状态,时间复杂度为O(1)

1 | 设置值,其中value只能是 0 和 1 |
Bitmap 类型非常适合二值状态统计的场景
GEO
执行下面的这个命令,就可以把 ID 号为 33 的车辆的当前经纬度位置存入 GEO 集合中:
1 | GEOADD cars:locations 116.034579 39.030452 33 |
当用户想要寻找自己附近的网约车时,LBS 应用就可以使用 GEORADIUS 命令。
例如,LBS 应用执行下面的命令时,Redis 会根据输入的用户的经纬度信息(116.054579,39.030452 ),查找以这个经纬度为中心的 5 公里内的车辆信息,并返回给 LBS 应用。
1 | GEORADIUS cars:locations 116.054579 39.030452 5 km ASC COUNT 10 |
Pipeline
多条命令一次打包,减少网络IO
通过redisTemplate.executePipelined执行批量操作:

注意:
- 注意 Pipeline 不支持原子性:它只负责打包发送,执行过程中可能被其他客户端的命令“插队”。如果某条命令失败,其后续命令仍会继续执行。对原子性有强要求,请使用 Lua 脚本或事务。
- Redis Cluster 的使用限制:在 Redis 集群(Cluster)模式下使用 Pipeline 时,请确保 Pipeline 中的所有命令都操作同一个 slot 的 key,否则会报错。
