5.Redis 面试题

在这里插入图片描述

⭐重点面试题


介绍一下Redis ?

Redis 的全称是:Remote Dictionary.Server,本质上是一个 Key-Value 类型的内存数据库

整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据 flush 到硬盘上进行保存。

因为是纯内存操作,Redis 的性能非常出色,每秒可以处理超过 10 万次读写操作,是已知性能最快的Key-Value DB。

Redis 的出色之处不仅仅是性能,Redis 最大的魅力是支持保存多种数据结构

可以用他的 List 来做 FIFO 双向链表,实现一个轻量级的高性 能消息队列服务

可以用他的 Set 做高性能的 tag 系统。

另外 Redis 也可以对存入的 Key-Value 设置 expire 过期时间。

Redis 的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此 Redis 适合的场景主要局限在较小数据量的高性能操作和运算上

Redis的数据类型都有哪些?

常用的有5种,分别是String , Hash , List , Set , ZSet

  • String-键值对类型
  • Hash-1个大key,然后就是多组key value , 可以存储用户信息
  • List-队列先进后出,栈先进先出集合,可以实现排队,插队,消息队列等
  • Set-也是1个集合,不过是1个去重的集合,相同的元素只会存在1个,可以实现投票,好友推荐等
  • ZSet-也是去重集合具有Set的功能,多了1个自动排序,默认是顺序查询,相当于权重,可以用来实现抽奖,限流,排行榜等。

新版本中扩展了更多类型,有BitMaps , Hyperlogloss ,Geospatial ,Streams等

  • BitMaps-只存0和1,可以节省存储空间,可以用来记录用于一年的打卡情况。打卡为1,未打卡为0
  • Hyperlogloss-海量数据统计 统计过程中不记录独立元素,可以用来统计每日或没有的UV数。
  • Geospatial-用于存储和操作地理空间数据
  • Streams-发布订阅

Redis 有哪些适合的场景?

  1. 会话缓存(Session Cache),最常见的Redis应用。
  2. 全页缓存(FPC)
  3. 消息队列,Reids 在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得 Redis 能作为一个很好的消息队列平台来使用。
  4. 排行榜/计数器,Redis 在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(SortedSet)也使得我们在执行这些操作的时候变的非常简单,Redis 只是正好提供了这两种数据结构。
  5. 发布/订阅,Steams类型可以实现发布/订阅

说说你对Redis事务的理解?

Redis事务的原理
Redis 中的事务是一组命令的集合,是 Redis 的最小执行单位。它可以保证一次执行多个命令,每个事务是一个单独的隔离操作,事务中的所有命令都会序列化、按顺序地执行。服务端在执行事务的过程中,不会被其他客户端发送来的命令请求打断。
它的原理是先将属于一个事务的命令发送给 Redis,然后依次执行这些命令。

Redis 事务的注意事项

  • Redis 事务是不支持回滚的,不像 MySQL 的事务一样,要么都执行要么都不执行;
  • Redis 服务端在执行事务的过程中,不会被其他客户端发送来的命令请求打断。直到事务命令全部执行完毕才会执行其他客户端的命令。

Redis 事务回滚
Redis 的事务不支持回滚,但是执行的命令有语法错误,Redis 会执行失败,这些问题可以从程序层面捕获并解决。但是如果出现其他问题,则依然会继续执行余下的命令。这样做的原因是因为回滚需要增加很多工作,而不支持回滚则可以保持简单、快速的特性。

描述一下Redis的事务机制

Redis的事务机制允许将多个操作打包成一个原子操作,即要么所有操作都成功执行,要么全部都不执行。Redis的事务机制是通过MULTI、EXEC、DISCARD和WATCH等命令来实现的。以下是Redis事务机制的基本概念和命令:

MULTI: 事务的开始,该命令标记一个事务块的开始。
EXEC: 执行事务,将之前在MULTI和EXEC之间的命令执行为一个原子操作。
DISCARD: 放弃事务,取消事务块,清除之前在MULTI和EXEC之间的命令。
WATCH: 监视一个或多个键,如果在事务执行期间这些键被修改,则事务会被取消。

