IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Redis面试题总结(2022版) -> 正文阅读

[大数据]Redis面试题总结(2022版)

Redis面试题总结(2022版)

本文是 Java 面试总结系列的第二篇文章,该专栏将整理和梳理笔者作为 Java 后端程序猿在日常工作以及面试中遇到的实际问题,通过这些问题的系统学习,也帮助笔者顺利拿到阿里、字节、华为、快手等Offer。由于笔者能力有限,其中大多答案来自巨人的肩膀并引以出处。同时若有错误或疏忽还望各位大佬们不吝指出…

标题地址
MySQL数据库面试题总结(2022版)https://blog.csdn.net/adminpd/article/details/122910606
Redis面试题总结(2022版)https://blog.csdn.net/adminpd/article/details/122934938

一、基础

常见考点

Redis 为何这么快?

  • 基于内存
  • 单线程减少上下文切换,同时保证原子性
  • IO多路复用
  • 高级数据结构(如 SDS、Hash以及跳表等)

ref 关于Redis处理高并发

缓存三大问题以及解决方案?

  • 缓存穿透:查询数据不存在

1)缓存空值

2)key 值校验,如布隆筛选器 ref 分布式布隆过滤器(Bloom Filter)详解(初版)

  • 缓存击穿:缓存过期,伴随大量对该 key 的请求

1)互斥锁

2)热点数据永不过期

3)熔断降级

  • 缓存雪崩:同一时间大批量的 key 过期

1)热点数据不过期

2)随机分散过期时间

ref 【面试】redis缓存穿透、缓存击穿、缓存雪崩区别和解决方案

缓存数据库双写不一致问题?

先删后写还是先写后删?

  • 先删缓存后写 DB

产生脏数据的概率较大(若出现脏数据,则意味着再不更新的情况下,查询得到的数据均为旧的数据)。

比如两个并发操作,一个是更新操作,另一个是查询操作,更新操作删除缓存后,查询操作没有命中缓存,先把老数据读出来后放到缓存中,然后更新操作更新了数据库。于是,在缓存中的数据还是老的数据,导致缓存中的数据是脏的,而且还一直这样脏下去了。

  • 删写 DB 再删缓存

产生脏数据的概率较小,但是会出现一致性的问题;若更新操作的时候,同时进行查询操作并命中,则查询得到的数据是旧的数据。但是不会影响后面的查询。

解决方案

1)缓存设置过期时间,实现最终一致性;

2)Cannel 等中间件监听 binlog 进行异步更新。

ref 更新数据时,是先删除缓存再更新DB,还是先更新DB再删除缓存?

如何保证 Redis 的高并发?

Redis 通过主从加集群架构,实现读写分离,主节点负责写,并将数据同步给其他从节点,从节点负责读,从而实现高并发。

ref 如何保证Redis的高并发

Redis 如何保证原子性?

常用命令

Redis 有哪些常用操作?

  • 终端连接:redis-cli -h 127.0.0.1 -p 6379
  • key
keys *  # 获取所有的key
select 0  # 选择第一个库
move myString 1  # 将当前的数据库key移动到某个数据库,目标库有,则不能移动
flush db  # 清除指定库
randomkey  # 随机key
type key  # 类型
    
set key1 value1   # 设置key
get key1  # 获取key
mset key1 value1 key2 value2 key3 value3
mget key1 key2 key3
del key1  # 删除key
exists key  # 判断是否存在key
expire key 10  # 10s 过期
pexpire key  # 1000 毫秒
persist key  # 删除过期时间
  • string
  • hash
  • list
  • set
  • set
  • 订阅发布
subscribe chat1 # 订阅频道
publish chat1 "hell0 ni hao"  # 发布消息
pubsub channels  # 查看频道
pubsub numsub chat1  # 查看某个频道的订阅者数量
unsubscrible chat1  # 退订指定频道 或 punsubscribe java.*
psubscribe java.*  # 订阅一组频道
  • 事务
  • 备份

