Redis系列:(一)Redis概念详解

2025-06-22 00:03
248
0

Redis 作为一款开源的内存型数据结构存储系统,在当今的分布式系统架构中扮演着极为关键的角色,凭借其出色的读写速度、丰富的数据类型和强大的功能,在缓存、消息队列、分布式系统等众多场景中得到了广泛应用。本系列文章,将从基本概念入手,逐步深入到核心功能与底层原理,将为你全面剖析 Redis 的各项特性。

TIP:Redis的安装配置这里就不做多讲,网上有很多,这里贴一个讲解Redis比较全面的网站:《Redis 教程 | 菜鸟教程》

一、基本概念

Redis,即 Remote Dictionary Server(远程字典服务器)的缩写,它采用键值对(key - value)的存储形式(通俗点理解其实就是一个巨大的HashMap),其中每个键都具有唯一性,通过键能够快速定位并获取对应的值。由于数据完全存储在内存中,Redis 拥有卓越的读写性能,能完美应对高并发场景下对数据的快速访问需求,极大提升系统的响应速度。

Redis作为一个巨大的HashMap,能存哪些数据,如何进行操作?

1.1、常用数据类型和命令

Redis支持多种数据类型,每种数据类型都有其独特的用途,如下列举一些常用的数据类型和基础操作命令。

  • 字符串(String):最基本的数据类型,可以存储字符串、整数或浮点数。使用场景:缓存、计数器、共享Session、限流等。
    • SET 命令:用于设置键值对,语法为SET key value [EX seconds] [PX milliseconds] [NX|XX]。其中,EX seconds表示设置键的过期时间为seconds秒;PX milliseconds表示设置键的过期时间为milliseconds毫秒;NX表示只有当键不存在时才设置键值XX表示只有当键已存在时才设置键值。例如,SET mykey "Hello Redis" EX 60,将键mykey的值设置为Hello Redis,并在 60 秒后过期。
    • GET 命令:用于获取指定键的值,语法为GET key。如GET mykey,将返回mykey对应的值。
    • INCR 命令:用于对存储的整数进行自增操作,语法为INCR key。若键不存在,则默认初始值为 0,然后进行自增。例如,SET num 5,再执行INCR numnum的值将变为 6。
    • INCRBY 命令:用于将值增加给定的增量(increment),语法为INCRBY key increment
    • DECR 命令:与INCR相反,用于对存储的整数进行自减操作,语法为DECR key
    • DECRBY 命令:用于将值减去给定的减量值(decrement),语法为DECRBY key decrement
    • MSET 命令:用于同时设置一个或多个键值对,语法为MSET key1 value1 key2 value2 ...。该命令是原子性操作,要么所有键值对都设置成功,要么都失败。例如,在用户注册场景中,需要同时设置用户的姓名、年龄和邮箱,可执行MSET user:1001:name "CYX" user:1001:age 25 user:1001:email "``cyx@example.com``",一次性完成多个键值对的设置。
    • MGET 命令:用于同时获取一个或多个键的值,语法为MGET key1 key2 ...。比如,在展示用户信息页面时,需要获取用户的姓名、年龄和邮箱,执行MGET user:1001:name user:1001:age user:1001:email,即可一次性获取这三个键对应的值,提高数据获取效率。
    • APPEND 命令:如果key已经存在并且是一个字符串,此命名会将value追加到原来值的末尾。语法为:APPEND key value
  • 列表(List):是一个有序的字符串列表,可以在列表的头部或尾部添加元素。list最大的存储元素个数:2的32次方-1 = 4294967295
    • LPUSH 命令:将一个或多个值插入到列表头部,语法为LPUSH key value [value ...]。例如,LPUSH mylist "apple" "banana",会将bananaapple依次插入到列表mylist的头部。
    • RPUSH 命令:将一个或多个值插入到列表尾部,语法为RPUSH key value [value ...]
    • LPOP 命令移除并返回列表的头元素,语法为LPOP key
    • RPOP 命令移除并返回列表的尾元素,语法为RPOP key
    • BLPOP 和 BRPOP 命令:从左边或者右边移除第一个元素,如果列表中没有元素,会阻塞列表直到等待超时或发现可弹出的元素为止。语法BLPOP|BRPOP key1 [key2] timeout,超时时间设置为0表示不设置等待超时时间,会一直等待到有数据可弹出为止。这个命令可以实现一个简单的消息中间件的功能。
    • LINDEX 命令:通过索引获取列表中的元素。语法为 LINDEX key index
    • LRANGE 命令获取列表指定范围内的元素,语法为LRANGE key start stop。其中,startstop为元素的索引,索引从 0 开始,-1表示最后一个元素。例如,LRANGE mylist 0 -1将返回列表mylist的所有元素。
    • LREM 命令:用于从列表中移除指定数量的与某个值相等的元素。其基本语法为:LREM key count value其中key表示列表的键名。count表示移除元素的方式,分为三种情况:1、正数表示从列表头部开始,移除前count个等于value的元素。2、负数表示从列表尾部开始,移除前count个等于value的元素。3、零表示移除所有等于value的元素。命令返回被移除元素的数量。若列表不存在,返回 0。
    • LTRIM 命令:列表进行修剪,只保留指定区间中的元素。语法为:LTRIM key start stop,其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
    • LSET 命令:设置指定索引下的值。语法LSET key index value
  • 集合(Set):是一个无序的不重复字符串集合,支持集合的交、并、差等操作。使用场景:打标签
    • SADD 命令:将一个或多个成员添加到集合中,语法为SADD key member [member ...]。例如,SADD myset "red" "green",将redgreen添加到集合myset中。
    • SMEMBERS 命令:返回集合中的所有成员,语法为SMEMBERS key
    • SISMEMBER 命令:判断一个成员是否在集合中,语法为SISMEMBER key member。如果成员存在,返回 1;否则返回 0。
    • SINTER 命令:返回给定集合的交集,语法为SINTER key [key ...]。例如,SINTER set1 set2将返回set1set2的交集。
    • SUNION 命令:返回给定集合的并集,语法为SUNION key [key ...]
    • SDIFF 命令:返回给定集合的差集,语法为SDIFF key [key ...]
  • 有序集合(Sorted Set):与集合类似,但每个元素都关联一个分数(score),集合中的元素按照分数从小到大排序。
    • ZADD 命令:将一个或多个成员及其分数添加到有序集合中,语法为ZADD key [NX|XX] [CH] [INCR] score member [score member ...]。其中,NX表示只有当成员不存在时才添加;XX表示只有当成员已存在时才更新;CH表示返回此次操作中分数发生变化的成员及其分数变化情况;INCR表示对成员的分数进行递增操作。例如,ZADD myzset 1 "one" 2 "two",将onetwo添加到有序集合myzset中,分数分别为 1 和 2。
    • ZRANGE 命令:按照分数范围获取有序集合中的成员,语法为ZRANGE key start stop [WITHSCORES]WITHSCORES参数表示同时返回成员及其分数。例如,ZRANGE myzset 0 -1 WITHSCORES将返回myzset中的所有成员及其分数。
    • ZRANK 命令:获取有序集合中成员的排名(从 0 开始),语法为ZRANK key member。例如,ZRANK myzset "one"将返回onemyzset中的排名。
  • 哈希(Hash):是一个键值对的集合,可以理解为HashMap或者字典,适合存储对象
    • HSET 命令:用于在哈希表中设置字段值,语法为HSET key field value。例如,HSET myhash name "John" age 30,将在哈希表myhash中设置name字段为Johnage字段为 30。
    • HSETNX 命令:只有在字段 field 不存在时,才设置哈希表字段的值。语法为:HSETNX key field value
    • HGET 命令获取哈希表中指定字段的值,语法为HGET key field。如HGET myhash name将返回John
    • HMSET和HMGET 命令:其实就是HSET和HGET的批量命令,语法为:HMGET key field1 [field2] 和 HMSET key field1 value1 [field2 value2 ]
    • HGETALL 命令获取哈希表中的所有字段和值,语法为HGETALL key
    • HDEL 命令删除哈希表中的一个或多个字段,语法为HDEL key field [field ...]

