知乎高赞:为什么同样是分布式架构的Kafka需要Leader而Redis不需要

简介: 知乎高赞:为什么同样是分布式架构的Kafka需要Leader而Redis不需要

Redis不需要Leader这个观点其实有歧义,是不准确的,这个问题本质其实是涉及数据分片、数据副本一致性,接下来将为大家一一解答


1、Redis Cluster 架构


在Redis3.0版本开始,Redis引入了一种去中心化的集群架构,采用预分片的模式,一个集群中所有节点总共对应16384个槽位,在对一个key进行写入时,首先对key取hashcode,然后求模来映射到具体的某一个节点,其部署架构如下图所示:

9d5f885cc5e56f117a6bc16154ac1702.png

上述每一个节点中存储的数据都不一样,即每一个节点存储整体数据的一部分,并且为了实现去中心化每一个节点需要存储集群中所有key所对应存档的节点信息(即Key的路由信息),这样当客户端将查询key1的请求发送到redisA节点,但该key1实际存储在redisB节点,此时A节点需将该节点路由到实际存储该key的节点,内部实现一个重定向,从而实现访问任意一个节点都能查询到存储的值。


上述架构中是不需要存在Leader的,这也是所谓的集群去中心化设计思想的关键,但问题来了,如果集群中任意一个节点宕机不可用,存储在该节点中的数据就会丢失,为了解决这个问题,通常会引入主从架构,架构图如下所示:


f3b9c13f7aed6d71eff733eb3f542260.png

具体的做法是为每一个主节点引入一个或多个从节点,用来拷贝主节点的数据,上图中的每一个虚线框表示一个复制组,也称之为副本,副本之间的数据期望完全一致。


在主从架构中如何保证数据一致性呢?通常主从集群与客户端之间的交互方式有如下几种:


  • 客户端发送写请求到Master,在Master节点写入成功就返回给客户端,同时从节点异步复制数据,主从存在延迟,并且当主节点宕机存在丢数据的风险
  • 客户端发送写请求到Master,Master节点写入成功后,需要等待从从节点同样写入成功后才会向客户端返回成功,该方式会增大延迟,增加主从数据延迟,但还是无法避免主从数据不一致


上述两种情况,都无法确保数据在主从两个节点上的一致性


为什么同步双写也无法保证数据的一致性呢?

f324a0403ecdcb7255b67d13ca5387f7.png

客户端只有在master,slave同步写入成功后才会收到响应,乍一看,能提供一致性,其实不然,试想一下,例如将key1的数据先写入到Master节点,在写入从节点的过程中出现错误,客户端会收到写入失败,但此时去master中查询key1的数据,却能查询出上一次请求失败的数据,即客户端虽然收到了写入失败,但主节点却写入成功,造成了数据语义上的不一致性


即主从同步这种架构,主从节点、客户端的确认机制存在天然的不足,为了解决该问题,Raft等分布式副本数据强一致性协议就闪亮登场了。


2、副本之间强一致性协议


为了解决数据的高可用性,避免单点故障,通常会将数据同步为多份,高可用性是解决了,但带来了另外一个问题,多个副本数据之间如何保证一致性,为了解决该问题出现了诸如 raft、paxos等一致性协议。


Raft协议的数据复制说明图如下:


f64fe8c28dc328d78d139f8f64e99f75.png

图中客户端向Raft协议集群发起一个写请求,集群中的 Leader 节点来处理写请求,首先数据先存入 Leader 节点,然后需要广播给它的所有从节点,从节点接收到 Leader 节点的数据推送对数据进行存储,然后向主节点汇报存储的结果,Leader 节点会对该日志的存储结果进行仲裁,如果超过集群数量的一半都成功存储了该数据,主节点则向客户端返回写入成功,否则向客户端写入写入失败。


如果只有主节点写入成功,但其他从节点没有写入成功,就算数据被写入到Leader节点,但这部分数据对客户端来说是不可见的。


Raft协议主要分为两个部分:Leader节点选举与日志复制


Leader节点选举:从集群中选举一个Leader节点用于处理数据的读写,从节点只负责从Leader节点同步数据,并且Leader节点宕机,会自动触发选举,选举出一个新的Leader节点。


日志复制:数据写入主节点后,主节点需要将数据转发给从节点,只有集群中超过半数节点都成功将一条数据写入才向客户端返回成功。


Raft协议的实现细节本文不打算深究,大家如果感兴趣,可以在文末获取笔者的电子书,其中有一个系列专门阐述Raft协议的实现原理,本文只从设计层面剖析为什么Raft协议能实现数据的一致性


笔者认为Raft协议能确保数据的一致性,主要是引入了全局日志序号与已提交指针。


2.1 引入了全局日志序号


为了方便对日志进行管理与辨别,raft 协议为一条一条的消息进行编号,每一条消息达到主节点时会生成一个全局唯一的递增号,这样可以根据日志序号来快速的判断数据在主从复制过程中数据是否一致。


