Redis主要有哪些功能?
- 缓存加速:Redis通常被作为应用程序的缓存层,将热点数据或频繁访问的数据存储在Redis中,减少对数据库的访问次数,常见应用场景包括Web页面缓存、数据库查询结果缓存、API调用缓存等。
- 轻量级数据库:可以用作一个轻量级数据库,尤其是需要在高速读写和持久化的场景下,支持多种数据结构,如字符串、哈希、列表、集合、有序集合等,常见应用场景包括实现会话管理、用户信息存储、排行榜、计数器等功能。
- 消息代理:提供发布/订阅模式以及List数据结构,实现消息的发布和订阅功能,用于实现消息队列、实时通知等功能,常见应用场景包括实时聊天应用、新闻推送、实时监控等场景。
- 分布式锁:Redis的setnx命令可以实现分布式锁功能,确保分布式系统中对共享资源的访问是安全的。单线程特性可以保证多个客户端之间对同一把锁的操作是原子性的,避免竞态条件。
- 计数器:Redis的原子操作特性使其非常适合实现计数器功能。可以用Redis来记录网站的访问量、API接口的调用次数、用户的点赞数、评论数等数据。通过incr等命令能实现原子性的自增操作,从而实现一个全局计数器。
- 数据结构算法实现:Redis支持多种数据结构,使开发者可以利用Redis实现各种数据结构和算法,简化开发过程。可以使用Redis的集合数据结构实现交集、并集、差集等操作。
- 实时系统支撑:在实时分析、在线游戏、实时推荐等场景中,可以确保数据的实时更新和查询。
- 限流控制:通过Lua脚本结合其数据结构实现限流功能,防止系统在高并发场景下因流量过大而崩溃。Redis提供了令桶和漏桶算法的实现,可以用于实现分布式限流。
谈谈Redis事务?
- 事务的开始与执行:
- 开始事务:使用MULTI命令开启一个事务,之后客户端发送的所有命令都会被放入事务队列中,不会立即执行。
- 执行事务:当从客户端发送EXEC命令时,Redis会顺序执行事务队列中的所有命令。
- 事务特性:
- 原子性:Redis事务是原子性的,要么全部执行成功,要么全部执行失败。
- 隔离性:Redis事务是隔离的,即一个事务中的命令不会被其他事务所干扰。Redis的事务隔离相对简单,没有像传统关系型数据库那么复杂的隔离级别,主要通过将事务中的命令顺序执行来实现隔离效果。
- 事务的回滚:
- 自动回滚:如果事务队列中的某个命令执行失败,Redis会自动停止执行后续的命令,并将事务回滚到开始事务之前的状态。
- 手动回滚:Redis也支持使用DISCARD命令手动回滚事务。在执行EXEC之前,如果客户端发送DIRCARD命令,那么事务队列中的所有命令都会被清空,事务不会执行。
- 事务使用场景:
- 批量操作:当需要对多个键进行一系列操纵,且这些操作是相关的,可以使用事务提高效率。
- 保证操作一致性:在一些需要保证多个操作要么全部成功要么全部失败的场景中,事务非常有用。
- 简化代码逻辑:当多个操作需要一起执行时,通过事务可以将这些操作封装起来,使得代码更加清晰易懂。
- 事务局限性:
- 不支持复杂的事务回滚:Redis的事务回滚机制相对简单,主要是基于命令执行是否成功来判断。对于复杂场景,如事务中某个命令执行后对数据产生了部分影响,但后续命令失败,Redis无法像传统关系型数据库那样进行复杂的回滚操作,将数据恢复到事务开始前的状态。
- 阻塞问题:事务执行过程中,其他客户端的命令会被阻塞,直到事务执行完成。如果事务中的命令较多或执行时间较长,可能会导致其他客户端的请求响应延迟。对于大多数Redis使用场景,这种情况较少出现,因为Redis的命令执行速度通常很快。
- 缺乏事务控制语句:没有像传统关系型数据库中的BEGIN TRANSACTION、COMMIT、ROLLBACK等事务控制语句,事务控制相对简单,不够灵活。
谈谈Redis LUA脚本?
- 允许用户在Redis服务器上执行自定义的LUA代码。
- 特性:
- 原子性:Redis使用单个LUA解释器运行所有的脚本,并保证脚本执行的原子性。在脚本执行期间,其他客户端的命令不会被执行,直到脚本执行完毕。
- 类型转换:在LUA脚本中,Redis命令的返回值会被转换成LUA的数据结构,反之亦然。使得用户可以在LUA脚本中方便地处理Redis数据。
- 脚本缓存:Redis有一个内部脚本缓存机制,可以保存所有运行过地脚本。用户可以使用EVALSHA命令通过脚本地SHA1校验和执行脚本,而不是每次都发送脚本主体。
- 使用场景:
- 多命令事务:当需要执行多个Redis命令,并且这些命令必须作为一个原子操作来完成时可以使用。
- 乐观锁和复合操作:通过LUA脚本可以实现复杂地锁定逻辑和复合操作,如在购物车系统中同时更新商品数量和库存。
- 条件执行:基于某些条件来决定是否执行特定地操作,如根据用户的积分等级来给予不同的折扣。
- 批量读取与写入:使用LUA脚本来批量获取或设置数据,减少网络往返次数。
- 数据预处理和缓存更新:在返回给客户端之前对数据进行预处理,或者在更新某个键时自动删除相关的缓存键,保证数据的一致性。
- 注意事项:
- 性能考虑:虽然LUA脚本提供了强大的功能,但它们可能会导致阻塞问题,特别是在长时间运行或执行大量计算情况下。在编写LUA脚本时应该谨慎考虑性能影响。
- 全局变量保护:LUA脚本不允许创建全局变量。如果脚本需要在多次执行之间维持某种状态,可以借助外部Redis Key来保存状态。
谈谈Redis集群?
- 架构:
- 无中心架构:每个节点都保存数据,节点之间互相连接,从而知道整个集群的状态。
- 数据分片:集群将数据分散存储在多个节点上,每个节点负责一部分数据。数据分片基于哈希槽实现,每个键通过CRC16算法映射到特定槽,槽再分配给集群中的节点。
- 节点角色:
- 主节点:负责处理槽对应的读写请求,维护数据副本,并同步给从节点。
- 从节点:复制主节点数据,提供读服务,主节点故障时可晋升为主节点。
- 工作原理:
- 节点间通信:节点间通过Gossip协议交换集群状态信息,包括节点新增、删除、故障、槽信息变更等。客户端与任意节点建立连接,节点负责将请求转发至正确的主节点。
- 高可用性:主从复制、故障检测与选举、投票机制。
- 槽迁移:在线迁移、状态同步。
- 应用场景:
- 大规模数据存储:Redis集群通过数据分片,将数据分散到多个节点,解决海量数据存储问题。
- 高并发读写:Redis集群允许多个节点同时提供服务,适用于高并发读写场景。
- 分布式系统:在分布式系统中,Redis集群可以作为缓存层,提供高效的读写操作和数据存储,支持分布式应用的高可用性和扩展性。
- 优点:
- 去中心化:集群完全去中心化,采用多主多从,所有Redis节点彼此互联,内部使用二进制协议优化传输速度和带宽。
- 客户端直连:客户端与Redis节点直连,不需要中间代理层,客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
- 高可用性:每个主节点都有多个从节点,当主节点故障时,从节点可以自动晋升为主节点,保证集群的高可用性。
Redis如何做内存优化?
- 数据结构选择与优化:
- 选择合适的数据结构:根据业务需求选择合适的数据结构,最大限度减少内存消耗。例如存储用户的点赞列表时,如果只需要记录点赞与否,使用Set数据结构比使用List更节省空间。
- 使用压缩技术:对于有一定规律或冗余的存储数据,考虑将数据存入Redis之前进行压缩。在读取数据时再进行解压。可以使用Snappy或LZ4等高效的压缩算法,但需要注意压缩和解压带来的CPU开销。
- 内存管理策略:
- 设置合理的maxmemory参数:根据服务器的内存容量和其他应用的内存需求,合理设置Redis的maxmemory参数,防止Redis占用过多的内存导致系统性能下降。
- 使用内存淘汰策略:根据业务场景选择合适的淘汰策略。如果业务允许部分数据丢失,且数据访问有冷热之分,像缓存系统,allkey-lru可能是一个较好的选择。内存淘汰策略包括noeviction(不淘汰,当内存满时写入操作会报错)、volatile-lru(从设置了过期时间的键中使用最近最少使用算法淘汰)、allkeys-lru(从所有键中使用最近最少使用算法淘汰)。
- 启用内存碎片整理:定期执行MEMORY DOCTOR和MEMORY PURGE命令,清理碎片并优化内存使用。通过配置rdbchecksum参数为yes,在内存回收时进行碎片整理,提高呢村使用的连续性。
- 过期策略与持久化配置:
- 设置合理的过期时间:对于自动过期数据,设置合理的TTL以减少内存占用。例如临时用户登录验证码可以设置为5-10分钟过期。
- 选择合适的持久化方式:根据数据重要性和恢复需求来配置,如RDB(定期快照)或AOF(追加日志文件)。如果对数据的持久化要求不高,可以禁用Redis的持久化功能,减少对磁盘的写入操作。
- 连接和客户端优化:
- 使用连接池:避免频繁的创建和关闭连接,可以使用连接池管理Redis的连接。
- 批量操作:利用Redis批量操作命令减少单个操作的网络延迟和处理开销。例如使用MGET、MSET等命令同时获取或设置多个键的值。
- 避免使用过大的Key和Value:保持Key简短,并使用简洁的命名约定。
- 定期清理不必要的数据:管理数据的生命周期,定期删除过期或不必要的数据。可以设置Cron任务定期清理Redis的垃圾数据。
Redis回收进程如何工作的?
- 工作流程:
- 检测内存使用情况:周期性检测Redis的内存占用情况,当内存占用超过阈值时,触发内存回收机制。
- 标记过期键:扫描所有键,标记已过期键。
- 删除过期键:根据标记,删除已过期的键,释放内存。
- 执行内存淘汰:如果内存仍然不足,根据配置的淘汰策略删除一些键。
- 回收空闲内存:检查并回收大块的空闲内存,减少内存碎片。
Redis哨兵机制实现原理?
- 工作机制:
- 监控与心跳检测:哨兵周期性向Redis节点发送INFO命令,获取节点状态信息。哨兵通过PING命令检测节点的连通性,若节点在指定时间内未响应,则标记为下线。
- 主观下线与客观下线:
- 主观下线:当一个哨兵认为某个节点不可达时,标记该节点为主观下线。
- 客观下线:当足够数量的哨兵同意某个节点为主观下线时,该节点被标记为客户下线,触发故障转移流程。
- 故障转移:
- 领导者选举:当主节点客观下线时,哨兵集群选出一个哨兵作为故障转移的协调者。
- 从节点晋升:协调者哨兵选择一个从节点晋升为主节点,执行SLAVEOF NO ONE命令使其脱离旧主节点。
- 配置更新:协调者哨兵向其他哨兵与从节点广播新的主节点信息,更新其配置。
- 数据同步:新主节点开始接收写请求,其他从节点重新连接主节点,继续数据同步。
- 配置文件与通知:
- 自动配置更新:哨兵监控到集群状态变化时,自动更新客户端配置文件,执行新主节点。
- 客户端通知:哨兵提供订阅机制,客户端订阅+switch-master频道,实时获取主节点变更通知。
- 哨兵配置:
- 配置文件:sentinel.conf,包含监控的主节点信息、哨兵节点间通信参数、故障转移策略等。
- 故障转移参数:
- quorum:判定节点客观下线所需的哨兵数量。
- parallel-syns:新主节点在故障转移后同时进行数据同步的从节点数量。
- down-after-milliseconds:判定节点主观下线的超时时间。
Redis支持哪几种数据类型?
- List、Set、Hash、String、ZSet。
Redis是单进程单线程的?
- 主要是单进程,单线程的,但存在特殊情况。
- 特殊情况:
- AOF持久化:
- AOF重写:当AOF文件变得太大时,Redis会启动一个子进程来重写AOF文件。这个过程是异步的,不会阻塞主进程。
- 文件写入:AOF文件的写入操作是同步哦 fsync 系统调用完成,可配置为每秒同步一次,减少磁盘IO。
- RDB持久化:
- RDB快照:生成RDB文件时,会启动一个子进程来完成快照操作。主进程继续处理客户端请求,子进程完成后,新的RDB文件会替换旧的文件。这个过程是异步的,不会阻塞主进程。
- 多线程IO:
- Redis 6.0之后:引入多线程IO支持,可以使用多个线程来处理客户端的读写操作,但命令的执行仍然是单线程的。通过io-threads配置参数设置IO线程的数据量。默认值是4。
- AOF持久化:
Redis单线程设计在哪里?
- Redis使用一个主线程来处理网络IO和键值对的读写操作。接收客户端的请求、解析请求、执行相应命令、结果返回客户端,所有这些操作都在同一个线程中顺序执行。
Redis快的核心原因?
- 内存存储:将数据存储在内存中,读写速度远高于磁盘。
- 单线程模型:避免了复杂的线程同步和锁竞争问题。
- 非阻塞IO:通过事件驱动和多路复用处理客户端请求。
- 命令的原子性:Redis的每个命令都是原子性的,命令的执行不会被终端。
- 优化的数据结构:Redis内部使用多种高效的数据结构,如哈希表、跳表、压缩列表等。
- 命令的简单性:Redis的命令相对简单,大多数命令的操作事件复杂度较低。例如GET、SET、INCR等命令的时间复杂度为O(1)。
- 多线程IO(Redis 6.0以后):使用多个线程来处理客户端的读写操作。
- 持久化策略的优化:提供RDB和AOF持久化策略,通过异步操作和子进程来实现,不会阻塞主进程的命令处理。
- 网络优化:支持高效的协议解析和数据传输。使用自定义的二进制协议,减少协议解析的开销,提高数据传输效率。
- 内存管理:采用内存管理机制,如内存碎片管理、内存分配器优化等。
Redis单点吞吐量是多少?
- 受多种因素影响:硬件配置、Redis配置、运行的具体操作和负载。
- 自带性能测试工具:redis-benchmark 模拟多个并发客户端同时向Redis服务器发送请求,并计算服务器的响应时间和吞吐量。
- 一般情况下,单节点的吞吐量可以达到数万到数十万次操作每秒(OPS);
谈谈QPS、TPS?
- QPS:每秒处理的请求数,通常用于衡量Redis的读写操作频率。
- TPS:每秒处理的事务数,通常用于衡量Redis的事务处理频率。
Redis相比memcached有哪些优势?
- 数据类型的丰富性:Redis支持多种数据类型,如字符串、列表、集合、哈希、有序集合等,且支持更复杂的操作,如原子性、排序等。
- 数据持久化:可以将内存中的数据保存到磁盘上,在服务器重启后恢复数据。
- 发布/订阅功能:允许应用程序通过订阅感兴趣的频道来接收消息,并通过发布消息到频道来通知其他应用程序。
- 集群支持:可以将数据分布在多个节点上,实现横向扩展和负载均衡。与Memcached集群相比,Redis的集群支持更加原生和高效。
- 丰富的数据操作命令:例如对列表进行范围查询、对集合进行交集、并集等操作。
- Lua脚本支持:允许使用Lua脚本进行批量操作,将多个命令打包成一个原子操作,减少网络通信开销。
- 事务处理:可以将多个命令打包成一个事务执行,保证操作的原子性。
Redis有哪几种数据淘汰策略?
- noeviction:不淘汰任何键,当内存不足以容纳新写入数据时,写入操作会报错,默认淘汰策略。
- volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的键进行淘汰。适用于数据访问频率差异较大的场景,即部分数据访问频繁,部分数据访问较少。
- volatile-lfu:从已设置过期时间的数据集中挑选最不经常使用的键进行淘汰。适用于数据访问频率差异较大的场景。
- volatile-ttl:从已设置过期时间的数据集中挑选将要过期的键进行淘汰,即TTL值越小的键越先被淘汰。
- volatile-random:从已设置过期时间的数据集中随机选择键进行淘汰。适用于对数据淘汰顺序没有特定要求的场景。
- allkeys-lru:从所有键中挑选最近最少适用的键进行淘汰。
- allkeys-lfu:从所有键中挑选最不经常适用的键进行淘汰。
- allkeys-random:从所有键中随机选择键进行淘汰。
Redis集群方案有哪些?
- 主从复制:将一台服务器的数据复制到其他Redis服务器上。前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能由主节点到从节点。
- 哨兵模式:哨兵节点会监控主节点的状态,当主节点故障时,会自动选择一个从节点提升为新的主节点,并将其他从节点重新指向新的主节点。
- Redis Cluster:支持自动分片、自动容错、横向扩展。将数据分布到多个节点上,每个节点只保存部分数据,通过哈希算法将数据映射到特定节点上。
Redis各种集群方案的优劣势比较?
- 主从复制:
- 优点:
- 数据备份和恢复:从节点可以作为数据备份,保证主节点宕机或丢失数据时可以快速恢复。
- 读写分离:从节点可以分担主节点的读压力,提高读性能。
- 高可用性:当主节点宕机时,从节点可以自动切换为主节点继续提供服务。
- 扩展性:通过加入更多的从节点,实现横向扩展,增强集群处理能力。
- 缺点:
- 延迟:主节点需要广播数据给从节点,存在一定的网络传输延迟。
- 容灾能力:如果所有从节点挂掉,集群的容灾能力很差。
- 一致性问题:由于Redis的异步复制机制,当主节点数据由修改而还未同步到从节点时,主节点宕机可以导致数据不一致。
- 故障恢复复杂:主节点或从节点宕机时,需要手动干预,比较繁琐。
- 写能力受限:主节点的写能力受到单机的限制。
- 存储能力受限:主节点的存储能力受到单机的限制。
- 优点:
- 哨兵模式:
- 优点:
- 自动故障转移:解决主从模式中主节点故障时不能自动切换问题。
- 高可用性:可以自动检测主节点的故障并进行故障转移,保证服务的高可用性。
- 部署简单:Redis Sentinel集群部署相对简单。
- 多节点监控:可以适用一套Sentinel监控一组或多组Redis护具节点。
- 缺点:
- 中心化:始终只有一个Redis主机来接收和处理写请求,写操作受单机瓶颈影响。
- 资源浪费:所有节点保存全量数据,浪费内存空间,没有实现真正分布式存储。
- 写操作限制:主机宕机后,投票选举期间禁止写操作,直到选举出新的主节点。
- 复杂性:部署相对Redis主从模式要复杂一些,原理理解更繁琐。
- 资源浪费:从节点作为备份节点不提供服务。
- 读写分离复杂:不能解决读写分离问题,实现起来相对复杂。
- 优点:
- Redis Cluster:
- 优点:
- 高可用性:支持主从复制和故障转移,当某个节点发生故障时,系统自动将主节点切换为从节点。
- 横向扩展:通过增加节点来提高系统的性能和容量,灵活应对不同规模的应用需求。
- 数据分片:将数据分散存储在多个节点上,有效减轻单个节点的负载压力。
- 自动数据迁移:当新增或删除节点时,系统可以自动调整数据分片,保证数据的均衡分布。
- 缺点:
- 部署复杂:需要对节点和哈希槽进行配置和管理。
- 不支持事务:不支持跨节点的事务,只支持单节点事务。
- 数据不一致:主从节点之间的数据同步存在一个的延迟,可能出现数据不一致情况。
- 部分命令不支持:部分Redis命令不支持在集群模式中使用,例如Keys、Scan等命令。
- 客户端要求:客户端必须支持cluster协议。
- 事务操作有限:只支持多key在同一节点上的事务操作,当多个key分布于不同的节点上时无法使用事务功能。
- 资源隔离性差:当多个业务使用同一套集群时,无法根据统计区分冷热数据。
- 不支持多数据库空间:只能使用一个数据库空间,即db0。
- 复制结构限制:从节点只能复制主节点,不支持嵌套树状复制结构。
- 优点:
Redis集群方案应该怎么做?
- 需要考虑集群架构的选择、数据分片的策略、故障恢复的机制、集群的扩展性等方面。
Redis提供了哪几种持久化方式?
- RDB(定期快照)、AOF(日志文件追加)、混合持久化(RDB和AOF两种机制混合使用)持久化方式。
Redis各种持久化方式的实现?
- RDB实现:
- 通过生成快照方式,将当前Redis进程的数据持久化到磁盘上的dump.rdb文件中。
- 通常使用BGSAVE命令,通过fork生成一个子进程来处理持久化操作。子父进程共享内存,通过COW(Copy On Write)机制,只有在数据被修改时才会复制内存页面。
- AOF实现:
- 通过记录每个写操作来实现数据的持久化,这些命令以Redis协议的格式保存在AOF文件中,新命令会被追加到文件末尾。
- 为了防止AOF文件过大,在后台对AOF文件进行重写,使AOF文件的体积不会超出保存数据集状态所需的实际大小。
- 混合机制实现:
- AOF文件的开头部分是RDB格式的全量数据,后面部分是AOF格式的增量数据。
Redis如何选择合适的持久化方式?
- RDB:
- 优点:
- 生成的快照文件是紧凑压缩的二进制文件,占用空间较小,适用于备份和全量复制等场景。
- 恢复速度较快,因为快照文件是完整的数据备份。
- 缺点:只保存了某个时间点的数据快照,无法记录数据的变化过程,可能存在数据丢失的风险。
- 优点:
- AOF:
- 优点:
- 记录了每个写操作命令,因此即使出现宕机等故障,只会丢失最后一次持久化之后的数据,保证数据的可靠性。
- AOF文件是以文本形式存储的,易于阅读和解析。
- 缺点:可能会产生较大的IO开销,并且数据恢复时间可能需要较长的时间。
- 优点:
- 混合持久化:
- 优点:结合了RDB的快速数据恢复能力和AOF的数据安全性,提供即快速又可靠的数据恢复方案。
- 缺点:持久化文件的复杂性和管理难度增加。
Redis常见性能问题?
- 内存使用过高:当Redis使用的内存超过物理内存容量时,系统可能开始使用交换空间,这会导致性能急剧下降。
- 网络延迟:可能导致请求响应时间增加,影响客户端访问性能。
- 阻塞操作:可能导致Redis无法响应其他请求,影响系统吞吐量。
- 持久化操作引起的性能问题:特别是AOF持久化,可能引起磁盘IO压力。
- 热点Key问题:当某个Key被访问的次数超过一定阈值时,Redis会自动将这个Key移动到其他节点上,从而实现数据分布的均衡。
- 数据一致性问题:当多个客户端同时访问同一个Key时,可能会出现数据不一致的情况,需要通过一致性协议来保证数据的一致性。
Redis性能解决方案?
- 配置优化:
- 内存管理:
- 设置最大内存:通过maxmemory参数设置Redis使用的最大内存。
- 设置内存淘汰策略:通过maxmemory-policy参数设置内存达到限制时的处理策略。
- 网络优化:
- 调整TCP keepalive:更快检测到失效的连接。
- 设置客户端连接超时时间:通过timeout参数设置客户端连接超时时间。
- IO优化:
- 启用IO线程:通过io-threads参数启用io线程提升并发性能。
- 内存管理:
- 硬件优化:
- 内存:确保有足够的内存来存储数据和提供缓冲空间。
- CPU:通过taskset命令将Redis进程绑定到特定的CPU核心上,减少上下文切换的开销。
- 磁盘:使用更快的磁盘(如SSD),提高持久化操作的性能。
- 数据结构优化:
- 合理选择数据结构:根据业务需求选择合适的数据结构,优化数据存储和读写操作。
- 减少数据结构的嵌套:避免复杂的嵌套操作,如嵌套哈希和列表,简化数据模型。
- 持久化策略:RDB、AOF、混合持久化。
- 批量操作:使用Pipeline批量发送命令。
- Lua脚本:使用Lua脚本将多个命令组合执行。
- 合理设置过期时间:对会话数据等设置合理的过期时间,自动清理不再需要的数据。
- 集群优化:使用Redis Cluster分片数据,提高系统的吞吐量和可用性。
Redis支持的Java客户端都有哪些?
- Jedis、Lettuce、Redisson、Jedisson、RedisTemplate。
Redis哈希槽的概念?
- 哈希槽数量:Redis Cluster中共有16384个哈希槽,编号从0到16383.
- 数据映射:每个键通过一个哈希函数映射到一个特定的哈希槽。键的名称通过CRC16算法计算得到一个16位的哈希值,然后对16384取模,得到改建对应的哈希槽编号。
Redis集群最大节点个数是多少?
- 理论上是16384个节点。
- 实际部署中,由于资源、管理、稳定性限制,很少会有如此大规模的集群。
- 通常根据业务需求、资源限制、管理复杂度等多种因素来确定。
Redis集群的主从复制模型是怎样的?
- 初始化过程:
- 连接建立:
- 从节点启动时,会连接到配置的主节点,并发送REPLCONF listening-port命令,告知主节点自己的监听端口。
- 主节点会建立一个客户端对象来表示从节点,并将其添加到自己的从节点列表中。
- 全量复制:
- 从节点发送SYNC命令请求全量复制。
- 主节点接收到SYNC命令后,执行BGSAVE命令生成RDB文件,并将生成的RDB文件发送给从节点。
- 从节点接收并加载RDB文件,将数据加载到内存中。
- RDB文件传输期间,主节点会将新的写操作命令缓存在内存中,这些命令被称为复制积压缓冲区。
- RDB文件传输完成后,主节点会将复制积压缓冲区中的命令发送给从节点,确保主从节点数据一致。
- 部分复制:
- 如果从节点与主节点的连接短暂终端,从节点会尝试部分复制来恢复数据。
- 从节点发送PSYNC 命令,其中runid是主节点运行ID,offset是从节点上次接收的命令偏移量。
- 主节点接收到PSYNC命令后,检查runid和offset是否有效,若有效,则主节点会从复制积压缓冲区中获取从offset开始的命令,发送给从节点。
- 如果runid无效或offset超出复制积压缓冲区的范围,主节点会执行全量复制。
- 连接建立:
Redis集群之间是如何复制的?
- 复制过程:
- 配置主从关系:
- 将一个节点配置为主节点,并在配置文件中设置其IP地址和端口号。
- 将其他节点配置为从节点,并在配置文件中指定主节点的IP地址和端口号。
- 同步(SYNC)阶段:
- 当从节点首次连接到主节点时,或者从节点与主节点之间的连接重连时,会触发全量同步。
- 主节点会生成一个RDB快照文件,该文件包含了主节点当前的数据状态。
- 主节点将RDB快照文件发送给从节点,从节点接收并加载RDB快照文件,实现数据的初始化同步。
- 在RDB快照文件生成和传输期间,主节点会继续处理客户端的请求,并将这些请求的命令缓存起来。
- 当RDB快照文件传输完成后,主节点会将缓存的命令发送给从节点,从节点执行这些命令,以保持主从数据一致性。
- 命令传播(Command Propagate)阶段:
- 同步阶段完成后,主从节点数据已保持一致。
- 当主节点接收到客户端的写请求并修改数据时,会将这些命令发送给从节点。
- 从节点接收并执行这些命令,以保持主从数据一致性。
- 配置主从关系:
Redis集群会有写操作丢失吗?为什么?
- 会
- 写操作丢失可能原因:
- 异步复制机制:如果主节点在执行完写操作后出现故障或网络问题,导致从节点无法及时接收到复制操作,那么未复制的写操作将会丢失。
- 网络分区:如果Redis集群中的某个节点或一组节点与其他节点失去联系,但客户端仍然能够连接到这些孤立节点,那么在这些节点上执行的写操作可能在集群重连后不会被其他节点获悉,导致数据丢失。
- 持久化策略:
- RDB:如果Redis在两次快照之间崩溃,并且AOF未启用或配置不当,那么自上次快照以来的所有写操作都可能丢失。
- AOF:如果AOF文件写入磁盘不及时,可能导致数据丢失。
- 配置不当:如果集群配置不当,如节点数量不够、复制因子设置较低等,可能导致数据丢失的风险加剧。
- 客户端超时或重试:网路不稳定或集群负载较高时,客户端可能遇到超时,如果客户端在超时后重试写操作而不检查之前操作的状态,可能导致数据不一致或丢失。