ref redis常用命令大全
ref 随笔分类 - Redis

数据结构

Redis 有哪些数据结构?

  • 字符串 String
  • 字典 Hash
  • 列表 List
  • 集合 Set
  • 有序集合 Zset

有序集合 Zset 的底层实现?

zset 是 Redis 中一个非常重要的数据结构,其底层是基于跳表(skip list) 实现的。

跳表是一种随机化的数据结构,基于并联的链表,实现简单,插入、删除、查找的复杂度均为 O(logN)。简单说来跳表也是链表的一种,只不过它在链表的基础上增加了跳跃功能,正是这个跳跃的功能,使得在查找元素时,跳表能够提供 O(logN) 的时间复杂度。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jJeOB8nN-1644857707745)(https://upload-images.jianshu.io/upload_images/4286978-1c82913df845e4df.png)]

跳表为了避免每次插入或删除带来的额外操作,不要求上下相邻两层链表之间的节点个数有严格的对应关系,而是为每个节点随机出一个层数(level)。而且新插入一个节点不会影响其它节点的层数。因此,插入操作只需要修改插入节点前后的指针,而不需要对很多节点都进行调整。

ref Redis内部数据结构详解(6)——skiplist

Zset 为何不使用红黑树等平衡树?

1)跳跃表范围查询比平衡树操作简单。 因为平衡树在查询到最小值的时还需要采用中序遍历去查询最大值。 而跳表只需要在找到最小值后,对第一层的链表遍历即可。

2)平衡树的删除和插入需要对子树进行相应的调整,而跳表只需要修改相邻的节点即可。

3)跳表和平衡树的查询操作都是O(logN)的时间复杂度。

4)从整体上来看,跳表算法实现的难度要低于平衡树。

ref redis中的Zset原理

什么是简单动态字符串 SDS?

Redis 是基于 C 语言写的,但并未直接使用 C 语言中的字符串,而是自己构建了一种新的字符串数据结构—— Simple Dynamic String。

struct sdshdr{
     //记录buf数组中已使用字节的数量
     //等于 SDS 保存字符串的长度
     int len;
     //记录 buf 数组中未使用字节的数量
     int free;
     //字节数组,用于保存字符串
     char buf[];
}

从上面的定义我们不妨看出,SDS 相比原生字符串可以:

  • 常数复杂度获取字符串长度
  • 杜绝缓冲区溢出
  • 减少修改字符串的内存重新分配次数
  • 二进制安全

ref Redis详解(四)------ redis的底层数据结构

数据存储

Redis 的数据过期策略是什么?

在回答词问题之前,首先需要回答另一个问题,就是如何设置 Redis 中数据的过期时间?

1)expire key time (以秒为单位)–这是最常用的方式
2)setex(String key, int seconds, String value) --字符串独有的方式

除了字符串自己独有设置过期时间的方法外,其他方法都需要依靠 expire 方法来设置时间,如果没有设置时间,那缓存就是永不过期。 如果设置了过期时间,使用 persist key 让缓存永不过期。

常见的过期策略

  • 定时删除

在设置 key 的过期时间的同时,为该 key 创建一个定时器,让定时器在 key 的过期时间来临时,对 key 进行删除。

  • 惰性删除
  • 定期删除

每隔一段时间执行一次删除(在 redis.conf 配置文件设置,1s 刷新的频率)过期 key 操作。

Redis采用的过期策略

Redis 采用了惰性删除+定期删除的方式处理过期数据。

  • 惰性删除流程

1)在进行get或setnx等操作时,先检查key是否过期;

2)若过期,删除key,然后执行相应操作;

3)若没过期,直接执行相应操作。

  • 定时删除流程

其核心是对指定个数个库的每一个库随机删除小于等于指定个数个过期 key:

1)历每个数据库(就是 redis.conf 中配置的 “database” 数量,默认为16);

