Advertisement

Redis集群方案应该怎么做?都有哪些方案?

阅读量:

基于codis方案的主要集群方法与主流使用的集群方案基本上与twemproxy类似的效果,并且该方法具备在节点数量发生变动的情况下旧节点的数据能够被恢复至新的哈希节点位置。

Redis 3.0版本自带的集群系统特点在于其分布式算法基于其哈希槽概念而非一致性哈希,并且还支持通过指定节点配置实现集群管理。

在业务代码层开发:启动几个互不相干的Redis实例,在代码层对key进行哈希计算后前往对应的Redis实例执行数据操作。该方法对哈希层的代码需求较高,并需考虑节点失效时的替代算法方案、数据波动时的自愈脚本恢复以及 Redis 实例的有效监控等各项保障措施。

Redis集群方案什么情况下会导致整个集群不可用?

如果有A、B、C三个节点组成的集群,在不依赖复制模型的情况下,在节点B发生故障导致集群认为缺少指定范围(5501-11000)的槽而不依赖复制模型的情况下。

添加图片注释,不超过 140 字(可选)

Redis集群的主从复制模型是怎样的?

以确保当部分节点出现故障或大部分节点之间无法通信时, 集群仍能正常运行, 因此使用了主从复制模型, 使得每个节点都会拥有N-1个副本副本

Redis集群会有写操作丢失吗?为什么?

Redis无法确保数据达到强一致性要求,在实际应用中,在特定条件下可能导致写操作丢失

Redis集群之间是如何复制的?

Redis集群之间是通过异步复制。

Redis集群最大节点个数是多少?

16384个。

Redis集群如何选择数据库?

Redis集群目前无法做数据库选择,默认在0数据库。

Redis 持久化方案

Redis的持久化是什么?

RDB持久化:该机制能够在预设时间段内输出数据集中对应的具体时间点快照。

AOF持久化:存储服务器执行的所有修改指令,并且当服务器启动时用于恢复数据集。

按照Redis协议的标准格式组织存储在AOF文件中的所有操作指令,在线新增的操作将依次被添加至该文件的末尾段落。此外,在后台运行时系统还可以执行对AOF文件进行重写的操作(rewrite),从而确保整个存储空间不会被不必要的数据所占据。

AOF与RDB的结合使用:在Redis重启发生时,系统会优先选择AOF文件来进行数据集合的还原工作;这是因为,在一般情况下,AOF文件存储的数据集合相较于RDB文件而言更为完整。

RDB的优缺点?

优点:RDB is an efficient file structure that represents the state of Redis at a specific point in time. Such files are particularly well-suited for backup operations. For instance, you can perform hourly backups within the recent 24-hour period and also conduct daily backups. This setup ensures that you can seamlessly recover to different versions in case of issues.

RDB特别适合灾难恢复场景,在这种情况下它仅包含一个文件,并且其内容极为浓缩。经过加密处理后可以直接上传至其他数据中心或直接上传至亚马逊S3存储服务中。

RDB能最大限度地提升Redis的性能。当父进程保存RDB文件时,其唯一的任务就是启动一个子进程来处理后续的所有存储工作;而在此过程中,父进程中无需进行任何磁盘I/O操作。与AOF相比,在复原大型数据集方面,RDB的表现更为出色。

为了避免服务器故障导致的数据丢失问题, 你需要考虑选择其他方案. 然而Redis提供了一种机制, 即通过设置不同的存储点(save point)来控制RDB文件的备份频率. 由于每个RDB文件都需要完整复制当前的数据集合, 这种操作并非易事. 因此, 每隔5分钟就需要进行一次备份操作以确保数据的安全性.

在这种情况下,在故障发生时(即一旦发生故障停机),就可能导致你失去几分钟的数据。在进行每次保存操作时(即每次保存RDB的时候),Redis都会启动一个子进程(即fork()出一个子进程),并由该子进程执行实际的持久化操作(即进行实际的持久化工作)。

在数据集规模较大时使用fork()可能会导致运行时间过长;当数据集规模极大且面临CPU资源紧张的情况时,则可能导致服务停机长达整整一秒。

AOF的优缺点?

优点:使用AOF持久化可以让Redis变得更加持久(significantly more durable):你可以根据需求选择不同的fsync策略:比如不进行fsync、每隔一秒钟进行一次fsync或者每次执行写入命令时都进行fsync。

采用每秒钟同步一次的默认策略,在当前配置下 Redis仍能维持较好的性能水平;即使发生故障导致停机,在这种情况下也会最多只丢失一秒钟的数据。

AOF files are specifically designed for logging append-only operations (i.e., append-only logs). This feature ensures that when writing to an AOF file, you do not need to perform a seek operation. Notably, even if the log contains incomplete commands due to certain issues (such as disk space constraints or partial writes during system halts), the Redis-Check-Aof tool is capable of easily resolving these problems.