2.2 已提交指针


我们知道,日志先写入主节点,然后再进行传播,在集群中超过半数节点的写入成功之前,这条日志都不能认为写入成功,尽管已经存储到了主节点中,为了让客户端对这条日志不可见,Raft协议引入了已提交指针,只有小于等于已提交的数据才能被客户端感知


一条日志要能被提交的充分必要条件是日志得到了集群内超过半数节点成功追加,才能被认为已提交,才会向客户端返回成功,这样就实现了数据在集群内、客户端与集群之间的数据一致性语义


为了让大家更加深入的理解Raft协议数据性一致性问题,给出如下思考题,主从切换会导致Raft丢失数据吗?


例如一个Raft协议中有3个节点,各个节点的写入情况如下:


Node1:100

Node2:89

Node3:88


其中Node1为Leader节点,如果Node1节点宕机,整个集群触发重新选举,会丢失数据吗?


答案是肯定不会的


首先我们要先明白,在上面的状态下,已提交指针为89,因为集群有两个节点都成功写入了89,即向客户端返回成功的数据也是序号为89的数据,在选举过程中,Node3不可能会被选举为Leader,因为Node3中存储的数据小于Node2存储的数据,当Node2选举为新的Leader时,Node3会向Node2同步数据。


3、总结


本文从知乎上一个不严紧的问题出发,挖掘该问题的本质:分布式数据存储的数据分片与高可用(避免单点故障),从而又引发新的问题(数据副本之间的一致性)

相关文章
|
5月前
|
存储 负载均衡 NoSQL
【赵渝强老师】Redis Cluster分布式集群
Redis Cluster是Redis的分布式存储解决方案,通过哈希槽(slot)实现数据分片,支持水平扩展,具备高可用性和负载均衡能力,适用于大规模数据场景。
398 2
|
5月前
|
存储 缓存 NoSQL
【📕分布式锁通关指南 12】源码剖析redisson如何利用Redis数据结构实现Semaphore和CountDownLatch
本文解析 Redisson 如何通过 Redis 实现分布式信号量(RSemaphore)与倒数闩(RCountDownLatch),利用 Lua 脚本与原子操作保障分布式环境下的同步控制,帮助开发者更好地理解其原理与应用。
344 6
|
5月前
|
消息中间件 Java Kafka
Java 事件驱动架构设计实战与 Kafka 生态系统组件实操全流程指南
本指南详解Java事件驱动架构与Kafka生态实操,涵盖环境搭建、事件模型定义、生产者与消费者实现、事件测试及高级特性,助你快速构建高可扩展分布式系统。
281 7
|
5月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
885 3
|
3月前
|
缓存 Cloud Native 中间件
《聊聊分布式》从单体到分布式:电商系统架构演进之路
本文系统阐述了电商平台从单体到分布式架构的演进历程,剖析了单体架构的局限性与分布式架构的优势,结合淘宝、京东等真实案例,深入探讨了服务拆分、数据库分片、中间件体系等关键技术实践,并总结了渐进式迁移策略与核心经验,为大型应用架构升级提供了全面参考。
|
3月前
|
存储 NoSQL 前端开发
【赵渝强老师】MongoDB的分布式存储架构
MongoDB分片通过将数据分布到多台服务器,实现海量数据的高效存储与读写。其架构包含路由、配置服务器和分片服务器,支持水平扩展,结合复制集保障高可用性,适用于大规模生产环境。
340 1
|
3月前
|
缓存 运维 监控
Redis 7.0 高性能缓存架构设计与优化
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Redis 7.0高性能缓存架构,探索函数化编程、多层缓存、集群优化与分片消息系统,用代码在二进制星河中谱写极客诗篇。
|
4月前
|
存储 监控 NoSQL
Redis高可用架构全解析:从主从复制到集群方案
Redis高可用确保服务持续稳定,避免单点故障导致数据丢失或业务中断。通过主从复制实现数据冗余,哨兵模式支持自动故障转移,Cluster集群则提供分布式数据分片与水平扩展,三者层层递进,保障读写分离、容灾切换与大规模数据存储,构建高性能、高可靠的Redis架构体系。
|
4月前
|
消息中间件 缓存 监控
中间件架构设计与实践:构建高性能分布式系统的核心基石
摘要 本文系统探讨了中间件技术及其在分布式系统中的核心价值。作者首先定义了中间件作为连接系统组件的"神经网络",强调其在数据传输、系统稳定性和扩展性中的关键作用。随后详细分类了中间件体系,包括通信中间件(如RabbitMQ/Kafka)、数据中间件(如Redis/MyCAT)等类型。文章重点剖析了消息中间件的实现机制,通过Spring Boot代码示例展示了消息生产者的完整实现,涵盖消息ID生成、持久化、批量发送及重试机制等关键技术点。最后,作者指出中间件架构设计对系统性能的决定性影响,
|
4月前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
285 0
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)