2)检查当前库中的指定个数个 key (默认是每个库检查 20 个,相当于该循环执行 20 次):

2.1)如果当前库中没有一个 key 设置了过期时间,直接执行下一个库的遍历;

2.2)随机获取一个设置了过期时间的 key,检查是否过期,如果过期则删除;

2.3)判断定期删除操作是否已经达到指定时长,若已经达到,直接退出定期删除。

ref Redis学习笔记–Redis数据过期策略详解

持久化文件对过期策略的处理?

过期 key 是不会写入 RDB 和 AOF 文件,同时数据恢复时也会做过期验证。

Redis 有哪些内存淘汰机制?

Redis 作为一个内存数据库,在内存空间不足的时候,为了保证命中率,就会和我们操作系统中的页面置换算法类似,选择一定的数据淘汰策略。

  • volatile(设置过期时间的数据集)

1)volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。

2)volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。

3)volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。

4)volatile-lfu:从已设置过期时间的数据集挑选使用频率最低的数据淘汰。

  • allkeys(所以数据集)

5)allkeys-lru:从数据集中挑选最近最少使用的数据淘汰

6)allkeys-lfu:从数据集中挑选使用频率最低的数据淘汰。

7)allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰

  • no-enviction

8)no-enviction(驱逐):禁止驱逐数据,这也是默认策略。

意思是当内存不足以容纳新入数据时,新写入操作就会报错,请求可以继续进行,线上任务也不能持续进行,采用 no-enviction 策略可以保证数据不被丢失。

PS:在 redis.config 文件中,我们可以设置 maxmemory 的值来配置 Redis 的最大占用内存字节数。

ref Redis5.0数据淘汰策略详解

Redis 有哪些持久化机制?

RDB 机制

RDB 持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方式。也就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为 dump.rdb。

RDB 支持 同步(save 命令)、后台异步(bgsave)以及自动配置三种方式触发。

优点

  • RDB 文件紧凑,全量备份,非常适合用于进行备份和灾难恢复
  • 生成 RDB 文件时支持异步处理,主进程不需要进行任何磁盘IO操作
  • RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快

缺点
RDB 快照是一次全量备份,存储的是内存数据的二进制序列化形式,存储上非常紧凑。且在快照持久化期间修改的数据不会被保存,可能丢失数据。

AOF 机制

全量备份总是耗时的,有时候我们提供一种更加高效的方式 AOF,其工作机制更加简单:会将每一个收到的写命令追加到文件中。

随着时间推移,AOF 持久化文件也会变的越来越大。为了解决此问题,Redis 提供了 bgrewriteaof 命令,作用是 fork 出一条新进程将内存中的数据以命令的方式保存到临时文件中,完成对AOF 文件的重写

AOF 也有三种触发方式:1)每修改同步 always 2)每秒同步 everysec 3)不同no:从不同步。

优点

  • AOF 可以更好的保护数据不丢失,一般 AOF 隔 1 秒通过一个后台线程执行一次 fsync 操作
  • AOF 日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损
  • AOF 日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写
  • AOF 日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复

缺点

  • 对于同一份数据来说,AOF 日志文件通常比 RDB 数据快照文件更大

  • AOF开启后,支持的写 QPS 会比RDB支持的写 QPS 低,因为 AOF 一般会配置成每秒 fsync 一次日志文件,当然,每秒一次 fsync,性能也还是很高的

ref 详解Redis中两种持久化机制RDB和AOF

RDB 和 AOF 该如何选择?

通过前面章节我们已经明白了两种机制的原理,接下来就该结合具体需求进行机制的选择,通常情况我们是二者结合使用的。

Pipeline

什么是 Redis 的 Pipeline?

ref Redis系列十:Pipeline详解

原生批命令 (mset, mget) 与 Pipeline 区别?

1)原生批命令是原子性,pipeline是非原子性

2)原生批命令一命令多个 key, 但 pipeline 支持多命令(存在事务),非原子性