事务的使用步骤如下:

  1. 使用MULTI命令开始一个事务块。
  2. 在MULTI和EXEC之间,执行要包含在事务中的命令,这些命令不会立即执行,而是在EXEC命令执行时一起执行。
  3. 如果需要取消事务,可以使用DISCARD命令。
  4. 如果需要提交事务,可以使用EXEC命令,Redis会依次执行在MULTI和EXEC之间的命令。
  5. 如果在事务执行期间,被监视的键发生了变化,事务会被取消。

需要注意的是,Redis的事务机制并不同于传统数据库的事务,它不支持回滚和隔离级别。事务块中的命令在EXEC执行时会一次性执行,但如果在事务执行过程中发生了错误,错误信息会被记录,但不会影响后续命令的执行。

Redis的主从模式

Redis的主从模式是一种用于数据复制和高可用性的架构,允许多个Redis实例之间建立一个主从关系,其中一个实例充当主服务器(master),而其他实例充当从服务器(slaves)。主从模式有助于数据备份、故障恢复和读写分离等需求。

Redis主从模式的主要特点和工作方式:

  • 数据复制: 主服务器将数据写入到自己的数据库中,然后通过异步的方式将写操作传播到从服务器,使从服务器的数据与主服务器保持一致。
  • 读写分离: 通过将主服务器用于写操作,从服务器用于读操作,可以分摊读写压力,提高系统的读写性能。
  • 高可用性: 如果主服务器发生故障,从服务器可以接管成为新的主服务器,从而实现故障转移,提高系统的可用性。
  • 数据备份: 从服务器可以用于备份数据,以防止主服务器数据丢失。
  • 异步复制: 默认情况下,Redis主从复制是异步的,即主服务器写入数据后,并不立即等待从服务器确认。这可以提高性能,但可能导致主从数据不一致。
  • 全量复制和增量复制: 初次复制时,从服务器会进行全量复制,即复制所有主服务器的数据。之后的复制是增量复制,只复制发生变化的数据。
  • 复制链: 从服务器也可以充当其他从服务器的主服务器,从而构建复制链。这种链式复制可以在多个级别上实现数据的传播。
  • 可配置性: Redis主从复制可以配置为只复制特定的数据库、特定的数据类型等,以满足不同需求。
    需要注意的是,Redis主从复制是异步的,这意味着从服务器可能会因为网络故障或其他原因导致数据滞后,从而导致数据不一致。为了确保数据一致性,可以使用Redis的复制延迟监控、持久化等手段。另外,Redis 6.0版本引入了支持半同步复制的功能,以提高数据可靠性。

Redis的哨兵模式

Redis的哨兵模式是一种用于监控和自动故障转移的架构,用于提高Redis系统的高可用性。在哨兵模式中,有一组特殊的Redis实例称为"哨兵",它们负责监控主服务器和从服务器的状态,当主服务器发生故障时,哨兵可以自动将一个从服务器提升为新的主服务器,以实现故障转移。

以下是Redis哨兵模式的主要特点和工作方式:

  • 监控: 哨兵会周期性地检查所有主服务器和从服务器的状态,包括是否存活、是否正常运行等
  • 自动故障转移: 当哨兵检测到主服务器不可用时,它会选举一个新的主服务器,然后将其他从服务器切换为新的主服务器的从服务器,从而实现故障转移。
  • 配置更新: 如果主服务器发生故障,哨兵会更新所有客户端的连接配置,以指向新的主服务器,从而实现无感知的故障切换。
  • 多哨兵支持: 可以在Redis集群中部署多个哨兵,这些哨兵会协同工作来监控和管理主从服务器。
  • 提供监控信息: 哨兵可以提供有关主从服务器状态、故障转移历史等信息,以供监控和管理。
  • 配置自动化: 哨兵模式可以在一定程度上实现自动化的故障转移和节点管理,减少人工干预。

需要注意的是,哨兵模式虽然提供了一定的高可用性,但在故障转移过程中仍然可能出现数据不一致或数据丢失的情况。为了进一步提高可靠性,可以使用持久化、数据备份等手段。另外,哨兵模式适用于较小规模的Redis集群,对于更大规模的集群,可以考虑使用Redis Cluster。

Redis的集群模式