当AOF文件体积超过设定阈值时,Redis会自动执行后台重写操作:该操作生成的新AOF文件仅包含恢复当前数据集所需的最小指令集合。

整个重写操作具有高度的安全性。由于Redis在创建新AOF文件的过程中会持续地将所有相关命令追加至现有的AOF文件中,并且即便在重写过程中出现服务中断的情况,现有AOF文件也不会受到影响。

当新AOF文件创建完成时, Redis会从旧AOF文件迁移至新AOF文件,随后开始对新AOF文件进行追加操作

缺点:在相同的数据集展示下,在相同的数据集展示下,在相同的数据集展示下,在相同的数据集展示下,在相同的数据集展示下,在相同的数据集展示下,在相同的数据集展示下,在相同的数据集展示下,在相同的数据集中显示时

通常情况下,在执行每秒fsync操作时系统的性能表现依然非常出色。然而若关闭fsync这一功能,则可以使事务自动Commit(AOF)的速度与Read-Only备份数组(RDB)相当快,并且即便在高负载的情况下也是如此。但当处理大规模的数据增删操作时,则会发现Read-Only备份数组(RDB)能够提供更有保障的最大延迟程度(latency)。

过去曾出现过类似的问题:由于某些特定指令的操作使得在重新加载过程中出现无法将数据集恢复到最初状态的情况。

添加图片注释,不超过 140 字(可选)

如何选择合适的持久化方式?

通常情况下,在追求与PostgreSQL相当的数据安全性时, 建议同时启用两种持久化功能

在这种情况下,在Redis重 boot过程中会首要加载AOF文件以还原原有的数据,在常规场景下AOF文件所包含的数据量通常更多地体现在其完整性上

如果你特别重视你的数据,并且也能容忍数分钟以内的数据丢失的话,则建议采用RDB持久化。

(3) 大量用户仅限于使用AOF持久化技术来实现事务管理功能, 但这种做法并不被推荐.原因在于, 定时生成RDB快照(snapshot)能够方便地执行数据库备份操作, 并且在恢复数据集时, RDB技术所展现出的速度优势明显优于AOF.此外, 使用RDB技术还可以有效消除AOF程序中所存在的潜在缺陷.

如果你只需要让数据在服务器运行期间存在的话 那么可以选择完全不依赖任何持久化存储机制

Redis持久化数据和缓存怎么做扩容?

(1)如果Redis被当做缓存使用,使用一致性哈希实现动态扩容缩容。

(2)如果Redis被用作持久化存储,在设计和部署时必须确保每个节点都与指定的keys-to-nodes映射关系一一对应,并且节点数量在系统运行期间无法更改。

如果需要处理Redis节点动态变化的情况,则必须具备一套能够实现动态均衡分配的机制;然而,在现有技术中,只有Redis集群具备这一能力。

Redis的内存淘汰策略有哪些?

Redis的内存管理机制旨在解决当Redis缓存区内存不足以容纳新数据时的情况。具体而言,在现有存储空间有限的情况下, 该机制如何安排新数据项的位置以避免溢出

复制代码
 全局的键空间选择性移除

    
 noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
    
  
    
 allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近少使用的key。
    
  
    
 allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。
    
  
    
  
    
 设置过期时间的键空间选择性移除 
    
 volatile-lru:当内存不足以容纳新写入数据时,且设置了过期时间的键空间中,移除最近少使用 的key。
    
  
    
 volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某 个key。
    
  
    
 volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 key优先移除。

简单描述下Redis线程模型

Redis采用了Reactor模式来构建一个网络事件处理器。该事件处理器被命名为文件事件处理器(file event handler)。

该系统由四个部分构成:多种套接字、IO多路复用程序、文件事件分配器、事件处理器

由于事件分发队列处理事务的方式基于单线程模型的设计原则,在Redis中实现了高效的事务管理。

文件事件处理器通过 I/O 多路复用程序同时接收多个套接字,并根据当前执行的任务为每个套接字分配相应的事件处理器。

当被监听的套接字处于准备状态,并准备好执行连接应答、读取、写入以及关闭等操作时,在这些操作对应的时机上会产生相应的文件事件;随后相关的文件事件处理器会调用与之对应的套接字预先注册好的事件处理器来进行处理。

虽然基于单线程模式运行, 但通过I/O多路复用机制监控多个套接字, 文件事件处理器既实现了高效的网络通信模型, 又能够与Redis服务器中的其他模块良好衔接, 这一设计从而维持了Redis内部采用单一线程设计所带来的简化优势

Redis事务其他实现方式?

基于Lua脚本的Redis操作中,命令会被支持以一次性、按顺序的方式执行,然而它不具备针对事务运行错误进行回滚的能力.如果在执行过程中出现部分命令错误,剩余的操作仍然会继续执行.

