Redis(二)分布式锁+异步队列+持久化
通过Redis实现分布式锁
- 分布式锁应该具备哪些条件
- 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行
- 高可用的获取锁与释放锁
- 高性能的获取锁与释放锁
- 具备可重入特性(可理解为重新进入,由多于一个任务并发使用,而不必担心数据错误)
- 具备锁失效机制,防止死锁
- 具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败
- 分布式锁应该解决的问题
- 互斥性问题:不能同时有两个客户端获取到锁
- 安全性问题:锁只能由持有它的客户端删除,不能由其他客户端删除
- 死锁问题:一旦获取到锁的某个客户端宕机,释放不了锁,会造成死锁,应该存在一定的锁机制来避免死锁
- 容错问题:在一些结点宕机后,客户端任然能够获取和释放锁
- 通过redis实现分布式锁
- SETNX key value:如果key不存在,则创建并且赋值(时间复杂度为O(1),若设置成功返回1,否则返回0)
- EXPIRE key seconds:设置key的生存时间,当key过期时(生存时间为0),会自动被删除
但是这里会存在问题,如果刚执行完SETNX然后缓存就挂了,那么锁就无法被释放了,主要原因是虽然这两个操作都是原子性的,但是他们加起来就不是了,违背了原子性
SET key [EX seconds][PX milliseconds] [NX|XX]
- EX seconds:设置键的过期时间为seconds秒
- PX millisecond:设置键的过期时间为millisecond秒
- NX 只在键存在时,才对键进行设置操作
- XX 只在键已经存在时,才对键进行设置操作
- SET操作完成,返回ok,否则返回nil
注意:在大量的key同时过期时,这种集中过期,由于在清理大量key很消耗时间,所以会出现短暂的卡顿现象,解决的方法是:在设置key的过期时间的时候,给每个key加上随机值,使过期时间分散一些
通过Redis实现异步队列
- 使用List作为队列,RPUSH生产信息,LPOP消费信息,如果看做生产者消费者模式,这样子的缺点是:没有等待队列里有值就直接消费,此时可以在代码中引入Sleep机制其调用LPOP重试
注意:如果不想用Sleep机制时,在pop时可以用:BLPOP[key…] timeout :阻塞直到队列有消息或超时,缺点:只能提供一个消费者消费
为了解决上面的问题,可以使用pub/sub:主题订阅者模式
- 发送者(pub)发送消息,订阅者(sub)接受消息
- 订阅者可以订阅任意数量的频道(相当于生产者消费者的一对多模型)
redis中的操作如下:
这样子有一个缺点:消息的发布是无状态的,无法保证可达,对于发布者来说,消息是即发即失的,此时如果某个消费者在生产者发送消息时下线,重新上线是接收不到消息的,要解决这个问题,就需要去使用专业的消息队列,如kafka
Redis持久化方式
RDB(快照)持久化
可以保持某个时间点的全量数据快照
在redis.conf中可以对于RDB持久化进行配置,选定合适的save配置策略有利于平衡redis的性能:
比如这里 save 900 1是指在900秒内有1次写入就进行一次备份,生成的文件保存在dump.rdb中
- 手动使用方式:
- SAVE:阻塞Redis的服务器进程,知道RDB文件被创建完毕
- BGSAVE:Fork出一个子进程来创建RDB文件,不阻塞服务器进程
- 自动触发RDB持久化方式:
- 根据redis.conf配置文件中的SAVE m n定时触发(用的是BGSAVE)
- 主从复制时,主节点自动触发
- 执行Debug Reload
- 执行Shutdownq且没有开启AOF持久化
BGSAVE的原理:
RDB的缺点:
- 内存数据的全量同步,数据了太大会而严重影响性能
- 可能会因为Redis挂掉而丢失从当前至最近一次快照期间的数据
AOF(保存写状态)
AOF持久化是默认关闭的
- 记录下除了查询以外的所有变更数据库状态的指令
- 以append的形式追加保存到AOF文件中(增量)
在redis.conf配置AOF时的参数:
- appendfsync:为always时表示缓存区内容一旦有变化就写入文件中,为everysec表示每隔一秒就写入文件,no表示将写入AOF的操作交由操作系统决定(一般而言,操作系统会等到缓存区别填满,才会同步数据到磁盘中去)
- appendonly:负责开启与关闭AOF
- 这些指令存储在appendonly.aof中
日志重写解决AOF文件大小不断增大的问题,原理如下:
- 调用fork(),创建一个子进程
- 子进程把新的AOF写到一个临时文件中,不依赖于原来的AOF文件
- 子进程持续将新的变动同时写到内存和原来的AOF里
- 主进程获取子进程重写AOF的完成信号,往新的AOF同步增量变动
- 使用新的AOF文件替换掉旧的AOF文件
RDB和AOF的优缺点
- RDB
- 优点:全量数据快照,文件小,恢复快
- 缺点:无法保存最近一次快照之后的数据
- AOF
- 优点:可读性高,适合保存增量数据,数据不易丢失
- 缺点:文件体积大,恢复时间长
在redis4.0之后推出了二者的混合方式(RDB-AOF混合持久化方式)作为二者的默认持久化方式:使用BGSAVE做全量持久化,AOF做增量持久化