Redis的集群模式是一种用于构建高可用性和分布式的数据存储架构,通过将多个Redis节点组成一个集群,实现数据分片、负载均衡和故障转移等功能。Redis Cluster提供了自动分片和节点管理功能,使得在分布式环境下使用Redis更加方便和可靠。

Redis集群模式的主要特点和工作方式:

  • 自动分片: Redis Cluster会将数据自动分成多个槽(slot),每个槽对应一个节点。这样,集群中的每个节点都只负责管理一部分数据,实现了数据分片。
  • 节点故障转移: 当某个节点发生故障时,Redis Cluster会自动进行故障转移,将故障节点的槽分配给其他正常节点,从而实现高可用性。
  • 负载均衡: 客户端可以通过Redis Cluster提供的路由机制,将请求均匀地分发到集群中的不同节点上,实现负载均衡。
  • 节点管理: Redis Cluster支持自动添加和移除节点,使得集群的扩展和缩减变得更加容易。新节点加入集群后,数据会自动迁移。
  • 数据复制: Redis Cluster中的每个节点都有多个复制节点,用于实现数据的备份和高可用性。每个主节点会有1个或多个从节点,实现数据冗余。
  • 节点通信: 集群中的节点通过Gossip协议进行通信,用于检测节点状态、故障检测和配置更新等。
  • 客户端支持: 使用Redis Cluster,客户端可以透明地访问集群中的不同节点,而无需手动管理节点。

Redis集群模式在处理大规模数据、提高系统可用性和性能方面具有很大优势,但在配置和管理时也需要考虑到数据一致性、故障转移的延迟等问题。使用Redis Cluster可以有效地构建分布式系统,但也需要了解其特性和限制,以适应不同的业务需求

什么是缓存穿透,缓存击穿和缓存雪崩?

缓存穿透
缓存的穿透是指当查询一个不存在的数据时,由于缓存中没有该数据,导致查询透过缓存直接查数据库,从而增加数据库的负担。

通常解决缓存穿透的方法是

  • 对于查询不到的数据也将其缓存起来,并设置一个较短的过期时间。
  • 使用布隆过滤器来过滤掉查询不存在数据的请求。

缓存穿透
缓存击穿是指某个热点数据过期或者被删除,导致大量请求直接绕过缓存访问数据库,导致数据库压力瞬间升高,甚至崩溃。

解决缓存击穿的方法是

  • 使用互斥锁(Mutex),只允许一个请求进入数据库查询,其他请求等待。
  • 使用分布式锁,保证同一时间只有一个进程能够访问共享资源
  • 使用缓存预热,将热点数据提前加载到缓存
  • 设置热点数据永不过期
  • 使用限流策略

缓存雪崩

缓存雪崩是指在某个时间段,缓存集中过期失效,导致大量请求直接访问数据库,造成短时间内数据库请求量骤增,压力过大,可能造成数据库崩溃。

缓存雪崩的解决方案有以下几种

  • 缓存预加载,在正式流量到来前,提前将可能会用到的数据加载到缓存中,避免在流量高峰期间查询数据库
  • 缓存高可用,使用多级缓存,如本地缓存和分布式缓存。如果某一个缓存出现了问题,可以快速切换到另一级缓存上
  • 缓存限流,通过限制访问频率,降低缓存的压力
  • 数据预热,在系统启动时,将所有需要缓存的数据直接加载到缓存中,避免在查询时缓存未命中
  • 将缓存的失效时间设置为随机值,避免缓存同时失效导致数据库压力过大
  • 数据库容,建立数据库的主从复制和故障转移机制,避免数据库出现单点故障
  • 限制并发查询,避免过多的查询同时落在数据库上
  • 缓存数据分片,避免单个缓存的失效影响整个缓存系统

缓存

穿透,击穿,雪崩

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

缓存穿透是指查询一个一定不存在的数据,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到 DB 去查询,可能导致 DB 挂掉。这种情况大概率是遭到了攻击。
解决方案的话,我们通常都会用布隆过滤器来解决它

介绍一下布隆过滤器吗?

布隆过滤器主要是用于检索一个元素是否在一个集合中。我们当时使用的是redisson实现的布隆过滤器。