TIP:企业中key的命名可以参考如下格式,业务名:对象名:id:[属性]

更多命令可以参考其它网站的汇总:Redis命令

1.2、高级数据类型和命令

Redis 还提供了一些高级数据类型,以满足更复杂的业务需求。

1.2.1、位图(Bitmaps)

位图其本质上是基于字符串类型实现的,但它可以按位进行操作,适合需要大规模布尔值存储、高效统计(如计数、交集)的场景。对数据稀疏、需要复杂查询逻辑或频繁删除操作的场景不适合。

相关命令:

  • SETBIT 命令:用于设置位图中指定偏移量(offset)的位值,语法为SETBIT key offset value,其中value只能是 0 或 1。例如,SETBIT user_login_status 100 1,表示将user_login_status位图中偏移量为 100 的位设置为 1。
  • GETBIT 命令:获取位图中指定偏移量的位值,语法为GETBIT key offset
  • BITCOUNT 命令:统计位图中值为 1 的位的数量,语法为BITCOUNT key [start end]startend参数可选,用于指定统计的字节范围。

应用的场景:

  • 用户签到统计:用一个位图表示用户一年的签到记录(0/1),每日占 1 位,365 天仅需 46 字节。可以高效统计连续签到、签到次数(BITCOUNT)。
  • 活跃用户统计:以用户 ID 为偏移量,记录每天的活跃状态(0/1),可快速计算日活、月活。可以节省内存(1 亿用户仅需 12MB),支持按位运算(如BITOP AND计算多日活跃交集)。
  • 数据状态标记:例如标记用户权限(如管理员 / 普通用户)、商品库存状态(有货 / 缺货)等。可以快速查询和修改单个状态(GETBIT/SETBIT)。
  • 布隆过滤器:用多个哈希函数映射元素到位图,判断元素是否存在。
    • 可能误判但不会漏判:不存在的情况能正确判断出来,存在的情况可能会因为Hash冲突导致误判。
    • 误判的优化方案:可以通过多个Hash函数来确认是否都存在Hash冲突。
    • 使用场景:可以作为缓存穿透防护、URL 去重、黑名单、邮件垃圾过滤。
  • 用户在线状态:实时标记用户在线 / 离线,支持大规模用户基数下的状态统计。

