【分布式缓存】——-基于redis分布式缓存的实现

本文介绍Redis作为高性能Key-Value数据库的特点及其应用场景,包括支持的数据结构、持久化机制、复制功能及分布式缓存的设计方案。

一:Redis 是什么?

Redis是基于内存、可持久化的日志型、Key-Value数据库 高性能存储系统,并提供多种语言的API.

二:出现背景

  • 数据结构(Data Structure)需求越来越多, 但memcache中没有, 影响开发效率
  • 性能需求, 随着读操作的量的上升需要解决,经历的过程有: 
    数据库读写分离(M/S)–>数据库使用多个Slave–>增加Cache (memcache)–>转到Redis
  • 解决写的问题: 
    水平拆分,对表的拆分,将有的用户放在这个表,有的用户放在另外一个表;
  • 可靠性需求 
    Cache的"雪崩"问题让人纠结 
    Cache面临着快速恢复的挑战

  • 开发成本需求 
    Cache和DB的一致性维护成本越来越高(先清理DB, 再清理缓存, 不行啊, 太慢了!) 
    开发需要跟上不断涌入的产品需求 
    硬件成本最贵的就是数据库层面的机器,基本上比前端的机器要贵几倍,主要是IO密集型,很耗硬件;

  • 维护性复杂 
    一致性维护成本越来越高; 
    BerkeleyDB使用B树,会一直写新的,内部不会有文件重新组织;这样会导致文件越来越大;大的时候需要进行文件归档,归档的操作要定期做; 
    这样,就需要有一定的down time;

基于以上考虑, 选择了Redis

三:Redis 应用

Redis简介

1. 支持5种数据结构

支持strings, hashes, lists, sets, sorted sets 
string是很好的存储方式,用来做计数存储。sets用于建立索引库非常棒;

2. K-V 存储 vs K-V 缓存

新浪微博目前使用的98%都是持久化的应用,2%的是缓存,用到了600+服务器 
Redis中持久化的应用和非持久化的方式不会差别很大: 
非持久化的为8-9万tps,那么持久化在7-8万tps左右; 
当使用持久化时,需要考虑到持久化和写性能的配比,也就是要考虑redis使用的内存大小和硬盘写的速率的比例计算;

3. 社区活跃

Redis目前有3万多行代码, 代码写的精简,有很多巧妙的实现,作者有技术洁癖 
Redis的社区活跃度很高,这是衡量开源软件质量的重要指标,开源软件的初期一般都没有商业技术服务支持,如果没有活跃社区做支撑,一旦发生问题都无处求救;

Redis基本原理

redis持久化(aof) append online file: 
写log(aof), 到一定程度再和内存合并. 追加再追加, 顺序写磁盘, 对性能影响非常小

1. 单实例单进程

Redis使用的是单进程,所以在配置时,一个实例只会用到一个CPU; 
在配置时,如果需要让CPU使用率最大化,可以配置Redis实例数对应CPU数, Redis实例数对应端口数(8核Cpu, 8个实例, 8个端口), 以提高并发: 
单机测试时, 单条数据在200字节, 测试的结果为8~9万tps;

2. Replication

过程: 数据写到master–>master存储到slave的rdb中–>slave加载rdb到内存。 
存储点(save point): 当网络中断了, 连上之后, 继续传. 
Master-slave下第一次同步是全传,后面是增量同步;、

3. 数据一致性

长期运行后多个结点之间存在不一致的可能性; 
开发两个工具程序: 
1.对于数据量大的数据,会周期性的全量检查; 
2.实时的检查增量数据,是否具有一致性;

对于主库未及时同步从库导致的不一致,称之为延时问题; 
对于一致性要求不是那么严格的场景,我们只需要要保证最终一致性即可; 
对于延时问题,需要根据业务场景特点分析,从应用层面增加策略来解决这个问题; 
例如: 
1.新注册的用户,必须先查询主库; 
2.注册成功之后,需要等待3s之后跳转,后台此时就是在做数据同步。

四:分布式缓存的架构设计

1.架构设计

由于redis是单点,项目中需要使用,必须自己实现分布式。基本架构图如下所示

2.分布式实现

通过key做一致性哈希,实现key对应redis结点的分布。

一致性哈希的实现:

l        hash值计算:通过支持MD5与MurmurHash两种计算方式,默认是采用MurmurHash,高效的hash计算。

l        一致性的实现:通过Java的TreeMap来模拟环状结构,实现均匀分布

3.client的选择

对于jedis修改的主要是分区模块的修改,使其支持了跟据BufferKey进行分区,跟据不同的redis结点信息,可以初始化不同的 ShardInfo,同时也修改了JedisPool的底层实现,使其连接pool池支持跟据key,value的构造方法,跟据不同 ShardInfos,创建不同的jedis连接客户端,达到分区的效果,供应用层调用

4.模块的说明

l        脏数据处理模块,处理失败执行的缓存操作。

l        屏蔽监控模块,对于jedis操作的异常监控,当某结点出现异常可控制redis结点的切除等操作。

整个分布式模块通过hornetq,来切除异常redis结点。对于新结点的增加,也可以通过reload方法实现增加。(此模块对于新增结点也可以很方便实现)

对于以上分布式架构的实现满足了项目的需求。另外使用中对于一些比较重要用途的缓存数据可以单独设置一些redis结点,设定特定的优先级。另外对 于缓存接口的设计,也可以跟据需求,实现基本接口与一些特殊逻辑接口。对于cas相关操作,以及一些事物操作可以通过其watch机制来实现。