它的底层主要是先去初始化一个比较大数组,里面存放的二进制0或1。在一开始都是0,当一个key来了之后经过3次hash计算,模于数组长度找到数据的下标然后把数组中原来的0改为1,这样的话,三个数组的位置就能标明一个key的存在。查找的过程也是一样的。

当然是有缺点的,布隆过滤器有可能会产生一定的误判,我们一般可以设置这个误判率,大概不会超过5%,其实这个误判是必然存在的,要不就得增加数组的长度,其实已经算是很划分了,5%以内的误判率一般的项目也能接受,不至于高并发下压倒数据库。

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

缓存击穿的意思是对于设置了过期时间的key,缓存在某个时间点过期的时候,恰好这时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端 DB 加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把 DB 压垮。

解决方案有两种方式:

  1. 以使用互斥锁:当缓存失效时,不立即去load db,先使用如 Redis 的 setnx 去设置一个互斥锁,当操作成功返回时再进行 load db的操作并回设缓存,否则重试get缓存的方法

  2. 第二种方案可以设置当前key逻辑过期,大概是思路如下:

    1. 在设置key的时候,设置一个过期时间字段一块存入缓存中,不给当前key设置过期时间
    2. 当查询的时候,从redis取出数据后判断时间是否过期
    3. 如果过期则开通另外一个线程进行数据同步,当前线程正常返回数据,这个数据不是最新

当然两种方案各有利弊:
如果选择数据的强一致性,建议使用分布式锁的方案,性能上可能没那么高,锁需要等,也有可能产生死锁的问题
如果选择key的逻辑删除,则优先考虑的高可用性,性能比较高,但是数据同步这块做不到强一致。

什么是缓存雪崩 ? 怎么解决 ?

缓存雪崩意思是设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB 瞬时压力过重雪崩。与缓存击穿的区别:雪崩是很多key,击穿是某一个key缓存。

解决方案主要是可以将缓存失效时间分散开,比如可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

双写一致性

redis做为缓存,mysql的数据如何与redis进行同步呢?(双写一致性)

嗯!就说我最近做的这个项目,里面有xxxx(根据自己的简历上写)的功能,需要让数据库与redis高度保持一致,因为要求时效性比较高,我们当时采用的读写锁保证的强一致性。

我们采用的是redisson实现的读写锁,在读的时候添加共享锁,可以保证读读不互斥,读写互斥。当我们更新数据的时候,添加排他锁,它是读写,读读都互斥,这样就能保证在写数据的同时是不会让其他线程读数据的,避免了脏数据。这里面需要注意的是读方法和写方法上需要使用同一把锁才行。

那这个排他锁是如何保证读写、读读互斥的呢?

其实排他锁底层使用也是setnx,保证了同时只能有一个线程操作锁住的方法

你听说过延时双删吗?为什么不用它呢?

延迟双删,如果是写操作,我们先把缓存中的数据删除,然后更新数据库,最后再延时删除缓存中的数据,其中这个延时多久不太好确定,在延时的过程中可能会出现脏数据,并不能保证强一致性,所以没有采用它。

redis做为缓存,mysql的数据如何与redis进行同步呢?(双写一致性)

嗯!就说我最近做的这个项目,里面有xxxx(根据自己的简历上写)的功能,数据同步可以有一定的延时(符合大部分业务)

我们当时采用的阿里的canal组件实现数据同步:不需要更改业务代码,部署一个canal服务。canal服务把自己伪装成mysql的一个从节点,当mysql数据更新以后,canal会读取binlog数据,然后在通过canal的客户端获取到数据,更新缓存即可。

持久化

redis做为缓存,数据的持久化是怎么做的?

在Redis中提供了两种数据持久化的方式:1、RDB 2、AOF

这两种持久化方式有什么区别呢?

  1. RDB是一个快照文件,它是把redis内存存储的数据写到磁盘上,当redis实例宕机恢复数据的时候,方便从RDB的快照文件中恢复数据。
  2. AOF的含义是追加文件,当redis操作写命令的时候,都会存储这个文件中,当redis实例宕机恢复数据的时候,会从这个文件中再次执行一遍命令来恢复数据

RDB,AOF这两种方式,哪种恢复的比较快呢?