优点

  • 极致节省内存:每 100 万个标记仅需 125KB 内存(100 万 bit ≈ 122KB)。
  • 操作高效:单个位的设置 / 查询时间复杂度为 O (1),批量操作(如BITCOUNT)也非常快。
  • 支持位运算:可对多个位图执行 AND/OR/XOR/NOT 操作,适合多维数据分析。
  • 原子性:所有操作都是原子的,无需担心并发问题。

缺点

  • 偏移量限制:位图的最大偏移量为 2^32-1(约 42.9 亿),可能需要分片存储海量数据。
  • 空间效率问题:若偏移量分布稀疏(如用户 ID 不连续),会浪费大量内存。解决方案:使用SETBIT前预分配空间,或改用其他结构(如HASH)。
  • 复杂操作支持有限:仅支持位级操作,无法直接实现复杂逻辑(如范围查询)。
  • 可读性差:二进制数据难以直接调试和理解,需通过工具转换。

1.2.2、超日志(HyperLogLog)

Redis HyperLogLog 是一种概率性数据结构,用于估算集合的基数(去重元素数量)。它的核心优势是只需极小的内存(固定 12KB)就能统计极大的数据量(如 2^64 个元素),误差率约为 0.81%

相关命令介绍:

  • PFADD 命令:将一个或多个元素添加到 HyperLogLog 中,语法为PFADD key element [element ...]。例如,PFADD myhll "a" "b" "c",将abc添加到myhll中。
  • PFCOUNT 命令:返回 HyperLogLog 中估算的不重复元素数量,语法为PFCOUNT key [key ...]。如果传入多个键,将返回这些键对应的 HyperLogLog 合并后的估算数量。
  • PFMERGE 命令:将多个 HyperLogLog 合并为一个,语法为PFMERGE destkey sourcekey [sourcekey ...]。例如,PFMERGE newhll hll1 hll2,将hll1hll2合并到newhll中。

应用场景

  • UV(独立访客)统计:每天一个 HyperLogLog,统计网站日活、月活。优势:内存占用极低(12KB 可统计数十亿用户),支持合并(PFCOUNT多个 HyperLogLog)。
  • 数据去重计数:统计搜索关键词、文章标签的独立数量。比SET节省 99% 以上内存,比 Bitmaps 更适合非布尔值场景。
  • 实时数据监控:监控系统中独立 IP、设备的访问量。优势:插入和查询时间复杂度均为 O (1),适合高并发场景。
  • 数据库分库分表去重:跨库统计用户、订单等数据的总独立量。