<think>嗯,用户现在聚焦在分布式缓存的"缓存冗余"设计上,这其实是个很有深度的架构问题。从对话历史看,用户已经对缓存类型有基础了解(代理缓存、CDN、对象缓存等),但需要更深入冗余机制的设计细节。 用户引用的资料[^3]提到冗余是"增加副本,提高可用性、安全性、性能",这正好是缓存冗余的核心目标。不过资料里没具体展开技术实现,需要结合分布式系统的特性来补充。 首先得明确缓存冗余要解决三个关键问题:数据丢失风险(比如Redis节点宕机)、访问热点压力(大量请求压垮单个节点)、跨地域延迟(异地用户访问慢)。对应的技术方案其实都是围绕"数据副本"展开的: - 主从复制是比较基础的做法,但要注意主节点故障时的切换延迟问题,引用资料[^2]提到分布式部署会增加复杂性,这里就体现出来了——需要哨兵或集群模式来保证切换可靠性。 - 分片集群更适用于超大规模场景,但数据分片本身不是冗余,必须配合每个分片的副本集才能真正实现冗余。这里可以关联用户之前问过的"Redis集群"话题。 - 多级缓存其实也是冗余思想,本地缓存本质是内存级副本,不过生命周期短,需要设计好回填策略。用户之前的多级缓存代码示例可以复用,但这次要强调其作为冗余层的作用。 用户可能还关心一致性代价。强一致性(如同步复制)和最终一致性(异步复制)的选择会影响性能,电商类业务往往选择后者,用版本号或时间戳解决冲突。这个点要结合资料[^3]说的"异步"模式来解释。 最后容量规划容易被忽略。冗余意味着存储空间翻倍,比如三副本就需要3倍内存。但资料[^2]提到分布式能利用更多物理资源,所以实际要计算的是"有效容量"而非单机容量。 </think> ### 分布式缓存缓存冗余设计 在分布式架构中,缓存冗余是通过**数据副本机制**提升系统可用性、容错性和性能的重要策略。其核心目标是确保当部分节点失效时,缓存服务仍能持续可用。以下是关键设计模式和技术实现: #### 一、缓存冗余的核心模式 1. **主从复制(Replication)** - **原理**:主节点处理写请求,异步/同步复制数据到从节点 - **故障转移**:主节点宕机时,哨兵(Sentinel)自动提升从节点为主节点 - **优势**: - 读操作分流到从节点,提升吞吐量 - 数据持久性保障(至少存在N个副本) - **缺陷**:异步复制可能造成数据短暂不一致 2. **多副本集群(Cluster Replication)** - **实现方式**: ```mermaid graph LR A[客户端] --> B[分片1-主] A --> C[分片1-副本] A --> D[分片2-主] A --> E[分片2-副本] B <-. 数据同步 .-> C D <-. 数据同步 .-> E ``` - **特性**: - 每个数据分片持有多个副本(通常2-3个) - 副本分散在不同物理机/机架,防硬件故障 - **示例**:Redis Cluster通过Gossip协议维护副本状态 #### 二、冗余设计关键技术 1. **数据同步机制** - **强一致性**:Raft/Paxos协议保证副本强一致(如Etcd) - **最终一致性**:异步复制+冲突解决(Dynamo风格) - **平衡策略**: $$ \text{延迟} \propto \frac{1}{\text{一致性强度}} $$ 业务容忍度决定一致性级别[^3] 2. **故障恢复策略** - **自动故障检测**:心跳监测(如Redis Sentinel) - **数据重建**: - 从其他副本恢复数据 - 结合持久化存储(AOF/RDB)重建缓存 - **流量切换**:负载均衡器自动隔离故障节点[^2] #### 三、冗余与性能的权衡 | 维度 | 高冗余方案 | 低冗余方案 | |---------------|---------------------------|---------------------| | 副本数量 | ≥3 | 1(无冗余) | | 写延迟 | 高(需同步多副本) | 低(单节点写入) | | 读吞吐量 | 高(多节点分担) | 受限(单节点) | | 数据丢失风险 | $\text{极低}$ | $\text{高}$ | | 适用场景 | 金融/医疗等强一致性要求 | 临时缓存/日志类数据 | #### 四、实践案例:Redis Cluster冗余设计 1. **数据分片**:16384个槽位(slot)哈希分片 2. **副本放置**: - 每个主节点配置1~N个从节点 - 自动保证主从节点不在同一物理机[^2] 3. **故障转移**: ```python # 伪代码:故障检测与切换 def handle_node_failure(node): if node.role == "master": replicas = get_healthy_replicas(node) new_master = elect_new_master(replicas) # 基于优先级选举 reconfigure_slots(new_master) # 槽位重分配 notify_clients() # 更新路由表 ``` #### 五、设计注意事项 1. **脑裂问题防护** - 采用多数派仲裁(Quorum)机制 - Redis Cluster要求节点数满足:$N_{\text{master}} \geq 3$ 且 $N_{\text{replica}} \geq 1$ 2. **资源成本控制** - 存储空间需求:$\text{总容量} = \text{数据量} \times (1 + \text{副本因子})$ - 通过冷热数据分离降低冗余成本 3. **一致性保障** - 写操作需满足:$W + R > N$(W:写成功副本数,R:读副本数,N:总副本数) - 结合版本号(Vector Clock)解决冲突 > **关键结论**:缓存冗余的本质是**用空间换可用性**,设计需围绕业务对数据一致性、可用性、延迟的要求展开,结合自动故障转移与数据平衡策略实现系统韧性[^3]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值