- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章2021年最新Redis面试题汇总(3)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
主从复制、哨兵模式、集群模式.
在当前最新的 redis 6.0 中,主从复制的完整过程如下:
1)开启主从复制 。
通常有以下三种方式:
slaveof
<masterip
> <masterport
>slaveof
<masterip
> <masterport
>slaveof
<masterip
> <masterport
>注:在 redis 5.0 之后,slaveof 相关命令和配置已经被替换成 replicaof,例如 replicaof <masterip> <masterport>。为了兼容旧版本,通过配置的方式仍然支持 slaveof,但是通过命令的方式则不行了.
2)建立套接字(socket)连接 。
slave 将根据指定的 ip 地址和端口,向 master 发起套接字(socket)连接,master 在接受(accept) slave 的套接字连接之后,为该套接字创建相应的客户端状态,此时连接建立完成.
3)发送ping命令 。
slave 向 master 发送一个 ping 命令,以检査套接字的读写状态是否正常、 master 能否正常处理命令请求.
4)身份验证 。
slave 向 master 发送 auth password 命令来进行身份验证.
5)发送端口信息 。
在身份验证通过后后, slave 将向 master 发送自己的监听端口号, master 收到后记录在 slave 所对应的客户端状态的 slave_listening_port 属性中.
6)发送ip地址 。
如果配置了 slave_announce_ip,则 slave 向 master 发送 slave_announce_ip 配置的 ip 地址, master 收到后记录在 slave 所对应的客户端状态的 slave_ip 属性.
该配置是用于解决服务器返回内网 ip 时,其他服务器无法访问的情况。可以通过该配置直接指定公网 ip.
7)发送capa 。
capa 全称是 capabilities,这边表示的是同步复制的能力。slave 会在这一阶段发送 capa 告诉 master 自己具备的(同步)复制能力, master 收到后记录在 slave 所对应的客户端状态的 slave_capa 属性.
8)数据同步 。
slave 将向 master 发送 psync 命令, master 收到该命令后判断是进行部分重同步还是完整重同步,然后根据策略进行数据的同步.
9)命令传播 。
当完成了同步之后,就会进入命令传播阶段,这时 master 只要一直将自己执行的写命令发送给 slave ,而 slave 只要一直接收并执行 master 发来的写命令,就可以保证 master 和 slave 一直保持一致了.
以部分重同步为例,主从复制的核心步骤流程图如下:
哨兵(sentinel) 是 redis 的高可用性解决方案:由一个或多个 sentinel 实例组成的 sentinel 系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器.
sentinel 可以在被监视的主服务器进入下线状态时,自动将下线主服务器的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求.
检查主观下线状态 。
在默认情况下,sentinel 会以每秒一次的频率向所有与它创建了命令连接的实例(包括主服务器、从服务器、其他 sentinel 在内)发送 ping 命令,并通过实例返回的 ping 命令回复来判断实例是否在线.
如果一个实例在 down-after-miliseconds 毫秒内,连续向 sentinel 返回无效回复,那么 sentinel 会修改这个实例所对应的实例结构,在结构的 flags 属性中设置 sri_s_down 标识,以此来表示这个实例已经进入主观下线状态.
检查客观下线状态 。
当 sentinel 将一个主服务器判断为主观下线之后,为了确定这个主服务器是否真的下线了,它会向同样监视这一服务器的其他 sentinel 进行询问,看它们是否也认为主服务器已经进入了下线状态(可以是主观下线或者客观下线).
当 sentinel 从其他 sentinel 那里接收到足够数量(quorum,可配置)的已下线判断之后,sentinel 就会将服务器置为客观下线,在 flags 上打上 sri_o_down 标识,并对主服务器执行故障转移操作.
当哨兵监测到某个主节点客观下线之后,就会开始故障转移流程。核心流程如下:
发起一次选举,选举出领头 sentinel领头 sentinel 在已下线主服务器的所有从服务器里面,挑选出一个从服务器,并将其升级为新的主服务器。领头 sentinel 将剩余的所有从服务器改为复制新的主服务器。领头 sentinel 更新相关配置信息,当这个旧的主服务器重新上线时,将其设置为新的主服务器的从服务器.
哨兵模式最大的缺点就是所有的数据都放在一台服务器上,无法较好的进行水平扩展.
为了解决哨兵模式存在的问题,集群模式应运而生。在高可用上,集群基本是直接复用的哨兵模式的逻辑,并且针对水平扩展进行了优化.
集群模式具备的特点如下:
集群的架构图如下所示:
故障转移的第一步就是选举出新的主节点,以下是集群选举新的主节点的方法:
1)当从节点发现自己正在复制的主节点进入已下线状态时,会发起一次选举:将 currentepoch(配置纪元)加1,然后向集群广播一条 clustermsg_type_failover_auth_request 消息,要求所有收到这条消息、并且具有投票权的主节点向这个从节点投票.
2)其他节点收到消息后,会判断是否要给发送消息的节点投票,判断流程如下:
如果通过以上所有校验,那么主节点将向要求投票的从节点返回一条 clustermsg_type_failover_auth_ack 消息,表示这个主节点支持从节点成为新的主节点.
3)每个参与选举的从节点都会接收 clustermsg_type_failover_auth_ack 消息,并根据自己收到了多少条这种消息来统计自己获得了多少个主节点的支持.
4)如果集群里有n个具有投票权的主节点,那么当一个从节点收集到大于等于n/2+1 张支持票时,这个从节点就会当选为新的主节点。因为在每一个配置纪元里面,每个具有投票权的主节点只能投一次票,所以如果有 n个主节点进行投票,那么具有大于等于 n/2+1 张支持票的从节点只会有一个,这确保了新的主节点只会有一个.
5)如果在一个配置纪元里面没有从节点能收集到足够多的支持票,那么集群进入一个新的配置纪元,并再次进行选举,直到选出新的主节点为止.
这个选举新主节点的方法和选举领头 sentinel 的方法非常相似,因为两者都是基于 raft 算法的领头选举(leader election)方法来实现的.
例如:集群已经对外提供服务,原来有3分片,准备新增2个分片,怎么在不下线的情况下,无损的从原有的3个分片指派若干个槽给这2个分片?
redis 使用了 ask 错误来保证在线扩容的安全性.
在槽的迁移过程中若有客户端访问,依旧先访问源节点,源节点会先在自己的数据库里面査找指定的键,如果找到的话,就直接执行客户端发送的命令.
如果没找到,说明该键可能已经被迁移到目标节点了,源节点将向客户端返回一个 ask 错误,该错误会指引客户端转向正在导入槽的目标节点,并再次发送之前想要执行的命令,从而获取到结果.
ask错误 。
在进行重新分片期间,源节点向目标节点迁移一个槽的过程中,可能会出现这样一种情况:属于被迁移槽的一部分键值对保存在源节点里面,而另一部分键值对则保存在目标节点里面.
当客户端向源节点发送一个与数据库键有关的命令,并且命令要处理的数据库键恰好就属于正在被迁移的槽时。源节点会先在自己的数据库里面査找指定的键,如果找到的话,就直接执行客户端发送的命令.
否则,这个键有可能已经被迁移到了目标节点,源节点将向客户端返回一个 ask 错误,指引客户端转向正在导入槽的目标节点,并再次发送之前想要执行的命令,从而获取到结果.
一个事务从开始到结束通常会经历以下3个阶段:
1)事务开始:multi 命令将执行该命令的客户端从非事务状态切换至事务状态,底层通过 flags 属性标识.
2)命令入队:当客户端处于事务状态时,服务器会根据客户端发来的命令执行不同的操作:
3)事务执行:当一个处于事务状态的客户端向服务器发送 exec 命令时,服务器会遍历事务队列,执行队列中的所有命令,最后将结果全部返回给客户端.
不过 redis 的事务并不推荐在实际中使用,如果要使用事务,推荐使用 lua 脚本,redis 会保证一个 lua 脚本里的所有命令的原子性.
redis 官网展示的 java 客户端如下图所示,其中官方推荐的是标星的3个:jedis、redisson 和 lettuce.
1)keys *java* 命令,该命令性能很好,但是在数据量特别大的时候会有性能问题 。
2)scan 0 match *java* 命令,基于游标的迭代器,更好的选择 。
scan 命令是一个基于游标的迭代器(cursor based iterator): scan 命令每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 scan 命令的游标参数, 以此来延续之前的迭代过程.
当 scan 命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束.
redis 本身提供了一些组件来实现消息队列的功能,但是多多少少都存在一些缺点,相比于市面上成熟的消息队列,例如 kafka、rocket mq 来说并没有优势,因此目前我们并没有使用 redis 来做消息队列.
关于 redis 做消息队列的常见方案主要有以下:
1)redis 5.0 之前可以使用 list(blocking)、pub/sub 等来实现轻量级的消息发布订阅功能组件,但是这两种实现方式都有很明显的缺点,两者中相对完善的 pub/sub 的主要缺点就是消息无法持久化,如果出现网络断开、redis 宕机等,消息就会被丢弃.
2)为了解决 pub/sub 模式等的缺点,redis 在 5.0 引入了全新的 stream,stream 借鉴了很多 kafka 的设计思想,有以下几个特点:
redis stream 相比于 pub/sub 已经有很明显的改善,但是相比于 kafka,其实没有优势,同时存在:尚未经过大量验证、成本较高、不支持分区(partition)、无法支持大规模数据等问题.
1)数据结构:memcached 支持简单的 key-value 数据结构,而 redis 支持丰富的数据结构:string、list、set、hash、sortedset 等.
2)数据存储:memcached 和 redis 的数据都是全部在内存中.
网上有一种说法 “当物理内存用完时,redis可以将一些很久没用到的 value 交换到磁盘,同时在内存中清除”,这边指的是 redis 里的虚拟内存(virtual memory)功能,该功能在 redis 2.0 被引入,但是在 redis 2.4 中被默认关闭,并标记为废弃,而在后续版中被完全移除.
3)持久化:memcached 不支持持久化,redis 支持将数据持久化到磁盘 。
4)灾难恢复:实例挂掉后,memcached 数据不可恢复,redis 可通过 rdb、aof 恢复,但是还是会有数据丢失问题 。
5)事件库:memcached 使用 libevent 事件库,redis 自己封装了简易事件库 aeevent 。
6)过期键删除策略:memcached 使用惰性删除,redis 使用惰性删除+定期删除 。
7)内存驱逐(淘汰)策略:memcached 主要为 lru 算法,redis 当前支持8种淘汰策略,见本文第16题 。
8)性能比较 。
本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注我的更多内容! 。
原文链接:https://blog.csdn.net/weixin_39709134/article/details/116998066 。
最后此篇关于2021年最新Redis面试题汇总(3)的文章就讲到这里了,如果你想了解更多关于2021年最新Redis面试题汇总(3)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我有一个关于 Redis Pubsub 的练习,如下所示: 如果发布者发布消息但订阅者没有收到服务器崩溃。订阅者如何在重启服务器时收到该消息? 请帮帮我,谢谢! 最佳答案 在这种情况下,消息将永远消失
我们正在使用 Service Stack 的 RedisClient 的 BlockingDequeue 来保存一些数据,直到它可以被处理。调用代码看起来像 using (var client =
我有一个 Redis 服务器和多个 Redis 客户端。每个 Redis 客户端都是一个 WebSocket+HTTP 服务器,其中包括管理 WebSocket 连接。这些 WebSocket+HTT
我有多个 Redis 实例。我使用不同的端口创建了一个集群。现在我想将数据从预先存在的 redis 实例传输到集群。我知道如何将数据从一个实例传输到集群,但是当实例多于一个时,我无法做到这一点。 最佳
配置:三个redis集群分区,跨三组一主一从。当 Master 宕机时,Lettuce 会立即检测到中断并开始重试。但是,Lettuce 没有检测到关联的 slave 已经将自己提升为 master
我想根据从指定集合中检索这些键来删除 Redis 键(及其数据集),例如: HMSET id:1 password 123 category milk HMSET id:2 password 456
我正在编写一个机器人(其中包含要禁用的命令列表),用于监视 Redis。它通过执行禁用命令,例如 (rename-command ZADD "")当我重新启动我的机器人时,如果要禁用的命令列表发生变化
我的任务是为大量听众使用发布/订阅。这是来自 docs 的订阅的简化示例: r = redis.StrictRedis(...) p = r.pubsub() p.subscribe('my-firs
我一直在阅读有关使用 Redis 哨兵进行故障转移的内容。我打算有1个master+1个slave,如果master宕机超过1分钟,就把slave变成master。我知道这在 Sentinel 中是
与仅使用常规 Redis 和创建分片相比,使用 Redis 集群有哪些优势? 在我看来,Redis Cluster 更注重数据安全(让主从架构解决故障)。 最佳答案 我认为当您需要在不丢失任何数据的情
由于 Redis 以被动和主动方式使 key 过期, 有没有办法得到一个 key ,即使它的过期时间已过 (但 在 Redis 中仍然存在 )? 最佳答案 DEBUG OBJECT myKey 将返回
我想用redis lua来实现monitor命令,而不是redis-cli monitor。但我不知道怎么办。 redis.call('monitor') 不起作用。 最佳答案 您不能从 Redis
我读过 https://github.com/redisson/redisson 我发现有几个 Redis 复制设置(包括对 AWS ElastiCache 和 Azure Redis 缓存的支持)
Microsoft.AspNet.SignalR.Redis 和 StackExchange.Redis.Extensions.Core 在同一个项目中使用。前者需要StackExchange.Red
1. 认识 Redis Redis(Remote Dictionary Server)远程词典服务器,是一个基于内存的键值对型 NoSQL 数据库。 特征: 键值(key-value)型,value
1. Redis 数据结构介绍 Redis 是一个 key-value 的数据库,key 一般是 String 类型,但 value 类型多种多样,下面就举了几个例子: value 类型 示例 Str
1. 什么是缓存 缓存(Cache) 就是数据交换的缓冲区,是存贮数据的临时地方,一般读写性能较高。 缓存的作用: 降低后端负载 提高读写效率,降低响应时间 缓存的成本: 数据一致性成本 代码维护成本
我有一份记录 list 。对于我的每条记录,我都需要进行一些繁重的计算,因为我要在Redis中创建反向索引。为了达到到达记录,需要在管道中执行多个redis命令(sadd为100 s + set为1
我有一个三节点Redis和3节点哨兵,一切正常,所有主服务器和从属服务器都经过验证,并且哨兵配置文件已与所有Redis和哨兵节点一起更新,但是问题是当Redis主服务器关闭并且哨兵希望选举失败者时再次
我正在尝试计算Redis中存储的消息之间的响应时间。但是我不知道该怎么做。 首先,我必须像这样存储chat_messages的时间流 ZADD conversation:CONVERSATION_ID
我是一名优秀的程序员,十分优秀!