优缺点:

  • 优点:
    • 内存占用极低:固定 12KB,无论统计 100 万还是 10 亿元素。
    • 高性能:插入和查询操作时间复杂度均为 O (1),且无锁。
    • 可合并性:支持多个 HyperLogLog 合并(PFMERGE),适合分布式系统。
  • 缺点:
    • 存在误差:标准误差率 0.81%,不适合精确统计(如财务数据)。
    • 无法获取明细:仅能返回基数估算值,不能获取具体元素内容。
    • 单次写入成本高:内部结构复杂,写入性能略低于普通SET。
    • 数据不可变:一旦创建无法删除单个元素,只能整体重置。

原理:HyperLogLog基于概率论中伯努利试验,并结合了极大似然估算方法,并做了分桶优化

1.2.3、地理空间(Geospatial)

Redis3.2版本提供了GEO(地理信息定位)功能,用于存储地理位置信息,并提供了一系列用于计算距离、查找附近位置等操作的命令。可以用来实现诸如:附近位置、摇一摇等类似功能。

相关命令介绍:

  • GEOADD 命令:将一个或多个地理位置(经度、纬度、名称)添加到键中,语法为GEOADD key longitude latitude member [longitude latitude member ...]。例如,GEOADD cities 116.40 39.90 beijing 121.47 31.23 shanghai
  • GEODIST 命令:计算两个地理位置之间的距离,语法为GEODIST key member1 member2 [unit]unit参数可选,用于指定距离单位,如m(米)、km(千米)等。
  • GEORADIUS 命令:以给定的地理位置为中心,查找一定范围内的其他地理位置,语法为GEORADIUS key longitude latitude radius unit [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]

1.3、其它Redis命令

  • 键操作命令
    • KEYS 命令:用于查找所有符合给定模式的键,语法为KEYS pattern。例如,KEYS my*将返回所有以my开头的键。但在生产环境中,由于可能会阻塞 Redis 服务器,不建议使用,可使用SCAN命令替代。SCAN命令采用游标方式渐进式查找,不会阻塞服务器。
    • EXISTS 命令:判断一个或多个键是否存在,语法为EXISTS key [key ...]。如果存在,返回 1;否则返回 0。
    • DEL 命令:删除一个或多个键,语法为DEL key [key ...]
    • RENAME 命令:修改键的名称,语法为RENAME key newkey。如果newkey已存在,将被覆盖。
  • 数据库操作命令
    • SELECT 命令:用于切换数据库,Redis 默认有 16 个数据库,编号从 0 到 15,语法为SELECT index。例如,SELECT 2将切换到编号为 2 的数据库。
    • FLUSHDB 命令:删除当前数据库中的所有键,语法为FLUSHDB
    • FLUSHALL 命令:删除所有数据库中的所有键,语法为FLUSHALL
  • 发布 / 订阅(Pub/Sub):允许客户端发布消息到指定频道,其他订阅了该频道的客户端会收到相应消息,常用于实时消息推送场景。
    • PUBLISH 命令:将消息发布到指定频道,语法为PUBLISH channel message。例如,PUBLISH news_channel "Breaking news!"
    • SUBSCRIBE 命令:订阅一个或多个频道,语法为SUBSCRIBE channel [channel ...]。客户端执行该命令后,将进入订阅模式,等待接收消息。
    • UNSUBSCRIBE 命令:退订一个或多个频道,语法为UNSUBSCRIBE [channel [channel ...]]
  • 流(Streams):是一种强大的数据结构,用于实现日志记录、消息队列等功能,支持复杂的消息处理和消费语义。
    • XADD 命令:向流中添加一个新的消息,语法为XADD key * field value [field value ...],其中*表示自动生成唯一的消息 ID。例如,XADD event_stream * event "user_login" user_id 123
    • XREAD 命令:从流中读取消息,语法为XREAD STREAMS key [key ...] $$表示从流的末尾开始读取,也可以指定具体的消息 ID 进行读取。
    • XGROUP 命令:用于管理消费者组,包括创建、删除消费者组等操作。例如,XGROUP CREATE event_stream group1 $ MKSTREAM,创建一个名为group1的消费者组,并在流不存在时创建流。
  • 模块(Modules):允许开发者扩展 Redis 的功能,通过加载外部模块实现自定义的数据类型、命令等。例如,RedisJSON 模块为 Redis 添加了对 JSON 数据的支持,提供了一系列操作 JSON 数据的命令;RedisGraph 模块则为 Redis 增加了图形数据库的功能。

