String(字符串)
基本操作命令
- 数据存储
set k v
- 数据获取
get key
- 追加操作
append key 追加的字符串
- 查看字符串长度
strlen key
- 自增 1
incr key
- 自减 1
decr key
- 自增 n
incrby key n
- 自减 n
decrby key n
- 获得被截取的字符串
getrange key start end #操作方法
getrange key 0 -1 #获得完整字符串
- 替换指定位置字符串
setrange key 指定位置 用于替换的字符串
- 设置 key 并赋予过期时间
setex key 过期时间
- 设置不存在的 key
setnx k v
如果 k 已存在则设置失败
set k v
如果 k 已存在则更改 v 的值
- 同时设置多个值
mset k1 v1 k2 v2 k3 v3 …
- 同时获取多个值
mget k1 k2 k3 …
- 同时设置多个不存在的 key
msetnx k1 v1 k2 v2 … #该操作是原子性的,要么同时成功要么同时失败
- 玩些花的(储存对象)
将 key 设置成 user:{id}:{filed} 的形式来存储对象
- 获取并修改
getset k v #如果不存在值,返回并修改。如果存在,返回k的值并修改
应用场景
- 计数器
string类型的incr和decr命令的作用是将key中储存的数字值加一/减一,这两个操作具有原子性,总能安全地进行加减操作,因此可以用string类型进行计数,如微博的评论数、点赞数、分享数,抖音作品的收藏数,京东商品的销售量、评价数等。
- 分布式锁
string类型的setnx的作用是“当key不存在时,设值并返回1,当key已经存在时,不设值并返回0”,“判断key是否存在”和“设值”两个操作是原子性地执行的,因此可以用string类型作为分布式锁,返回1表示获得锁,返回0表示没有获得锁。例如,为了保证定时任务的高可用,往往会同时部署多个具备相同定时任务的服务,但是业务上只希望其中的某一台服务执行定时任务,当定时任务的时间点触发时,多个服务同时竞争一个分布式锁,获取到锁的执行定时任务,没获取到的放弃执行定时任务。定时任务执行完时通过del命令删除key即释放锁,如果担心del命令操作失败而导致锁一直未释放,可以通过expire命令给锁设置一个合理的自动过期时间,确保即使del命令失败,锁也能被释放。不过expire命令同样存在失败的可能性,如果你用的是Java语言,建议使用JedisCommands接口提供的String set(String key, String value, String nxxx, String expx, long time)方法,这个方法可以将setnx和expire原子性地执行,具体使用方式如下(相信其它语言的Redis客户端也应当提供了类似的方法)。
- 存储对象
利用JSON强大的兼容性、可读性和易用性,将对象转换为JSON字符串,再存储在string类型中,是个不错的选择,如用户信息、商品信息等。
List(列表)
基本的操作命令
- 左侧插入
lpush list 值
- 右侧插入
rpush list 值
- 获取列表区间具体值
lrange list start end
- 获取列表所有值
lrange list 0 -1
- 弹出左侧n个元素
lpop list n #n默认是1
- 弹出右侧第n元素
rpop list n #n默认是1
- 通过下标取值
lindex list 下标
- 获取列表长度
llen list
- 移除指定元素
lrem list 移除元素个数 元素 #就算将移除元素个数设置成无穷大也是有几个移除几个
- 修剪列表
ltrim list start end
- 弹出列表右侧元素并将该元素移动另一个列表中
rpoplpush 列表 元素移动到的列表
- 根据下标更改列表中的元素
lset list 下标 更改的值 #如果列表不存在该下标则会报错
- 在列表指定元素前/后插入新元素
linsert list before/after 指定元素 插入元素
应用场景
- 消息队列
list类型的lpop和rpush(或者反过来,lpush和rpop)能实现队列的功能,故而可以用Redis的list类型实现简单的点对点的消息队列。不过我不推荐在实战中这么使用,因为现在已经有Kafka、NSQ、RabbitMQ等成熟的消息队列了,它们的功能已经很完善了,除非是为了更深入地理解消息队列,不然我觉得没必要去重复造轮子。
- 排行榜
list类型的lrange命令可以分页查看队列中的数据。可将每隔一段时间计算一次的排行榜存储在list类型中,如京东每日的手机销量排行、学校每次月考学生的成绩排名、斗鱼年终盛典主播排名等,下图是酷狗音乐“K歌擂台赛”的昨日打擂金曲排行榜,每日计算一次,存储在list类型中,接口访问时,通过page和size分页获取打擂金曲。
- 最新列表
list类型的lpush命令和lrange命令能实现最新列表的功能,每次通过lpush命令往列表里插入新的元素,然后通过lrange命令读取最新的元素列表,如朋友圈的点赞列表、评论列表。
Set(集合)
基本的操作命令
- 添加元素
sadd set 元素 #set集合中不可添加相同的元素
- 查看集合全部元素
smembers set
- 查看集合中是否有指定元素
sismember set 指定元素
- 获取集合中元素个数
scard set
- 移除集合中指定元素
srem set 指定元素
- 随机查询集合中的元素
srandmember set n # n 默认为1
- 随机移除集合中的元素
spop set n # n 默认为1
- 将集合中的指定元素移动到另一个集合
smove 原set 目标set 指定元素
- 差集
sdiff set1 set2 # set1 - set2
- 交集
sinter set1 set2 # set1 和 set2 的交集
- 并集
sunion set1 set2 # set1 和 set2 的并集
应用场景
- 好友/关注/粉丝/感兴趣的人集合
set类型唯一的特点使得其适合用于存储好友/关注/粉丝/感兴趣的人集合,集合中的元素数量可能很多,每次全部取出来成本不小,set类型提供了一些很实用的命令用于直接操作这些集合,如
a. sinter命令可以获得A和B两个用户的共同好友
b. sismember命令可以判断A是否是B的好友
c. scard命令可以获取好友数量
d. 关注时,smove命令可以将B从A的粉丝集合转移到A的好友集合
Hash(哈希)
基本的操作命令
- 添加hash中的字段-元素
hset hash 字段 元素
- 查看hash中指定的字段对应的元素
hget hash 字段
- 批量添加hash中的字段-元素
hmset hash 字段1 元素1 字段2 元素2 …
- 批量查看hash中字段对应的元素
hmget hash 字段1 字段2 …
- 查看hash中所有的字段-元素
hgetall hash
- 查看hash长度
hlen hash
- 查找指定字段在hash中是否存在
hexists hash 指定字段
- 只获取所有的字段
hkeys hash
- 只获取所有的元素
hvals hash
- 对字段中的元素进行加减操作
hincrby hash 字段名 加减数
- 对不存在的hash字段赋值
hsetnx hash 字段 元素 #只能对不存在的字段进行赋值
应用场景
- 购物车
以用户id为key,商品id为field,商品数量为value,恰好构成了购物车的3个要素
- 存储对象
hash类型的(key, field, value)的结构与对象的(对象id, 属性, 值)的结构相似,也可以用来存储对象
Zset(有序集合)
基本的操作命令
- 增加值
zadd zset 权重 元素
- 查看有序集合中的所有值
zrange zset 0 -1 # 自动从小到大排序
- 从小到大排序
zrangebyscore zset -inf +inf
zrangebyscore zset -inf +inf withscore # 带上权重显示
zrangebyscore zset 最小权重 最大权重 # 获取两权重间的排序
- 从大到小排序
zrevrange zset 0 -1
- 移除特定的元素
zrem zset 特定元素 #一次可以移除多个
- 获取集合中元素数量
zcard zset
- 获取权重区间中元素数量
zcount zset 最小权重 最大权重
应用场景
- 延时队列
zset 会按 score 进行排序,如果 score 代表想要执行时间的时间戳。在某个时间将它插入 zset 集合中,它变会按照时间戳大小进行排序,也就是对执行时间前后进行排序。
- 排行榜
我们以当前小时的时间戳作为 zset 的 key,把贴子ID 作为 member ,点击数评论数等作为 score,当 score 发生变化时更新 score。就可以模拟出热度。
- 限流
滑动窗口是限流常见的一种策略。如果我们把一个用户的 ID 作为 key 来定义一个 zset ,member 或者 score 可以都为访问时的时间戳。我们只需统计某个 key 下在指定时间戳区间内的个数,就能得到这个用户滑动窗口内访问频次,与最大通过次数比较,来决定是否允许通过。