3)原生批命令是服务端实现,而 pipeline 需要服务端与客户端共同完成

多线程

讲讲 Redis 6 中的多线程?

ref Redis 6.0 新特性-多线程连环13问!

二、集群

模式

Redis 集群搭建有几种模式?

  • 主从模式

和 MySQL 需要主从复制的原因一样,Redis 虽然读写速度非常快,但是也会产生性能瓶颈,特别是在读压力上,为了分担压力,Redis 支持主从复制。Redis 的主从结构一主一从,一主多从或级联结构,复制类型可以根据是否是全量而分为全量同步和增量同步。

  • 哨兵模式

在主从复制实现之后,如果想对 master 进行监控,Redis 提供了一种哨兵机制,哨兵的含义就是监控 Redis 系统的运行状态,通过投票机制,从 slave 中选举出新的 master 以保证集群正常运行。

还可以启用多个哨兵进行监控以保证集群足够稳健,这种情况下,哨兵不仅监控主从服务,哨兵之间也会相互监控。

  • Cluster 集群模式

ref Redis集群搭建的三种方式

Redis 主从复制的实现?

主从复制可以根据需要分为全量同步增量同步两种方式。

全量同步

Redis 全量复制一般发生在 slave 的初始阶段,这时 slave 需要将 master 上的数据都复制一份,具体步骤如下:

1)slave 连接 master,发送 SYNC 命令;

2)master 接到 SYNC 命令后执行 BGSAVE 命令生产 RDB 文件,并使用缓冲区记录此后执行的所有写命令;

3)master 执行完 BGSAVE 后,向所有的 slave 发送快照文件,并在发送过程中继续记录执行的写命令;

4)slave 收到快照后,丢弃所有的旧数据,载入收到的数据;

5)master 快照发送完成后就会开始向 slave 发送缓冲区的写命令;

6)slave 完成对快照的载入,并开始接受命令请求,执行来自 master 缓冲区的写命令;

7)slave 完成上面的数据初始化后就可以开始接受用户的读请求了。

增量同步

增量复制实际上就是在 slave 初始化完成后开始正常工作时 master 发生写操作同步到 slave 的过程。增量复制的过程主要是 master 每执行一个写命令就会向 slave 发送相同的写命令,slave 接受并执行写命令,从而保持主从一致。

ref Redis主从复制原理总结

Redis 的主从同步策略?

主从同步刚连接的时候进行全量同步,全量同步结束后开始增量同步。

如果有需要,slave 在任何时候都可以发起全量同步,其主要策略就是无论如何首先会尝试进行增量同步,如果失败则会要求 slave 进行全量同步,之后再进行增量同步。

注意:如果多个 slave 同时断线需要重启的时候,因为只要 slave 启动,就会和 master 建立连接发送SYNC请求和主机全量同步,如果多个同时发送 SYNC 请求,可能导致 master IO 突增而发送宕机。所以我们要避免多个 slave 同时恢复重启的情况。

哨兵模式的原理?

哨兵主要用于管理多个 Redis 服务器,主要有以下三个任务:监控、提醒以及故障转移

每个哨兵会向其它哨兵、master、slave 定时发送消息,以确认对方是否还存活。如果发现对方在配置的指定时间内未回应,则暂时认为对方已挂。若“哨兵群”中的多数 sentinel 都报告某一 master 没响应,系统才认为该 master “彻底死亡”,通过一定的 vote 算法从剩下的 slave 节点中选一台提升为 master,然后自动修改相关配置。

哨兵模式故障迁移流程?

1)首先是从主服务器的从服务器中选出一个从服务器作为新的主服务器。

选点的依据依次是

网络连接正常 -> 5 秒内回复过 INFO 命令 -> 10*down-after-milliseconds 内与主连接过的 -> 从服务器优先级 -> 复制偏移量 -> 运行id较小的。

2)选出之后通过 slaveif no ont 将该从服务器升为新主服务器;