RDB因为是二进制文件,在保存的时候体积也是比较小的,它恢复的比较快,但是它有可能会丢数据,我们通常在项目中也会使用AOF来恢复数据,虽然AOF恢复的速度慢一些,但是它丢数据的风险要小很多,在AOF文件中可以设置刷盘策略,我们当时设置的就是每秒批量写入一次命令

数据过期,淘汰策略

Redis的数据过期策略有哪些 ?

在redis中提供了两种数据过期删除策略

  1. 第一种是惰性删除,在设置该key过期时间后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key。
  2. 第二种是 定期删除,就是说每隔一段时间,我们就对一些key进行检查,删除里面过期的key
    定期清理的两种模式:
    • SLOW模式是定时任务,执行频率默认为10hz,每次不超过25ms,以通过修改配置文件redis.conf 的 hz 选项来调整这个次数
    • FAST模式执行频率不固定,每次事件循环会尝试执行,但两次间隔不低于2ms,每次耗时不超过1ms
      Redis的过期删除策略:惰性删除 + 定期删除两种策略进行配合使用。

Redis的数据淘汰策略有哪些 ?

这个在redis中提供了很多种,默认是noeviction,不删除任何数据,内部不足直接报错,是可以在redis的配置文件中进行设置的,里面有两个非常重要的概念,一个是LRU,另外一个是LFU

  1. LRU的意思就是最少最近使用,用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。
  2. LFU的意思是最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高
    我们在项目设置的allkeys-lru,挑选最近最少使用的数据淘汰,把一些经常访问的key留在redis中

数据库有1000万数据 ,Redis只能缓存20w数据, 如何保证Redis中的数据都是热点数据 ?

可以使用 allkeys-lru (挑选最近最少使用的数据淘汰)淘汰策略,那留下来的都是经常访问的热点数据

Redis的内存用完了会发生什么?

这个要看redis的数据淘汰策略是什么,如果是默认的配置,redis内存用完以后则直接报错。我们当时设置的 allkeys-lru 策略。把最近最常访问的数据留在缓存中。

分布式锁

setnx

Redis分布式锁如何实现 ?

在redis中提供了一个命令setnx(SET if not exists)
由于redis的单线程的,用了命令之后,只能有一个客户端对某一个key设置值,在没有过期或删除key的时候是其他客户端是不能设置这个key的

redision

如何控制Redis实现分布式锁有效时长呢?

的确,redis的setnx指令不好控制这个问题,我们当时采用的redis的一个框架redisson实现的。

在redisson中需要手动加锁,并且可以控制锁的失效时间和等待时间,当锁住的一个业务还没有执行完成的时候,在redisson中引入了一个看门狗机制,就是说每隔一段时间就检查当前业务是否还持有锁,如果持有就增加加锁的持有时间,当业务执行完成之后需要使用释放锁就可以了

还有一个好处就是,在高并发下,一个业务有可能会执行很快,先客户1持有锁的时候,客户2来了以后并不会马上拒绝,它会自旋不断尝试获取锁,如果客户1释放之后,客户2就可以马上持有锁,性能也得到了提升。

redisson实现的分布式锁是可重入的吗?

是可以重入的。这样做是为了避免死锁的产生。这个重入其实在内部就是判断是否是当前线程持有的锁,如果是当前线程持有的锁就会计数,如果释放锁就会在计算上减一。在存储数据的时候采用的hash结构,大key可以按照自己的业务进行定制,其中小key是当前线程的唯一标识,value是当前线程重入的次数

redisson实现的分布式锁能解决主从一致性的问题吗

这个是不能的,比如,当线程1加锁成功后,master节点数据会异步复制到slave节点,此时当前持有Redis锁的master节点宕机,slave节点被提升为新的master节点,假如现在来了一个线程2,再次加锁,会在新的master节点上加锁成功,这个时候就会出现两个节点同时持有一把锁的问题。

我们可以利用redisson提供的红锁来解决这个问题,它的主要作用是,不能只在一个redis实例上创建锁,应该是在多个redis实例上创建锁,并且要求在大多数redis节点上都成功创建锁,红锁中要求是redis的节点数量要过半。这样就能避免线程1加锁成功后master节点宕机导致线程2成功加锁到新的master节点上的问题了。

