带你走进Redis的世界 - 分布式环境下Redis的挑战

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 带你走进Redis的世界 - 分布式环境下Redis的挑战

前言

Redis作为存储系统,不论数据存储在内存中,还是我们之前聊过的,以快照或者AOF日志文件形式持久化到磁盘,作为单实例,会面临很多问题:

  • 数据量伸缩

单实例Redis存储k-v数量受限于内存和磁盘容量。长期运行的生产环境,会有很大瓶颈。

  • 访问量伸缩

单实例的Redis单线程执行客户端请求,吞吐量依赖于单机能够处理的数量

  • 单点故障

Redis持久化机制一定程度上,缓解了宕机/重启带来的数据安全性问题。但是对于单机系统应用,故障难以解决,会造成很大的生产问题

针对上述问题,对于数据存储系统,分布式环境下解决方案基本上通用的,如下:

  • 水平拆分 sharding
  • 主备复制 replication
  • 故障转移 failover


水平拆分

为了解决数据量和访问量增加带来的单机局限问题,采用水平拆分数据,将数据按照规则,拆分分散到不同节点处理。水平拆分后的每个节点存储的数据原则上没有交集,节点间相互独立。

image.png

具体的拆分策略一般如下所示:

hash映射

对应业务数据key,采用hash算法,映射到有限值域(hash值)上,映射尽量均匀,然后将均匀分布的hash值映射到Redis实例上。

image.png

范围映射

直接按照业务数据key进行选择,对应的实例存放。比如,0<= key <100 存放到Redis 实例0上;当大于100,存放在redis其他实例上。按照一定的规则去存放

hash和范围结合

典型的实现方式就是一致性hash。先对业务数据key进行hash求值,然后根据有限值域hash值,进行范围映射,进行存放。

按照一定的策略进行数据拆分存放,但对于客户端对于数据的请求,需要按照对应的规则,去请求到对应的实例上,称为请求路由。

对于只读的跨实例请求,按照拆分的规则进行路由到对应的实例即可。

对于跨实例的读写请求,需要特殊注意。比如,一个客户端请求需要先进行读取实例A中数据,根据获得的数据,再对实例B实施写操作,此时整个业务请求就失去了原子性。如果没有采用集群方案之前,可以通过proxy 代理层处理sharding逻辑。如独立的实例:Twemproxy


主备复制

为了解决单机性能瓶颈,引入数据拆分,将数据分发至多个redis节点,多个节点数据独立。

但是,当出现宕机问题,还是没法避免数据丢失问题。因此,引用主备复制机制,解决宕机数据安全问题。

主备复制流程

Redis包含master slave两类节点,master对外提供数据读写服务;slave节点作为master的数据备份,拥有master的全量数据,对外不提供写服务,可以读。

image.png

  1. slave节点刚启动,向master节点,发起SYNC命令,master被动将新进的slave节点加入自己的主备复制集群中
  2. master收到SYNC命令之后,开启BGSAVE操作,进行快照操作
  3. master完成BGSAVE之后,将快照信息发送给slave
  4. 在发送期间,master收到其他请求的写命令,除了正常响应之外,会存储到back-log
  5. 快照信息传送完毕,会继续传送back-log,等于追加增加的指令。
  6. 后续所有的对于master的写操作,master会同时同步给slave。保持实时异步复制


对于slave来讲,处理逻辑如下:

  • 发送完SYNC指令,对外提供读服务
  • 接收到master的快照信息,此时将slave的现有数据清空,将master的快照写入内存
  • 接受back-log执行

如多个slave节点发送SYNC命令到master,那么只要master没有完成BGSAVE操作,slave节点收到的快照信息和back-log是一致的。

断点续传

当slave节点发送SYNC指令到master,master会dump全部数据,进行异步复制。当一个已经和master完成了同步,且持续保持了很长时间的slave节点,突然断开重连,那么如果仍执行SYNC指令,就会再重发一遍。会造成不必要的开销,其中可能改变的数据没有或者很少。

Redis的PSYNC用来替代SYNC指令,可以实现断点续传。master slave维护一个offset记录当前已经同步过的指令,当出现断点重连之后,比较offset,只进行同步没有执行过的命令内容。

故障转移

当主备复制被正确使用之后,组成的集群,就具有一定的高可用,当master存在宕机或者故障,slave会自动切换为master,对外提供读写服务,这种机制称为failover(故障转移)。

针对如何发现故障,一般解决方案为采用一个daemon进程,监控所有的master-slave节点,观察可用性,并提供切换方案。image.png

但是单机的daemon又会出现单点问题,需要引入多个daemon,才进行集群管理。

image.png多个daemon集群方案,又会出现新的问题,要解决集群数据一致性问题。

Redis的sentinel提供了一套多daemon的交互机制,解决故障发现、故障转移决策协商机制等问题。

image.png

sentinel的互相感知

通过发布订阅模式来实现互相感知。

Master节点发布一个sentinel频道channel,所有的sentinel需要订阅master上的同channel,并发布自己的信息到channel,因此当新的sentinel增加,能够及时订阅到channel信息,并感知到当前所有订阅该channel的节点的信息。