3)然后再通过 slaveof ip port 命令让其他从服务器复制该信主服务器。

缺点

  • 主从服务器的数据要经常进行主从复制,这样会造成性能下降
  • 当主服务器宕机后,从服务器切换成主服务器的那段时间,服务是不可用的

Cluster 模式的原理?

其实现原理就是一致性 Hash。Redis Cluster 中有一个 16384 长度的槽的概念,他们的编号为 0、1、2、3 …… 16382、16383。这个槽是一个虚拟的槽,并不是真正存在的。正常工作的时候,Redis Cluster 中的每个 Master 节点都会负责一部分的槽,当有某个 key 被映射到某个 Master 负责的槽,那么这个 Master 负责为这个 key 提供服务。至于哪个 Master 节点负责哪个槽,这是可以由用户指定的,也可以在初始化的时候自动生成(redis-trib.rb脚本)。这里值得一提的是,在 Redis Cluster 中,只有 Master 才拥有槽的所有权,如果是某个 Master 的 slave,这个slave只负责槽的使用,但是没有所有权。

什么是一致性 Hash 以及解决什么问题?

一致性 hash 其实是普通 hash 算法的改良版,其 hash 计算方法没有变化,但是 hash 空间发生了变化,由原来的线性的变成了环。

缓存 key 通过 hash 计算之后得到在 hash 环中的位置,然后顺时针方向找到第一个节点,这个节点就是存放 key 的节点。

由此可见,一致性 hash 主要是为了解决普通 hash 中扩容和宕机的问题。

同时还可以通过虚拟节点来解决数据倾斜的问题:就是在节点稀疏的 hash 环上对物理节点虚拟出一部分虚拟节点,key 会打到虚拟节点上面,而虚拟节点上的 key 实际也是映射到物理节点上的,这样就避免了数据倾斜导致单节点压力过大导致节点雪崩的问题。

ref 什么是一致性hash?

Cluster 的分片机制?

为了使得集群能够水平扩展,首要解决的问题就是如何将整个数据集按照一定的规则分配到多个节点上。对于客户端请求的 key,根据公式 HASH_SLOT=CRC16(key) mod 16384,计算出映射到哪个分片上。而对于 CRC16 算法产生的 hash 值会有 16bit,可以产生 2^16-=65536 个值。

Redis 集群提供了灵活的节点扩容和收缩方案。在不影响集群对外服务的情况下,可以为集群添加节点进行扩容也可以下线部分节点进行缩容。可以说,槽是 Redis 集群管理数据的基本单位,集群伸缩就是槽和数据在节点之间的移动。

集群扩容

当一个 Redis 新节点运行并加入现有集群后,我们需要为其迁移槽和数据。首先要为新节点指定槽的迁移计划,确保迁移后每个节点负责相似数量的槽,从而保证这些节点的数据均匀。

1)首先启动一个 Redis 节点,记为 M4。
2)使用 cluster meet 命令,让新 Redis 节点加入到集群中。新节点刚开始都是主节点状态,由于没有负责的槽,所以不能接受任何读写操作,后续给他迁移槽和填充数据。
3)对 M4 节点发送 cluster setslot { slot } importing { sourceNodeId } 命令,让目标节点准备导入槽的数据。
4)对源节点,也就是 M1,M2,M3 节点发送 cluster setslot { slot } migrating { targetNodeId } 命令,让源节>点准备迁出槽的数据。
4)源节点执行 cluster getkeysinslot { slot } { count } 命令,获取 count 个属于槽 { slot } 的键,然后执行步骤>六的操作进行迁移键值数据。
5)在源节点上执行 migrate { targetNodeIp} " " 0 { timeout } keys { key… } 命令,把获取的键通过 pipeline 机制>批量迁移到目标节点,批量迁移版本的 migrate 命令在 Redis 3.0.6 以上版本提供。
6)重复执行步骤 5 和步骤 6 直到槽下所有的键值数据迁移到目标节点。
7)向集群内所有主节点发送 cluster setslot { slot } node { targetNodeId } 命令,通知槽分配给目标节点。为了>保证槽节点映射变更及时传播,需要遍历发送给所有主节点更新被迁移的槽执行新节点。