但是,如果使用了红锁,因为需要同时在多个节点上都添加锁,性能就变的很低了,并且运维维护成本也非常高,所以,我们一般在项目中也不会直接使用红锁,并且官方也暂时废弃了这个红锁

如果业务非要保证数据的强一致性,这个该怎么解决呢?

redis本身就是支持高可用的,做到强一致性,就非常影响性能,所以,如果有强一致性要求高的业务,建议使用zookeeper实现的分布式锁,它是可以保证强一致性的。

事务

说说你对Redis事务的理解?

Redis事务的原理
Redis 中的事务是一组命令的集合,是 Redis 的最小执行单位。它可以保证一次执行多个命令,每个事务是一个单独的隔离操作,事务中的所有命令都会序列化、按顺序地执行。服务端在执行事务的过程中,不会被其他客户端发送来的命令请求打断。
它的原理是先将属于一个事务的命令发送给 Redis,然后依次执行这些命令。

Redis 事务的注意事项

  • Redis 事务是不支持回滚的,不像 MySQL 的事务一样,要么都执行要么都不执行;
  • Redis 服务端在执行事务的过程中,不会被其他客户端发送来的命令请求打断。直到事务命令全部执行完毕才会执行其他客户端的命令。

Redis 事务回滚
Redis 的事务不支持回滚,但是执行的命令有语法错误,Redis 会执行失败,这些问题可以从程序层面捕获并解决。但是如果出现其他问题,则依然会继续执行余下的命令。这样做的原因是因为回滚需要增加很多工作,而不支持回滚则可以保持简单、快速的特性。

描述一下Redis的事务机制

Redis的事务机制允许将多个操作打包成一个原子操作,即要么所有操作都成功执行,要么全部都不执行。Redis的事务机制是通过MULTI、EXEC、DISCARD和WATCH等命令来实现的。以下是Redis事务机制的基本概念和命令:

MULTI: 事务的开始,该命令标记一个事务块的开始。
EXEC: 执行事务,将之前在MULTI和EXEC之间的命令执行为一个原子操作。
DISCARD: 放弃事务,取消事务块,清除之前在MULTI和EXEC之间的命令。
WATCH: 监视一个或多个键,如果在事务执行期间这些键被修改,则事务会被取消。

事务的使用步骤如下:

  1. 使用MULTI命令开始一个事务块。
  2. 在MULTI和EXEC之间,执行要包含在事务中的命令,这些命令不会立即执行,而是在EXEC命令执行时一起执行。
  3. 如果需要取消事务,可以使用DISCARD命令。
  4. 如果需要提交事务,可以使用EXEC命令,Redis会依次执行在MULTI和EXEC之间的命令。
  5. 如果在事务执行期间,被监视的键发生了变化,事务会被取消。

需要注意的是,Redis的事务机制并不同于传统数据库的事务,它不支持回滚和隔离级别。事务块中的命令在EXEC执行时会一次性执行,但如果在事务执行过程中发生了错误,错误信息会被记录,但不会影响后续命令的执行。

集群

Redis集群有哪些方案, 知道嘛 ?

在Redis中提供的集群方案总共有三种:主从复制、哨兵模式、Redis分片集群

主从复制

介绍一下主从同步

是这样的,单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,可以搭建主从集群,实现读写分离。一般都是一主多从,主节点负责写数据,从节点负责读数据,主节点写入数据之后,需要把数据同步到从节点中

主从同步数据的流程

主从同步分为了两个阶段,一个是全量同步,一个是增量同步

  1. 全量同步是指从节点第一次与主节点建立连接的时候使用全量同步,流程是这样的:

    • 第一:从节点请求主节点同步数据,其中从节点会携带自己的replication id和offset偏移量。
    • 第二:主节点判断是否是第一次请求,主要判断的依据就是,主节点与从节点是否是同一个replication id,如果不是,就说明是第一次同步,那主节点就会把自己的replication id和offset发送给从节点,让从节点与主节点的信息保持一致。
    • 第三:在同时主节点会执行bgsave,生成rdb文件后,发送给从节点去执行,从节点先把自己的数据清空,然后执行主节点发送过来的rdb文件,这样就保持了一致
      当然,如果在rdb生成执行期间,依然有请求到了主节点,而主节点会以命令的方式记录到缓冲区,缓冲区是一个日志文件,最后把这个日志文件发送给从节点,这样就能保证主节点与从节点完全一致了,后期再同步数据的时候,都是依赖于这个日志文件,这个就是全量同步
  2. 增量同步指的是,当从节点服务重启之后,数据就不一致了,所以这个时候,从节点会请求主节点同步数据,主节点还是判断不是第一次请求,不是第一次就获取从节点的offset值,然后主节点从命令日志中获取offset值之后的数据,发送给从节点进行数据同步

