分布式锁
redis实现是非公平锁,ectd、zk用来实现公平锁
获取不到锁的客户端阻塞等待,阻塞连接返回
set lock uuid nx ex 30 #不存在才能设置,定义加锁行为,占用锁,30s超时。或者用setnx
if (get(lock) == uuid) #释放锁
del(lock)
非公平锁:自旋锁,独占cpu不断尝试获取锁
公平锁:互斥锁,按照请求顺序得到锁
阻塞连接
使用list数据结构,队首入队LPUSH,用队尾弹出命令RPOP,这个命令会在list为空时阻塞连接
BRPOP key timeout # 超时时间 + 延时队列
在超时时间内如果有数据则弹出,timeout为0则永远阻塞
可以用于实现redis的一个公平锁
固定窗口限流
list链表中push的数据固定大小,防止链表过长
LPUSH入队,RPOP出队,如何只保存最近n条数据
ltrim listkey 0 49 #裁剪最近50条记录
lrange listkey 0 49 #获取最近50条记录
可应用于保存n条最新实时数据,比如战绩、排行
有序集合
使用zset数据结构,用于实现排行榜,热度,范围查找,元素有序且唯一
#添加到键为key的有序集合(sorted set)里面
ZADD key [NX|XX] [CH] [INCR] score member [score member ...]
#返回存储在有序集合key中的指定范围的元素
ZRANGE key start stop [WITHSCORES]
#返回有序集合key中,指定区间的成员(逆序)
ZREVRANGE key start stop [WITHSCORES]
内部使用的是跳表的数据结构
延时队列
将消息序列化成一个字符串作为 zset 的 member;这个消息的到期处理时间作为 score,然后用 多个线程轮询 zset 获取到期的任务进行处理。
分布式定时器
生产者将定时任务 hash 到不同的 redis 实体中,为每一个 redis 实体分配一个 dispatcher 进程, 用来定时获取 redis 中超时事件并发布到不同的消费者中;
时间窗口限流
系统限定用户的某个行为在指定的时间范围内(动态)只能发生N次;
事务
redis的事务有两种模式,MUTLI命令和lua脚本。
MULTI:开启事务
EXEC:提交事务
DISCARD:取消事务
WATCH:检测某个key的变动,若在事务执行中,key被其他客户端变动则取消事务;在事务开启前调用,乐观锁实现(cas);若被取消则事务返回nil
lua脚本实现原子性;redis中加载了一个lua虚拟机,用来执行redis lua脚本;redis lua脚本的执行是原子性的;当某个脚本正在执行时,不会有其他命令或其他脚本被执行;
# 从文件中读取 lua脚本内容
cat test1.lua | redis-cli script load --pipe
# 加载 lua脚本字符串 生成 sha1
> script load 'local val = KEYS[1]; return val'
"b8059ba43af6ffe8bed3db65bac35d452f8115d8"
# 检查脚本缓存中,是否有该 sha1 散列值的lua脚本
> script exists "b8059ba43af6ffe8bed3db65bac35d452f8115d8"
1) (integer) 1
# 清除所有脚本缓存
> script flush
OK
# 如果当前脚本运行时间过长,可以通过 script kill 杀死当前运行的脚本
> script kill
(error) NOTBUSY No scripts in execution right now.
# 测试使用
EVAL script numkeys key [key ...] arg [arg ...]
# 线上使用
EVALSHA sha1 numkeys key [key ...] arg [arg ...]
# 1: 项目启动时,建立redis连接并验证后,先加载所有项目中使用的lua脚本(script load);
# 2: 项目中若需要热更新,通过redis-cli script flush;然后可以通过订阅发布功能通知所有服
务器重新加载lua脚本;
# 3:若项目中lua脚本发生阻塞,可通过script kill暂停当前阻塞脚本的执行;
发布订阅
为了支持消息的多播机制,redis 引入了发布订阅模块;消息不一定可达;分布式消息队列;stream的方式确保一定可达
# 订阅频道 subscribe 频道
# 订阅模式频道 psubscribe 频道
# 取消订阅频道 unsubscribe 频道
# 取消订阅模式频道 punsubscribe 频道
# 发布具体频道或模式频道的内容 publish 频道 内容
# 客户端收到具体频道内容 message 具体频道 内容
# 客户端收到模式频道内容 pmessage 模式频道 具体频道 内容