(2)利用中间标记变量,并借助另一标记变量来判断事务是否已完成。在读取数据的过程中,在获取该标记变量后判断事务是否已完成。然而这将导致必须编写额外代码以实现这一功能,并因此显得较为繁琐。

添加图片注释,不超过 140 字(可选)

Redis 缓存雪崩与缓存击穿

简单说说缓存雪崩及解决方法

我们可以简单理解为:由于原有缓存失效而新缓存尚未到达的时间段内(举例来说,在设置缓存时我们选择了相同的过期时间因而导致在同一时刻出现了大面积的缓存过期),这些本应通过缓存快速响应的请求不得不转向数据库进而使得其对数据库的CPU与内存资源产生巨大压力这种压力可能导致数据库发生故障甚至完全崩溃从而引发了一系列连锁反应最终导致整个系统的崩溃。

解决办法:大多数系统设计者普遍采用加锁机制作为解决多线程访问数据库问题的主要手段。或者队列方式来管理这些操作以防止大量线程同时对数据库进行读写操作。这样可以有效防止失效时产生的大量并发请求直接冲击底层存储系统。另外一种简便方法是将缓存的有效期分散设置以减少潜在的压力点。

缓存穿透怎么导致的?

在处理大量请求时检索未存在的键值对可能会绕过缓存层直接向数据库发起请求从而导致数据库承受过大的负载压力直至崩溃

解决方法:

在查询结果为空的情况下也进行相应的缓存存储,在这种情况下可能会面临内存资源的紧张问题;建议采取以下措施:一方面将 ttl 设置得稍微短一些;另一方面在每次插入新数据之前及时清除对应的缓存项;这样既可以保证系统运行的高效性又能在一定程度上减少内存压力;一个缺点是过度的缓存可能导致大量无效数据占用存储空间;因此需要权衡好内存使用与响应速度之间的关系

  1. 采用布隆过滤器技术。在执行缓存操作前需先增加一层布隆过滤器,在检索操作时首先通过布隆过滤器检查 key 是否存在于数据库中。若 key 不存在则直接返回结果;若 key 存在于缓存中或数据库中则需继续进行后续的操作以获取更精确的数据来源。

布隆过滤器原理: 每当一个元素被加入到集合中时,通过将该元素应用n次Hash函数,并将结果对应到数组中的n个位置上进行设置操作,并将这些位置的值设为1。在检索过程中,请您检查这些对应的位置是否全为1即可(大致)推断该元素是否存在于集合中。具体而言,在检查结果中若发现任何一个对应的位置是0,则表示待检元素绝对不在集合内;而若所有对应的位置均为1,则表明待检元素很可能存在于集合中。总体而言,布隆过滤器是一种规模庞大的二进制位数组结构,在存储大量数据的同时能够高效实现 membership queries(成员查询)。

项目中有出现过缓存击穿,简单说说怎么回事?

当缓达到某个时间点时触发过期,在该时刻恰巧有大量并发请求同时针对这个特定Key到达。这些请求一旦发现该Key已过期后会触发从数据库中读取新数据并重新设置缓存值。这将导致大量并发请求同时访问后端数据库系统,在短时间内可能造成系统性能严重下降。

解决方案:

通过分布式锁机制实现对多线程访问权限的有效管理,在Redis缓存层中采用其提供的setnx指令作为互斥锁机制。该方法用于判断当前请求是否具备执行权限,在此前提下才允许相关处理逻辑执行。这种设计使得其他所有相关联的请求暂时无法获取该资源权值,并且能够有效防止出现大规模并发操作直接对数据库进行修改的情况。

不设置超时机制,在系统中选择基于volatile-lru的淘汰机制作为内存块管理策略。该方法的一个潜在问题是可能出现写一致性问题。具体而言,在系统运行过程中如果出现数据库中的数据更新情况,则可能导致缓存中的内容无法及时同步至数据库。从而导致缓存与数据库之间存在不一致性,并可能使应用从缓存中读取到过期或无效的数据。为此可以通过延时双删策略来解决这个问题。

Redis 缓存一致性与竞争

遇到缓存一致性问题,你怎么解决的?

因为缓存机制与数据库不在同一个数据源中,根本原因在于它们不具备原子性特征的操作,所以无法达到强一致性要求;转而需要通过实现终端一致性来解决这个问题.

解决方案:

延时双删:先刷新数据库并清除缓存,在等待两秒后再次清除一次缓存,并在读取数据时将其回写至缓存。

借助工具(canal)进行数据库的binlog日志采集并发送至MQ中;随后采用ACK机制确认并清除缓存数据。

为什么要用 Redis 而不用 map/guava 做缓存?