集群收缩

收缩节点就是将 Redis 节点下线,整个流程需要如下操作流程。

1)首先需要确认下线节点是否有负责的槽,如果是,需要把槽迁移到其他节点,保证节点下线后整个集群槽节点映射的完整性。
2)当下线节点不再负责槽或者本身是从节点时,就可以通知集群内其他节点忘记下线节点,当所有的节点忘记改节点后可以正常关闭。

ref Redis Cluster数据分片机制

客户端如何路由?

既然 Redis 集群中的数据是分片存储的,那我们该如何知道某个 key 存在哪个节点上呢?即我们需要一个查询路由,该路由根据给定的 key,返回存储该键值的机器地址

常规的实现方式便是采用如下图所示的代理方案,即采用一个中央节点(比如HDFS中的NameNode)来管理所有的元数据,但是这样的方案带来的最大问题就是代理节点很容易成为访问的瓶颈,当读写并发量高的时候,代理节点会严重的拖慢整个系统的性能。

Redis 并没有选择使用代理,而是客户端直接连接每个节点。Redis 的每个节点中都存储着整个集群的状态,集群状态中一个重要的信息就是每个桶的负责节点。在具体的实现中,Redis 用一个大小固定为 CLUSTER_SLOTS 的 clusterNode 数组 slots 来保存每个桶的负责节点。

typedef struct clusterNode {
    ...
    unsigned char slots[CLUSTER_SLOTS/8];
    ...
} clusterNode;

typedef struct clusterState {
    // slots记录每个桶被哪个节点存储
    clusterNode *slots[CLUSTER_SLOTS];
    ...
} clusterState;

在集群模式下,Redis 接收任何键相关命令时首先计算键对应的桶编号,再根据桶找出所对应的节点,如果节点是自身,则处理键命令;否则回复 MOVED 重定向错误,通知客户端请求正确的节点,这个过程称为 MOVED 重定向。重定向信息包含了键所对应的桶以及负责该桶的节点地址,根据这些信息客户端就可以向正确的节点发起请求。

ref Redis集群详解(上)

为什么是 163834 个槽位?

从前面的 Cluster 集群原理我们已经了解到集群中的所有节点在握手成功后悔定期发送 ping/pong 消息,交换数据信息。

先来了解一下消息体传递了哪些数据:

上图展示的消息体结构无外乎是一些节点标识,IP,端口号,发送时间等,但需要注意一下标红的 myslots 的 char 数组,长度为 16383/8,这其实是一个 bitmap,每一个位代表一个槽,如果该位为1,表示这个槽是属于这个节点的。

  • 消息体大小上的考量

至于这个消息体有多大?显然最占空间的就是 myslots 数组:16384÷8÷1024=2kb。如果槽位达到 65536,则所占空间提升到 65536÷8÷1024=8kb,极大浪费带宽。

  • Redis 集群主节点数量基本不可能超过 1000 个

集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。

  • 槽位越小,节点少的情况下,压缩比高

ref 为什么Redis集群有16384个槽

集群的故障发现与迁移?

故障发现

当集群内某个节点出现问题时,需要通过一种健壮的方式保证识别出节点是否发生了故障。Redis 集群内节点通过 ping/pong 消息实现节点通信,消息不但可以传播节点槽信息,还可以传播其他状态如:主从状态、节点故障等。因此故障发现也是通过消息传播机制实现的。 主要环节包括:

  • 主观下线(PFAIL-Possibly Fail)

集群中每个节点都会定期向其他节点发送ping消息,接收节点回复pong消息作为响应。如果在cluster-node-timeout时间内通信一直失败,则发送节点会认为接收节点存在故障,把接收节点标记为主观下线(PFail)状态。

  • 客观下线(Fail)