master的故障发现

sentinel节点通过心跳检测的方式,定期向master发送心跳包判断是否存活。一旦没有收到正确响应,当前sentinel节点,判断master为主观不可用态,此时没有最终的决议,只有当前节点的判断。

随后所有的sentinel节点进行确定,当确定不可用的节点数大于配置的阈值,则判断不可用,进行failover故障转移流程。

failover决策

Redis的sentinel机制采用的是Raft数据一致性协议,那可以Paxos的最强有力的颠覆者。如果不了解Raft的可以参考我之前的文章,深入分布式缓存-Raft,相关的介绍。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
3月前
|
NoSQL Java Redis
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
Redis分布式锁在高并发场景下是重要的技术手段,但其实现过程中常遇到五大深坑:**原子性问题**、**连接耗尽问题**、**锁过期问题**、**锁失效问题**以及**锁分段问题**。这些问题不仅影响系统的稳定性和性能,还可能导致数据不一致。尼恩在实际项目中总结了这些坑,并提供了详细的解决方案,包括使用Lua脚本保证原子性、设置合理的锁过期时间和使用看门狗机制、以及通过锁分段提升性能。这些经验和技巧对面试和实际开发都有很大帮助,值得深入学习和实践。
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
|
7天前
|
SQL 分布式计算 数据处理
云产品评测|分布式Python计算服务MaxFrame | 在本地环境中使用MaxFrame + 基于MaxFrame实现大语言模型数据处理
本文基于官方文档,介绍了由浅入深的两个部分实操测试,包括在本地环境中使用MaxFrame & 基于MaxFrame实现大语言模型数据处理,对步骤有详细说明。体验下来对MaxCompute的感受是很不错的,值得尝试并使用!
36 1
|
1月前
|
存储 NoSQL Java
使用lock4j-redis-template-spring-boot-starter实现redis分布式锁
通过使用 `lock4j-redis-template-spring-boot-starter`,我们可以轻松实现 Redis 分布式锁,从而解决分布式系统中多个实例并发访问共享资源的问题。合理配置和使用分布式锁,可以有效提高系统的稳定性和数据的一致性。希望本文对你在实际项目中使用 Redis 分布式锁有所帮助。
172 5
|
2月前
|
NoSQL Java 数据处理
基于Redis海量数据场景分布式ID架构实践
【11月更文挑战第30天】在现代分布式系统中,生成全局唯一的ID是一个常见且重要的需求。在微服务架构中,各个服务可能需要生成唯一标识符,如用户ID、订单ID等。传统的自增ID已经无法满足在集群环境下保持唯一性的要求,而分布式ID解决方案能够确保即使在多个实例间也能生成全局唯一的标识符。本文将深入探讨如何利用Redis实现分布式ID生成,并通过Java语言展示多个示例,同时分析每个实践方案的优缺点。
90 8
|
2月前
|
NoSQL Redis
Redis分布式锁如何实现 ?
Redis分布式锁通过SETNX指令实现,确保仅在键不存在时设置值。此机制用于控制多个线程对共享资源的访问,避免并发冲突。然而,实际应用中需解决死锁、锁超时、归一化、可重入及阻塞等问题,以确保系统的稳定性和可靠性。解决方案包括设置锁超时、引入Watch Dog机制、使用ThreadLocal绑定加解锁操作、实现计数器支持可重入锁以及采用自旋锁思想处理阻塞请求。
70 16
|
2月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
57 5
|
3月前
|
NoSQL Redis 数据库
计数器 分布式锁 redis实现
【10月更文挑战第5天】
64 1
|
3月前
|
SQL NoSQL 安全
分布式环境的分布式锁 - Redlock方案
【10月更文挑战第2天】Redlock方案是一种分布式锁实现,通过在多个独立的Redis实例上加锁来提高容错性和可靠性。客户端需从大多数节点成功加锁且总耗时小于锁的过期时间,才能视为加锁成功。然而,该方案受到分布式专家Martin的质疑,指出其在特定异常情况下(如网络延迟、进程暂停、时钟偏移)可能导致锁失效,影响系统的正确性。Martin建议采用fencing token方案,以确保分布式锁的正确性和安全性。
68 0
|
5月前
|
NoSQL Redis
基于Redis的高可用分布式锁——RedLock
这篇文章介绍了基于Redis的高可用分布式锁RedLock的概念、工作流程、获取和释放锁的方法,以及RedLock相比单机锁在高可用性上的优势,同时指出了其在某些特殊场景下的不足,并提到了ZooKeeper作为另一种实现分布式锁的方案。
154 2
基于Redis的高可用分布式锁——RedLock
|
5月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
这篇文章是关于如何在SpringBoot应用中整合Redis并处理分布式场景下的缓存问题,包括缓存穿透、缓存雪崩和缓存击穿。文章详细讨论了在分布式情况下如何添加分布式锁来解决缓存击穿问题,提供了加锁和解锁的实现过程,并展示了使用JMeter进行压力测试来验证锁机制有效性的方法。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】