缓 cached存储可分为 local local cache 和 distributed distributed cache 两种类型:例如以 Java 为例 其中基于 Java 带来的 Map 类或 Guava 库实现的本地 cache 方案具有显著优势 其特点主要体现在轻量性和快速响应能力上 其生命周期随 JVM 对象的一次性销毁过程而终止 并且在多实例场景中 每个独立 instance 都需要各自维护一份 cache 因此各处使用的时钟机制不具有一致性。

可将 Redis 和 MemoryCache等视为典型的分布式缓存方案。在多实例环境中,各个实例共享一致的缓存数据,并通过一致性机制确保这些缓存系统通过一致性机制确保数据的一致性。

一个主要问题是必须维持 redis 或memcached 服务的 high availability,在整个系统的架构设计中相对复杂

如何解决 Redis 的并发竞争Key问题?

Redis 在处理 Key 的并发竞争问题时所遇到的情况是多个系统同时对该 key 进行操作,并发执行的实际顺序与预期不同从而导致结果产生差异。

建议采用以下方案:该系统可采用分布式的锁机制(Zookeeper和Redis均支持分布式的锁功能)。当Redis未存在并发竞争键的问题时,则无需采用分布式的锁机制,因为这可能会导致性能下降。

基于zookeeper临时有序节点可以实现的分布式锁。

在zookeeper协议下,当应用端设备对某个特定方法进行锁定操作时,会在该方法对应的指定子目录中即时生成一个唯一标识的有序节点.

判断获取锁的方式极为简单,在有序节点中仅需比较最小序号节点即可。在释放锁时,则无需额外操作即可完成。这种机制能够有效规避服务中断所导致的锁无法解除的风险,在完成业务流程后,删除相应的子节点来释放锁。

在实践中,当然是从以可靠性为主,所以首推Zookeeper。

什么是 RedLock?

Redis 官方站标准化地采用 Redis 作为基础实现分布式锁机制,并将其命名为 Redlock;该方案较之于传统单节点机制更具优势,在安全性方面表现更为突出。

它可以保证以下特性:

复制代码
 安全特性:互斥访问,即永远只有一个 client 能拿到锁

    
  
    
 避免死锁:最终 client 都可能拿到锁,不会出现死锁的情况,即使原本锁住某资源的 client crash 了或者出现了网络分区 
    
  
    
 容错性:只要大部分 Redis 节点存活就可以正常提供服务

什么时候需要缓存降级?

当流量激增、服务出现故障(如响应迟缓或无法响应)时以及非关键服务可能导致关键流程效率下降的情况下, 必须确保即使出现故障的服务依然保持可用状态, 即使有损服务质量.

系统可以根据一些关键数据完成自动降级,并且还可以设置一个开关来完成人工降级。

缓存降级的终目的是保证核心服务可用,即使是有损的。

而且有些服务是无法降级的(如加入购物 车、结算)。

在实施降级操作之前首先要对系统的各个组成部分进行全面梳理,并评估当前系统的承载能力是否能够承受一定程度的降级影响;在此基础上以便识别并明确哪些关键组件或功能是必须要严格保护不可降级的以及哪些部分则可以在发生不可预见情况时暂时降低其功能或服务等级;例如,在日常运维中可以通过参考日志级别设置预案来制定相应的应急响应方案。

复制代码
 一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级;

    
  
    
 警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级, 并发送告警;
    
  
    
 错误:比如可用率低于90%,或者数据库连接池被打爆了,或者访问量突然猛增到系统能承受的 大阀值,此时可以根据情况自动降级或者人工降级;
    
  
    
 严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级。服务降级的目的,是为了防止Redis服务故障,导致数据库跟着一起发生雪崩问题。
    
 因此,对于不重要 的缓存数据,可以采取服务降级策略,例如一个比较常见的做法就是,Redis出现问题,不去数据库查 询,而是直接返回默认值给用户。

如何保证缓存与数据库双写时的数据一致性?

使用缓存可能会导致缓存和数据库之间发生双存储操作;多线程操作可能导致数据不一致的问题;那么如何解决数据不一致的问题?

通常情况下,在您的系统不需要严格的缓存与数据库一致性要求的情况下(即允许缓存偶尔与数据库存在不一致的情况),采取这种方案可能会带来不必要的复杂性(比如需要将读请求和写请求串联起来处理,并将它们串联后放到内存队列中进行处理)。因此最好避免采取这一方案)。

串行化执行后会导致系统的吞吐量明显减少,在处理线上请求时需要使用比正常情况下的多若干倍的服务器资源来维持业务稳定运行

另一种方式可能偶尔会导致不一致的情况。然而这种情况发生的概率极低。也就是说,在执行过程中首先需要更新数据库之后接着删除缓存。

肝完啦,感谢友友们的支持!

全部评论 (0)

还没有任何评论哟~