Redis 集群对于节点最终是否故障判断非常严谨,只有一个节点认为主观下线并不能准确判断是否故障。当某个节点判断另一个节点主观下线后,相应的节点状态会跟随消息在集群内传播,通过Gossip消息传播,集群内节点不断收集到故障节点的下线报告。当半数以上持有槽的主节点都标记某个节点是主观下线时。触发客观下线流程。

客观下线流程

故障恢复

故障节点变为客观下线后,如果下线节点是持有槽的主节点则需要在它的从节点中选出一个替换它,从而保证集群的高可用。下线主节点的所有从节点承担故障恢复的义务,当从节点通过内部定时任务发现自身复制的主节点进入客观下线时,将会触发故障恢复流程。

ref 018.Redis Cluster故障转移原理

三、场景

如何设置 Key 当天失效?

  • expireAt
  • key 值带上时间戳

如何实现分布式锁?

  • 「互斥性」: 任意时刻,只有一个客户端能持有锁
  • 「锁超时释放」:持有锁超时,可以释放,防止不必要的资源浪费,也可以防止死锁
  • 「可重入性」:一个线程如果获取了锁之后,可以再次对其请求加锁
  • 「高性能和高可用」:加锁和解锁需要开销尽可能低,同时也要保证高可用,避免分布式锁失效
  • 「安全性」:锁只能被持有的客户端删除,不能被其他客户端删除

Redison 底层原理:

ref Redis实现分布式锁的7种方案,及正确使用姿势!

RedLock 加锁步骤:

1)按顺序向集群中所有 master 节点请求加锁;

2)根据设置的超时时间来判断,是不是要跳过该 master 节点;

3)如果大于等于半数节点( N/2+1 )加锁成功,并且使用的时间小于锁的有效期,即可认定加锁成功啦;

4)如果获取锁失败,解锁!

如何实现排行榜功能?

活动运营中经常会有这样的需求:1)Value 值排序 2)Value 相同按时间排序。

  • 使用 MySQL:
EXPLAIN SELECT
    *
FROM
    (
        SELECT
            @rank := @rank + 1 AS rank,
            s.uid AS uid,
            s.coin AS coin
        FROM
            `user` s,
            (SELECT @rank := 0) r
        ORDER BY
            coin DESC,
            create_time
    ) q
WHERE
    q.uid = 'xxx';
  • 使用 Redis:
# 插入或者更新数据
Long zadd(final String key, final double score, final String member)
key : 排行榜的名字
memeber : 用户
score : 用户的分数
# 获取用户分数
Double zscore(String key, final String member)
# 获取用户的排名
Long zrevrank(final String key, final String member):(score从大到小,从0开始,所以需要加1)
Long zrank(final String key, final String member):(score从小到大,从0开始,所以需要加1)
# 获取某个范围内的用户排名
Set<Tuple> zrevrangeWithScoresBytes(String key, final long start, final long end) (从大到小)
Set<Tuple> zrangeWithScoresBytes(String key, final long start, final long end) (从小到大)
start : 开始排名
end : 结束排名
Tuple :

同时为了实现先到先得,zset 中的 score 并不能仅仅是排序的 Value 值,还需加入时间戳因子:score = (value * 10000000000(十次方)) + (100000000000(十一次方) - ts)

由于时间戳相同一个月的时间内,头三位是相等的,即我们还可以进一步压缩时间位数以提高排序值的精度。

ref redis zset做排行榜

四、优化

大 key 优化

为什么要优化大 key

ref redis大key优化

热点 key 优化

如何优化热点 key?

热 key 带来的问题:请求到的分片过于集中,超过单台 Server 的性能极限。

解决方案:

1)服务端缓存:即将热点数据缓存至服务端的内存中;

2)备份热点Key:即将热点Key+随机数,随机分配至 Redis 其它节点中。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-02-16 13:11:15  更:2022-02-16 13:11:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:34:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码