注意:生产环境尽量避免使用keys命令,生产环境数据量大的情况(几万、几十万+),如果直接使用keys * 命令,会刷出大量数据可能导致Redis阻塞。

二、应用场景介绍

2.1、缓存功能

Redis 最常用的功能之一就是作为缓存。在传统的应用架构中,数据库往往是性能瓶颈,因为磁盘 I/O 操作相对较慢。而 Redis 基于内存存储数据,读写速度极快,可以将一些经常被访问但更新频率较低的数据存储在 Redis 中,当应用程序需要这些数据时,优先从 Redis 中获取,只有在 Redis 中不存在时,才去数据库查询,并将查询结果存入 Redis,以便后续使用。

例如,在一个新闻网站中,新闻详情页面的数据更新频率较低,但访问量很大。可以将新闻详情数据存储在 Redis 中,每次用户请求新闻详情时,先从 Redis 中获取数据,如果获取到则直接返回给用户;如果 Redis 中没有,则从数据库中查询,然后将查询结果存入 Redis,并设置一个合理的过期时间(如几分钟或几小时),以保证数据的时效性。这样可以大大减轻数据库的压力,提高应用的响应速度。

2.2、分布式锁

在分布式系统中,多个进程或线程可能同时访问共享资源,为了避免数据不一致等问题,需要使用锁机制。Redis 可以实现分布式锁,其原理是利用 Redis 的原子性操作。

常见的实现方式是使用SET命令的NX参数。当一个进程想要获取锁时,使用SET lock_key "lock_value" NX EX lock_timeout命令尝试设置一个键值对,其中lock_key是锁的名称,lock_value可以是任意唯一标识该进程的值,NX表示只有当键不存在时才设置成功,即获取锁成功;EX lock_timeout设置锁的过期时间,防止进程在获取锁后因异常未释放锁而导致死锁。如果设置成功,该进程就获得了锁,可以执行相关操作;操作完成后,使用DEL lock_key命令释放锁。

例如,在一个分布式任务调度系统中,多个节点可能同时尝试执行同一个任务,通过 Redis 分布式锁可以保证同一时间只有一个节点执行该任务,避免任务重复执行或数据冲突。

2.3、消息队列

Redis 可以作为简单的消息队列使用,主要利用列表(List)数据类型的LPUSHRPOP命令。生产者使用LPUSH命令将消息添加到列表头部,消费者使用RPOP命令从列表尾部获取消息,从而实现消息的生产和消费。

为了实现更可靠的消息队列,还可以结合BRPOP命令(阻塞式获取)。当列表中没有消息时,BRPOP命令会阻塞消费者,直到有新消息加入列表,这样可以避免消费者频繁轮询,提高效率。

例如,在一个电商系统中,订单生成后,需要进行一系列后续操作,如库存扣减、发送邮件通知等。可以将订单相关信息作为消息发送到 Redis 消息队列中,不同的消费者(如库存处理模块、邮件发送模块)从队列中获取消息并进行相应处理,实现系统的解耦和异步处理。

三、内部机制

3.1、数据持久化

Redis 是基于内存的数据库,为了保证数据在服务器重启后不丢失,提供了两种持久化方式:RDB(Redis Database)和 AOF(Append Only File)。

RDB:RDB 是一种快照式的持久化方式,它将 Redis 在某一时刻的内存数据以二进制文件的形式保存到磁盘上。Redis 会按照配置的规则(如多久一次、数据集大小达到多少时)自动触发 RDB 快照,也可以使用SAVEBGSAVE命令手动触发。SAVE命令会阻塞 Redis 服务器,直到快照完成;而BGSAVE命令会 fork 一个子进程,由子进程进行快照操作,不会阻塞主线程。RDB 的优点是恢复速度快,因为直接加载二进制文件到内存即可;缺点是数据安全性相对较低,因为两次快照之间的数据变化可能会丢失。

