centos8 redis守护进程 安装 redis守护进程的用意_redis守护线程


redis 为什么是单线程的

redis基于内存操作的,cpu并不是的瓶颈,使用单线程可以省去上下文切换的时间

什么是缓存穿透?怎么解决?

当数据库中不存在该条数据,理应缓存也不会有该条数据,去查询一条在数据库中不存在的数据,

查了缓存没有查到,就会一直查询数据库,导致服务瘫痪,这就是缓存穿透

解决方案:

1.即使查询的该条数据在数据库中不存在,也把NULL结果放入缓存,给定一个较短的过期时间

2.使用布隆过滤器进行拦截,布隆过滤器会判断该条数据是否在数据库中存在,不存在就不会往数据库查询

怎么保证缓存和数据库数据的一致性?

一般大多数人都是先更新数据库,然后再删除缓存,但是在高并发的情况下,这也还是会造成数据不一致性

可以使用消息队列来处理,写操作可以只负责更新数据库,将ID放到消息队里,消费者去消费消息,即根据ID删除缓存

就算删除缓存失败,也还可以进行多次重试删除

这有做不仅可以将更新数据库和删除缓存达到解耦的目的,还可以解决删除缓存失败的问题

redis 持久化的两种方式

rdb快照存储:每隔一段时间将数据集备份到磁盘上

aof持久化:将redis的操作日志以追加的方式写入文件

二者如何选择:假如你愿意牺牲一些性能用来换取更高的缓存一致性,那就选用aof,否则就选rdb

redis 淘汰策略有哪些?

  • volatile-lru:从已设置过期时间的数据集(server. db[i]. expires)中挑选最近最少使用的数据淘汰。
  • volatile-ttl:从已设置过期时间的数据集(server. db[i]. expires)中挑选将要过期的数据淘汰。
  • volatile-random:从已设置过期时间的数据集(server. db[i]. expires)中任意选择数据淘汰。
  • allkeys-lru:从数据集(server. db[i]. dict)中挑选最近最少使用的数据淘汰。
  • allkeys-random:从数据集(server. db[i]. dict)中任意选择数据淘汰。
  • no-enviction(驱逐):禁止驱逐数据。

redisson实现分布式锁

不管使用什么中间件来实现分布式锁,有几点是实现分布式锁必须要考虑到的。

  1. 互斥:互斥需要考虑锁粒度的大小,比如可以将资源唯一标识作为锁名key
  2. 死锁: 如果一个线程获得锁,然后挂了,并没有释放锁,致使其他节点(线程)永远无法获取锁,这就是死锁。分布式锁必须做到避免死锁。
  3. 性能: 高并发分布式系统中,线程互斥等待会成为性能瓶颈,需要好的中间件和实现来保证性能。
  4. 锁特性:考虑到复杂的场景,分布式锁不能只是加锁,然后一直等待。最好实现如Java Lock的一些功能如:锁判断,超时设置,可重入锁等。

死锁的解决方案:

出现死锁的原因:某个线程一直不释放锁,其他线程无法获取到锁

出现死锁的场景:系统宕机,redis宕机

针对系统宕机的解决方案

假设某个线程获得锁之后,突然系统宕机,导致无法释放锁,造成死锁

还有一种情况就是该线程执行逻辑业务的时间需要2秒,但超期时间只有1秒

1秒过后,锁被释放,该线程还在执行业务,而锁被其他线程获取了,也在执行业务

这样就没有了互斥的效果,导致数据不一致。

可以为获得锁的线程续命,这个续命任务是由后台的一个守护线程执行的,当过了超期时间的三分之一

自动延长锁的生存时间,可以保证在该线程还没执行完业务之前不会释放锁,

对于系统宕机这种情况,守护线程会自动释放锁并且会跟随进程的结束而结束,

针对redis宕机的解决方案:给redis做集群

针对以上问题:可以使用redisson来实现分布式锁

它可以在加锁和设置超期时间的时候做到原子性操作

看门狗自动续航,避免发生死锁的问题,宕机后续航任务自动销毁

同一个线程ID获取相同资源的时候,还可以重入锁

在解锁的时候能够进行锁判断,避免误删其他节点的锁


centos8 redis守护进程 安装 redis守护进程的用意_redis守护线程_02


centos8 redis守护进程 安装 redis守护进程的用意_redis守护线程_03