Redis相关技术点

一,Redis持久化方式

方式一:RDB方式

Redis DataBase: 持久化内存数据到磁盘

Redis服务端,fork一个子进程,定时并且达到修改次数的时候写磁盘,写到rdb文件(dump.rdb)

fork函数的作用是创建一个子进程,并且和父进程运行同样的代码。

方式二:AOF方式

Append Only File :持久化修改数据的命令

客户端发起修改命令,到redis服务端,每秒、每个命令、不同步的方式到aof文件(appendonly.aof)

两种方式的对比

  1. 保存内容 RDB保存的是二进制文件,AOF保存的是Redis命令
  2. 数据恢复速度 RDB快照恢复速度快,AOF命令过多速度慢
  3. 数据恢复完整性 RDB可能会丢数据,AOF比RDB恢复完整性高

如何能够最大化保证恢复数据的速度以及数据的完整性?

混合持久化 Redis 4.0以后,以RDB的方式全量持久化内存数据,保证数据恢复的速度,并以增量的方式持久化修改命令,保证数据的完整性,最终以RDB和AOF共存的方式写入AOF文件。

二,Redis 单机、主从、哨兵、集群的架构模式

单机模式:

缓存服务中,只有一台Redis对我们的应用提供服务。 因为只有一台Redis,缺点比较明显。Redis宕机时,应用就无法使用。并且只有一台Redis,吞吐量也比较低。

主从模式:

缓存服务中,只有一台主Redis和多台从Redis,主Redis提供写,从Redis提供读。实现读写分离,减轻单台Redis的压力。但是主Redis宕机时,需要手动选择从Redis。

哨兵模式:

缓存服务中,任然有主从Redis对外提供服务,并且有哨兵去监控主从Redis的状态,如果主Redis发生宕机时,就会在从Redis自动选择一台对外提供服务

这种模式可以解决可用性问题,但是只有一台Redis对外提供写服务,大量写操作情况下,任然会有问题,所有引入集群模式,解决可用性和吞吐量大的问题。

集群模式:

是通过多个独立的主从Redis对外提供服务,可用性和吞吐量的问题。

但应用具体读写哪一台主从Redis?

集群模式下,有16384个hash slot (hash_slot=crc16(key) mod 16384) 分别分布在主从上,根据key去算出hash槽的位置,确定在哪一个主从。

三,Redis分布式锁的实现

什么是分布式锁?

比如有多个服务端A,B,C 经过分布式锁对共有资源进行访问,只有A可以成功,B和C失败。

这种在分布式系统中控制多个进程对共有资源的访问称为分布式锁。

分布式锁具有的性质

  1. 互斥性 同一时刻,只有一个客户端可以获取锁
  2. 安全性 锁的获取和释放是同一个客户端
  3. 可用性 高可用的分布式锁系统及避免产生死锁

怎样用Redis实现分布式锁

setnx + expire 加锁

setnx 如果key不存在 set成功返回1,失败返回0,保证互斥

expire 设置过期时间,防止锁的长期持有或死锁

这种方式是不对的,因为setnx + expire 会发生异常导致死锁

正确方式是:

set原子方法加锁

SET key value NX EX expire-time;

Redis 2.6.12以后,直接使用set方法进行加锁,避免死锁。NX和EX为固定值,前者表示SET IF NOT Exist,后者表示添加过期时间,具体时间取最后一个参数。

比较删除解锁

DEL Key 前判断是否为加锁的客户端,可以通过添加客户端的唯一id(具体实现自己决定)到value中,每次删除前比较,一致再进行删除解锁,保证安全性。

四,Redis缓存穿透、击穿、雪崩问题

缓存的使用场景:

当用户使用我们的网站或者app时候,他们操作的数据基本上来源于底层数据库,那么当用户量比较大的时候,数据库的读写压力也会随之增加。一般情况下,我们会缓存热点数据

缓存数据的目的是,一方面让网站和app可以直接从缓存拿数据,有很快的响应。另一方面可以减轻数据库的负担,redis就是常用的缓存数据库。

缓存存在的问题,只有一个不可用的问题。当缓存不可用时,用户的请求会落在db上,在高并发或者有人恶意攻击的情况下,可能会导致db的崩溃。

缓存穿透 当用户访问了一个本身就不存在的缓存,那么用户的请求最终都会落在db上,在高并发或者有人恶意攻击的情况下,可能会导致db的崩溃。

解决:

  1. 使用布隆过滤器判断缓存中是否存在
  2. 为请求设置一个值为null的缓存,设置较短的过期时间

缓存击穿 当用户访问缓存数据库,发现缓存已经过期失效,那么就要去db中重新拿缓存,并且写入缓存数据库中。如果在这时候有高并发的请求,就会导致瞬间db压力过大。

解决:

  1. 热点数据的缓存永不过期。可以解决瞬间数据库压力过大的问题
  2. 采用分布式锁,缓存失效后只有一个线程更新并写入缓存数据库

缓存雪崩 大面积的缓存击穿或者服务不可用

解决:

  1. 使用Redis哨兵或者集群等架构提升可用性
  2. 采用和缓存击穿一样的方式
  3. 错开缓存数据的过期时间点,防止缓存大面积失效

五,主从复制

主从复制的应用场景:

比如说在某一台的主机上安装Redis,这台主机发生宕机或者损坏,就会导致服务不可用,或者数据丢失,所以一般情况下,我们会为一个Redis服务器设置多个从服务器,以达到防止数据丢失的目的。这种模式也可以实现读写分离,然后来提升整个Redis对外的吞吐量,最后可以联合哨兵模式来提升系统的可用性以及扩展性。

一旦牵扯主从这种框架就会涉及复制的问题。

Redis支持两种复制模式:

全量复制 是指主从服务器之间建立连接,从服务器发送sync命令向主服务器请求数据,主服务器通过bgsave 生成RDB文件,并且将RDB文件传给从服务器,这个阶段又可以称之为数据同步的阶段。在这个阶段,主服务器可能会接收其他的写命令,这个时候需要将缓存中的写命令也给到从服务器去执行,这个又称为命令传播的阶段。

redis 2.8 后增加增量复制,全量复制的save效率较低,也比较消耗资源

增量复制

主从服务器之间什么时候需要数据复制?

  • 从服务器断线重连,断线期间有可能数据是不一致的,需要进行增量复制
  • 新增节点,必须进行全量复制

是否进行增量复制,也就是我们需要考虑从服务器复制了多少,首先可以按照主服务器的ID去判断,如果主服务器的ID变了,就需要进行全量复制。其次也需要偏移量来记录,主服务器和从服务器之间的差距有多少,并且主服务器中维护了一个积压命令的缓冲区,如果偏移量在缓冲区范围内,就进行增量复制。

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务