哨兵模式

怎么保证Redis的高并发高可用

首先可以搭建主从集群,再加上使用redis中的哨兵模式,哨兵模式可以实现主从集群的自动故障恢复,里面就包含了对主从服务的监控、自动故障恢复、通知;如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主;同时Sentinel也充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端,所以一般项目都会采用哨兵的模式来保证redis的高并发高可用

你们使用redis是单点还是集群,哪种集群

我们当时使用的是主从(1主1从)加哨兵。一般单节点不超过10G内存,如果Redis内存不足则可以给不同服务分配独立的Redis主从节点。尽量不做分片集群。因为集群维护起来比较麻烦,并且集群之间的心跳检测和数据通信会消耗大量的网络带宽,也没有办法使用lua脚本和事务

redis集群脑裂,该怎么解决呢?

这个在项目很少见,不过脑裂的问题是这样的,我们现在用的是redis的哨兵模式集群的

有的时候由于网络等原因可能会出现脑裂的情况,就是说,由于redis master节点和redis salve节点和sentinel处于不同的网络分区,使得sentinel没有能够心跳感知到master,所以通过选举的方式提升了一个salve为master,这样就存在了两个master,就像大脑分裂了一样,这样会导致客户端还在old master那里写入数据,新节点无法同步数据,当网络恢复后,sentinel会将old master降为salve,这时再从新master同步数据,这会导致old master中的大量数据丢失。

关于解决的话,我记得在redis的配置中可以设置:第一可以设置最少的salve节点个数,比如设置至少要有一个从节点才能同步数据,第二个可以设置主从数据复制和同步的延迟时间,达不到要求就拒绝请求,就可以避免大量的数据丢失

分片集群

redis的分片集群有什么作用

分片集群主要解决的是,海量数据存储的问题,集群中有多个master,每个master保存不同数据,并且还可以给每个master设置多个slave节点,就可以继续增大集群的高并发能力。同时每个master之间通过ping监测彼此健康状态,就类似于哨兵模式了。当客户端请求可以访问集群任意节点,最终都会被转发到正确节点

Redis分片集群中数据是怎么存储和读取的?

在redis集群中是这样的,Redis 集群引入了哈希槽的概念,有 16384 个哈希槽,集群中每个主节点绑定了一定范围的哈希槽范围, key通过 CRC16 校验后对 16384 取模来决定放置哪个槽,通过槽找到对应的节点进行存储。取值的逻辑是一样的

为什么Redis这么快

Redis是单线程的,但是为什么还那么快?

  1. 完全基于内存的,C语言编写
  2. 采用单线程,避免不必要的上下文切换可竞争条件
  3. 使用多路I/O复用模型,非阻塞IO
    例如:bgsave 和 bgrewriteaof 都是在后台执行操作,不影响主线程的正常使用,不会产生阻塞

能解释一下I/O多路复用模型?

I/O多路复用是指利用单个线程来同时监听多个Socket ,并在某个Socket可读、可写时得到通知,从而避免无效的等待,充分利用CPU资源。目前的I/O多路复用都是采用的epoll模式实现,它会在通知用户进程Socket就绪的同时,把已就绪的Socket写入用户空间,不需要挨个遍历Socket来判断是否就绪,提升了性能。

其中Redis的网络模型就是使用I/O多路复用结合事件的处理器来应对多个Socket请求,比如,提供了连接应答处理器、命令回复处理器,命令请求处理器;

在Redis6.0之后,为了提升更好的性能,在命令回复处理器使用了多线程来处理回复事件,在命令请求处理器中,将命令的转换使用了多线程,增加命令转换速度,在命令执行的时候,依然是单线程

  • 20
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值