Redis(二)分布式锁+异步队列+持久化

通过Redis实现分布式锁

  1. 分布式锁应该具备哪些条件
  • 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行
  • 高可用的获取锁与释放锁
  • 高性能的获取锁与释放锁
  • 具备可重入特性(可理解为重新进入,由多于一个任务并发使用,而不必担心数据错误)
  • 具备锁失效机制,防止死锁
  • 具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败
  1. 分布式锁应该解决的问题
  • 互斥性问题:不能同时有两个客户端获取到锁
  • 安全性问题:锁只能由持有它的客户端删除,不能由其他客户端删除
  • 死锁问题:一旦获取到锁的某个客户端宕机,释放不了锁,会造成死锁,应该存在一定的锁机制来避免死锁
  • 容错问题:在一些结点宕机后,客户端任然能够获取和释放锁
  1. 通过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实现异步队列

  1. 使用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中

  1. 手动使用方式:
  • SAVE:阻塞Redis的服务器进程,知道RDB文件被创建完毕
  • BGSAVE:Fork出一个子进程来创建RDB文件,不阻塞服务器进程
  1. 自动触发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的优缺点

  1. RDB
  • 优点:全量数据快照,文件小,恢复快
  • 缺点:无法保存最近一次快照之后的数据
  1. AOF
  • 优点:可读性高,适合保存增量数据,数据不易丢失
  • 缺点:文件体积大,恢复时间长

在redis4.0之后推出了二者的混合方式(RDB-AOF混合持久化方式)作为二者的默认持久化方式:使用BGSAVE做全量持久化,AOF做增量持久化
在这里插入图片描述

发布了22 篇原创文章 · 获赞 23 · 访问量 6283

猜你喜欢

转载自blog.csdn.net/bob_man/article/details/104440195
今日推荐