AOF:AOF 是一种日志式的持久化方式,它会将 Redis 执行的每一个写命令追加到 AOF 文件中。当 Redis 服务器重启时,会重新执行 AOF 文件中的命令来恢复数据。AOF 可以配置不同的同步策略,如always(每个写命令都同步到磁盘)、everysec(每秒同步一次)、no(由操作系统决定何时同步)。always策略数据安全性最高,但性能最差;everysec策略在保证较高数据安全性的同时,对性能影响较小,是默认的同步策略。AOF 的优点是数据安全性高,基本可以保证不丢失数据;缺点是文件体积较大,恢复速度相对较慢。

3.2、内存管理

Redis 采用了一种混合的内存管理方式。一方面,它使用了 jemalloc 内存分配器,jemalloc 是一个高效的内存分配库,能够减少内存碎片,提高内存分配和释放的效率。例如,在频繁分配和释放小内存块的场景下,jemalloc 可以避免内存碎片的产生,使得内存的使用更加紧凑和高效。

另一方面,Redis 对不同数据类型的内存使用进行了优化。对于字符串类型,当字符串长度较小时,采用紧凑的存储方式,直接在数据结构中存储字符串内容;当字符串长度较大时,则会使用动态分配的内存来存储。对于列表、集合等复杂数据类型,通过合理的数据结构设计,减少内存浪费。同时,Redis 还支持设置最大内存限制,当内存使用达到限制时,可以根据配置的淘汰策略(如volatile - lruallkeys - lru等)自动删除一些数据,以释放内存空间。

3.3、数据结构实现

Redis 的数据类型在底层是通过多种数据结构实现的。

字符串:Redis底层是用的C语言编写的,但其没有直接使用C语言的String类型,而是自己去实现了字符串类型,其底层实现主要是简单动态字符串(SDS),它克服了传统 C 语言字符串在长度计算、内存分配等方面的不足。SDS 不仅记录了字符串的内容,还记录了字符串的长度等信息,在进行字符串操作(如追加、截取)时,能够更高效地管理内存,避免缓冲区溢出等问题。

列表:在底层,列表可以使用双向链表或压缩列表(ziplist)来实现当列表元素较少且每个元素长度较短时,使用压缩列表可以节省内存空间;当列表元素较多或元素长度较大时,会转换为双向链表,以提高操作效率,如在列表头部或尾部插入、删除元素等操作的时间复杂度为 O (1)。

集合集合的底层实现有两种方式,当集合中的元素都是整数且元素数量较少时,使用整数集合(intset);当元素不是整数或元素数量较多时,使用哈希表(dict)。整数集合在存储整数时,能够根据元素的范围自动调整存储方式,以节省内存;哈希表则提供了高效的查找、插入和删除操作,时间复杂度平均为 O (1)。

哈希:哈希表是 Redis 哈希类型的底层实现。它采用链式哈希(拉链法)来解决哈希冲突,当多个键的哈希值相同时,会将这些键值对存储在同一个哈希桶的链表中。同时,Redis 会根据哈希表的负载因子自动进行扩容和缩容操作,以保证哈希表的性能。

有序集合:有序集合的底层实现是跳跃表(skiplist)和哈希表的结合。跳跃表用于按照分数对元素进行排序,提供了高效的范围查询操作;哈希表则用于快速根据成员查找其分数,使得插入、删除和查找操作的时间复杂度都能保持在较低水平。

3.4、事件驱动模型

Redis 采用事件驱动模型来处理客户端请求和内部事件。Redis 的事件主要分为文件事件(网络 I/O 事件)和时间事件。

文件事件Redis 使用 I/O 多路复用技术(如 epoll、kqueue 等)来监听多个客户端的套接字。当有客户端连接请求、数据发送或接收等操作时,会产生文件事件。Redis 将这些事件与相应的事件处理器关联起来,当事件发生时,调用对应的处理器进行处理。例如,当有新的客户端连接到 Redis 服务器时,会触发连接事件处理器,接受客户端连接,并将客户端套接字加入到事件监听列表中;当客户端发送命令请求时,会触发读事件处理器,读取命令并进行解析和执行。

时间事件:时间事件主要用于实现 Redis 的定时任务,如过期键的删除、RDB 和 AOF 的持久化操作等。Redis 将时间事件存储在一个有序链表中,按照事件的到期时间排序。在每次事件循环中,Redis 会检查时间事件链表,执行到期的时间事件。同时,Redis 的事件循环是单线程的,这保证了操作的原子性,避免了多线程编程中的锁竞争等问题,使得 Redis 在处理高并发请求时也能保持高效和稳定。

 

全部评论