Redis基础知识

1. redis的数据结构

1.1 String

1.1.1 底层结构

Redis 中的 string 类型底层实现使用了 SDS(Simple Dynamic String),是因为 SDS 提供了比 C 语言原生字符串(以空字符结尾的 char*)更灵活和高效的功能

  1. SDS 的结构如下:
struct sdshdr {
    int len;      // 已使用长度
    int alloc;    // 分配的总长度(包括 len 和 free 空间)
    char buf[];   // 实际存储字符串的数据区域
};
  1. 二进制安全

SDS 支持存储二进制数据(如图片、序列化数据等),不会因遇到 \0 提前截断, 通过独立记录字符串长度(而不是依赖 \0),确保了对二进制数据的安全处理

  1. 避免缓冲区溢出

SDS 通过记录实际已用长度(len)和总分配长度(alloc),严格控制字符串操作范围,避免了这种问题

1.1.2 常用命令

1. 设置值

  • SET key value

    • 设置指定 key 的值。如果 key 已存在,会覆盖原有的值。

    • 示例:

    SET mykey "Hello, Redis"
  • SETNX key value

    • 仅在 key 不存在时设置 key 的值。如果 key 已存在,不会做任何操作。可以用于分布式锁

    • 示例:

    SETNX mykey "Hello, Redis"
  • SETEX key seconds value

    • 设置 key 的值,并同时设置过期时间(秒)。

    • 示例:

    SETEX mykey 10 "Hello, Redis"  # 10 秒后过期
  • MSET key value [key value ...]

    • 批量设置多个键值对。

    • 示例:

    MSET key1 "value1" key2 "value2" key3 "value3"
  • MSETNX key value [key value ...]

    • 批量设置多个键值对,仅在所有 key 都不存在时才会设置。

    • 示例:

    MSETNX key1 "value1" key2 "value2"

2. 获取值

  • GET key

    • 获取指定 key 的值。

    • 示例:

    GET mykey  # 返回 "Hello, Redis"
  • MGET key [key ...]

    • 批量获取多个 key 的值。

    • 示例:

    MGET key1 key2 key3  # 返回 ["value1", "value2", "value3"]

3. 删除值

  • DEL key [key ...]

    • 删除指定 key

    • 示例:

    DEL mykey
    DEL key1 key2 key3  # 批量删除

4. 检查键是否存在

  • EXISTS key

    • 检查 key 是否存在。

    • 示例:

    EXISTS mykey  # 返回 1(存在)或 0(不存在)

5. 修改值

  • SET key value

    • 设置或修改 key 的值,如前面所示。
  • INCR key

    • key 的值递增 1(适用于整数值)。

    • 示例:

    SET mynum 10
    INCR mynum  # 返回 11
  • INCRBY key increment

    • key 的值递增指定的增量。

    • 示例:

    INCRBY mynum 5  # 返回 15
  • DECR key

    • key 的值递减 1(适用于整数值)。

    • 示例:

    SET mynum 10
    DECR mynum  # 返回 9
  • DECRBY key decrement

    • key 的值递减指定的减量。

    • 示例:

    DECRBY mynum 3  # 返回 6

6. 追加和截取

  • APPEND key value

    • 将指定的值追加到 key 的当前值的末尾。如果 key 不存在,等价于 SET key value

    • 示例:

    SET mykey "Hello"
    APPEND mykey ", Redis"  # mykey 的值变为 "Hello, Redis"
  • GETRANGE key start end

    • 获取 key 的值的子字符串(通过索引)。

    • 示例:

    GETRANGE mykey 0 4  # 返回 "Hello"
  • SETRANGE key offset value

    • 从指定的偏移量开始,将 key 的值替换为新值。适用于修改字符串的部分内容。

    • 示例:

    SET mykey "Hello, World"
    SETRANGE mykey 7 "Redis"  # mykey 的值变为 "Hello, Redis"

7. 获取键的长度

  • STRLEN key

    • 获取 key 的值的长度。

    • 示例:

    STRLEN mykey  # 返回字符串长度

8. 键的过期时间

  • EXPIRE key seconds

    • 设置 key 的过期时间(秒)。

    • 示例:

    EXPIRE mykey 10  # 10 秒后 mykey 过期
  • TTL key

    • 获取 key 的剩余过期时间(秒)。

    • 示例:

    TTL mykey  # 返回剩余时间或 -1(永不过期)
  • PERSIST key

    • 移除 key 的过期时间,使其成为持久化键。

    • 示例:

    PERSIST mykey  # 取消过期时间

9. 常用命令示例

SET mykey "Hello"
GET mykey  # 返回 "Hello"
APPEND mykey " World"  # mykey 的值变为 "Hello World"
STRLEN mykey  # 返回 11
INCR mycounter  # mycounter 自增 1
MSET key1 "value1" key2 "value2"  # 批量设置

1.2 Hash

1.2.1 常用命令

设置字段值

  • 命令:

    HSET key field value
    • 设置 Hash 中字段的值,如果字段不存在则创建。
  • 示例:

    HSET user:1001 name Alice
    HSET user:1001 age 30

获取字段值

  • 命令:

    HGET key field
    • 获取 Hash 中指定字段的值。
  • 示例:

    HGET user:1001 name  # 返回 "Alice"

删除字段

  • 命令:

    HDEL key field [field ...]
    • 删除一个或多个字段。
  • 示例:

    HDEL user:1001 age

检查字段是否存在

  • 命令:

    HEXISTS key field
    • 检查 Hash 中是否存在指定字段。
  • 示例:

    HEXISTS user:1001 name  # 返回 1(存在)

获取所有字段和值

  • 命令:

    HGETALL key
    • 返回 Hash 中所有字段和值。
  • 示例:

    HGETALL user:1001
    # 返回:
    # name Alice
    # age 30

获取字段列表

  • 命令:

    HKEYS key
    • 获取 Hash 中所有字段的列表。
  • 示例:

    HKEYS user:1001  # 返回 ["name", "age"]

获取值列表

  • 命令:

    HVALS key
    • 获取 Hash 中所有值的列表。
  • 示例:

    HVALS user:1001  # 返回 ["Alice", "30"]

获取字段数量

  • 命令:

    HLEN key
    • 返回 Hash 中字段的数量。
  • 示例:

    HLEN user:1001  # 返回 2

递增字段值

  • 命令:

    HINCRBY key field increment
    • 将指定字段的值加上增量(适用于整数值)。
  • 示例:

    HSET user:1001 age 30
    HINCRBY user:1001 age 5  # age = 35

1.2.2 使用场景

缓存对象信息, 可精确修改对象属性

1.3 List

1.3.1 是什么

一个双端链表的结构,容量是2的32次方减1个元素,大概40多亿,主要功能有push/pop等,一般用在栈、队列、消息队列等场景。

left、right都可以插入添加;

如果键不存在,创建新的链表;

如果键已存在,新增内容;

如果值全移除,对应的键也就消失了。

它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。

1.3.2 常用命令

1. 插入元素

  • LPUSH key value [value ...]

    • 在 List 的左侧插入一个或多个元素。

    • 示例:

    LPUSH mylist "a"
    LPUSH mylist "b" "c"
  • RPUSH key value [value ...]

    • 在 List 的右侧插入一个或多个元素。

    • 示例:

    RPUSH mylist "d"
    RPUSH mylist "e" "f"

2. 获取元素

  • LRANGE key start stop

    • 返回指定范围内的元素(从 startstop)。

    • 示例:

    LRANGE mylist 0 -1  # 返回整个列表
    LRANGE mylist 1 3   # 返回索引从 1 到 3 的元素
  • LINDEX key index

    • 获取 List 中指定索引的元素。

    • 示例:

    LINDEX mylist 2  # 返回索引为 2 的元素

3. 修改元素

  • LSET key index value

    • 将 List 中指定索引的元素修改为新值。

    • 示例:

    LSET mylist 1 "z"  # 将索引 1 处的元素修改为 "z"

4. 删除元素

  • LREM key count value

    • 删除 List 中指定值的元素。count 控制删除的方向和数量:

    • count > 0:从左到右,删除第一个匹配的元素。

    • count < 0:从右到左,删除第一个匹配的元素。

    • count = 0:删除所有匹配的元素。

    • 示例:

    LREM mylist 1 "a"  # 删除第一个匹配的 "a"
    LREM mylist 0 "b"  # 删除所有匹配的 "b"
  • LPOP key

    • 从 List 的左侧弹出并返回一个元素。

    • 示例:

    LPOP mylist  # 删除并返回 List 左侧的元素
  • RPOP key

    • 从 List 的右侧弹出并返回一个元素。

    • 示例:

    RPOP mylist  # 删除并返回 List 右侧的元素
  • RPOPLPUSH source destination

    • source List 的右侧弹出元素,并将其插入到 destination List 的左侧。

    • 示例:

    RPOPLPUSH mylist anotherlist

5. 获取 List 的长度

  • LLEN key

    • 返回 List 的元素个数。

    • 示例:

    LLEN mylist  # 返回 mylist 的长度

6. 队列和栈操作

  • LPUSH key value [value ...] 和 RPOP key
    • 实现队列的“先进先出”操作。
  • RPUSH key value [value ...]和 LPOP key
    • 实现栈的“后进先出”操作。

7. 修剪 List

  • LTRIM key start stop

    • 修剪 List,保留从 startstop 范围内的元素。

    • 示例:

    LTRIM mylist 1 3  # 保留索引 1 到 3 的元素

1.4 Zset

1.4.1 ziplist/listpack

用于元素较少 适用于数量不超过128, 大小不超过64字节

  1. 压缩列表(ziplist)
  • 定义: ziplist 是 Redis 中的一种紧凑型双向链表,专为节省小数据量的内存设计
  • 结构:

ziplist 是一个连续的内存块,由以下部分组成:

  1. zlbytes:整个 ziplist 占用的总字节数。
  2. zltail:指向 ziplist 最后一个元素的偏移量,方便快速访问尾部。
  3. zllenziplist 中元素的数量。
  4. entries:存储实际数据,每个 entry 是一个数据项。
  5. zlend:特殊标志(值为 255),表示列表的结束。
  • 用途:

ZSet 的元素数量较少(默认小于 128 个)且每个成员和分数较短时,ZSet 会用 ziplist 存储

  • 优点: 节省内存:所有数据连续存储,没有指针, 适合小数据量的集合
  • 缺点: 随着数据量增大,插入、删除的效率变低,因为需要对内存块进行重分配。不适合频繁增删和大数据量场景
  1. 列表包(listpack)
  • 定义: listpack 是 Redis 6.0 引入的新型压缩结构,旨在替代 ziplist,以提高性能和易用性, 设计理念类似 ziplist,但解决了 ziplist 存在的一些缺陷
  • 结构:

ziplist 类似,listpack 也是一个连续的内存块,由以下部分组成:

  1. total_bytes:整个 listpack 占用的字节数。

  2. num_elements:列表中的元素数量(可能是估计值)。

  3. entries:存储实际数据,每个 entry 紧密排列,支持多种数据类型。

  4. lp_end:结束标志(值为 255)。

  • 用途:

在 Redis 6.0+ 版本中,listpack 替代了 ziplist,作为小型 ZSet 的底层存储结构

  • 改进点:

解决了 ziplist 在增删数据时频繁重新分配内存的问题,

比较:ziplist vs listpack

特性 ziplist listpack
引入版本 Redis 2.x Redis 6.0
数据存储方式 连续内存,元素交替存储 连续内存,元素交替存储
内存管理 容易导致内存碎片 改进了内存分配和布局
操作效率 插入/删除效率较低 插入/删除效率较高
兼容性 已逐渐被弃用 未来的新标准
设计缺陷 操作复杂,容易出现越界或崩溃问题 更稳定,解决了越界问题

1.4.2 skiplist

用于元素较多 自动由listpack升级为skipList

Redis 的跳表(skiplist)在 ZSet 的实现中结合了两种数据结构:跳表和哈希表(dict

  1. 跳表(skipList)

作用: 实现元素的 有序存储按分数排序 的能力, 支持范围操作(如 ZRANGEBYSCOREZRANGEBYRANK

优势: 插入、删除、按分数查询的时间复杂度是 O(logN)

  1. 哈希表(dict)

作用: 提供 元素到分数的快速映射,通过元素值直接定位分数, 用于快速判断元素是否存在

优势: 精确查找的时间复杂度是 O(1), 插入和删除效率高,不受有序性限制

1.4.3 常用命令

1. 添加/更新元素

命令格式:

ZADD key [NX|XX] [CH] [INCR] score member [score member ...]

实例:

ZADD leaderboard 100 alice 200 bob 150 charlie

作用:
leaderboard 中添加以下成员及分数:

  • alice 分数 100
  • bob 分数 200
  • charlie 分数 150

2. 查询排名范围内的成员

命令格式:

ZRANGE key start stop [WITHSCORES]

实例:

ZRANGE leaderboard 0 -1 WITHSCORES

作用:
返回 leaderboard 中按分数递增排序的所有成员及其分数。

3. 查询分数范围内的成员

命令格式:

ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

实例:

ZRANGEBYSCORE leaderboard 100 150 WITHSCORES

作用:
返回 leaderboard 中分数在 100 到 150 范围内的成员及其分数。

4. 查询递减排名范围内的成员

命令格式:

ZREVRANGE key start stop [WITHSCORES]

实例:

ZREVRANGE leaderboard 0 -1 WITHSCORES

作用:
返回 leaderboard 中按分数递减排序的所有成员及其分数。

1.5 BitMap

1.5.1 是什么

Bitmap 本质上是一个 位数组,每一位可以存储 01,对应于布尔值 falsetrue

1.5.2 常用命令

设置位(SETBIT)

  • 命令:

    SETBIT key offset value
    • 设置指定偏移量的位值(01)。
    • key:存储 Bitmap 的键。
    • offset:位的偏移量,从 0 开始。
    • value:只能为 01
  • 示例:

    SETBIT user_active 5 1  # 将偏移量 5 的位设置为 1

获取位(GETBIT)

  • 命令:

    GETBIT key offset
    • 获取指定偏移量的位值。
  • 示例:

    GETBIT user_active 5  # 获取偏移量 5 的位值

统计位值(BITCOUNT)

  • 命令:

    BITCOUNT key [start end]
    • 统计 Bitmap 中值为 1 的位的数量。
    • 可指定范围(字节索引)进行统计。
  • 示例:

    BITCOUNT user_active   # 统计整个 Bitmap 中值为 1 的位的数量
    BITCOUNT user_active 0 1  # 统计第 0 到第 1 字节范围内的值为 1 的位

按位操作(BITOP)

  • 命令:

    BITOP operation destkey key [key ...]
    • 对多个 Bitmap 进行按位操作,并将结果保存到目标键。
    • 支持的操作包括:
    • AND(按位与)
    • OR(按位或)
    • XOR(按位异或)
    • NOT(按位取反,仅支持一个键)
  • 示例:

    BITOP AND result_bitmap key1 key2

查找第一个位的位置(BITPOS)

  • 命令:

    BITPOS key bit [start] [end]
    • 查找第一个指定值(01)出现的位的偏移量。
    • 可以指定范围(字节索引)进行查找。
  • 示例:

    BITPOS user_active 1  # 查找第一个值为 1 的位的位置

Bitmap 的存储机制

  • Redis 使用 String 类型 来存储 Bitmap,每个字符串中的位可以看作一个 Bitmap 单元。
  • 假如一个字符串有 N 个字节,它总共有 N × 8 位可用。
  • Bitmap 的存储非常紧凑,每 8 位只占用 1 字节内存。

1.5.3 Bitmap 的典型应用场景

用户活跃标记

  • 用一个 Bitmap 记录每天用户的活跃情况:

    • 用户 ID 对应于位的偏移量。
    • 如果用户活跃,设置对应的位为 1,否则为 0
  • 示例:

    SETBIT user_active_20241201 1001 1  # 用户 ID 为 1001 活跃
    GETBIT user_active_20241201 1001  # 检查用户是否活跃

签到打卡

  • 将 Bitmap 用于用户签到记录,每位代表一天:

    • 通过 SETBITGETBIT 操作更新或查询签到情况。
  • 示例:

    SETBIT user_checkin 5 1  # 用户第 5 天签到
    BITCOUNT user_checkin    # 统计用户总签到天数

1.6 Stream

Redis版的MQ redis 5.x之后出现

1.6.1 stream是什么

stream: 用于处理 消息队列日志数据 场景。Stream 提供了一种高效的、可持久化的消息存储方式,支持高并发数据写入和读取,并允许消息被多个消费者组同时消费。说白了就是一个消息队列

消息: 每条消息都有一个全局唯一的 ID,格式为 ms-seq,例如 1680000000000-0

  • ms:毫秒级时间戳。
  • seq:序列号,用于同一毫秒内的多条消息区分

消息内容: 每条消息是一个键值对(field-value)集合,允许存储多个字段的数据

可以理解为一个ID为一条消息, 每个ID里面可以有多个键值对代表内容

1.6.2 Stream的基础操作

添加消息:

  • 命令:

    XADD key ID field value [field value ...]
    • ID:可以指定,也可以用 * 让 Redis 自动生成。

    • 示例:

    XADD mystream * temperature 22 humidity 60

读取消息:

  • 命令:

    XRANGE key start end [COUNT count]
    • 读取从 startend 范围的消息。

    • 示例:

    XRANGE mystream - +
    • - 表示最小 ID,+ 表示最大 ID。

删除消息:

  • 命令:

    XDEL key ID [ID ...]
    • 删除指定 ID 的消息。
  1. 消费者组

作用: 一个 Stream 可以有多个消费者组,每个消费者组独立管理自己的消费进度, 消息会被分配给消费者组中的多个消费者,避免重复消费

创建消费者组

  • 命令:

    XGROUP CREATE key groupname id
    • 创建一个消费者组。
    • id:指定起始读取 ID,通常使用 $ 表示从最后一条消息开始。

读取消息

  • 命令:

    XREADGROUP GROUP groupname consumername COUNT count STREAMS key id
    • 消费者组读取消息。

    • consumername:指定消费者名称。

    • id:通常为 >,表示读取未消费的消息。

    • 示例:

    XREADGROUP GROUP mygroup consumer1 COUNT 10 STREAMS mystream >

确认消息

  • 命令:

    XACK key groupname id [id ...]
    • 确认已处理完消息,避免重复分配。

未确认消息

  • 命令:

    XPENDING key groupname
    • 查看消费者组的未确认消息。

Stream 与其他数据结构的比较

功能 Stream List Pub/Sub
消息存储 持久化 持久化 非持久化
消息有序性 有序 有序 无序
消费者管理 支持消费者组,消息确认 无消费者管理 无消费者管理
场景适配 适合日志流、任务队列 简单队列 广播或通知

1.7 GEO

1.7.1 基本概念

Geo 类型可以存储经度和纬度坐标

1.7.2 常用命令

1 添加地理位置

  • GEOADD key longitude latitude member

    • 将指定位置的地理信息(经纬度和名称)添加到 Geo 集合中。

    • 示例:

    GEOADD mygeokey 13.361389 38.115556 "Palermo"
    GEOADD mygeokey 15.087269 37.502669 "Catania"

2. 获取地理位置的坐标

  • GEOPOS key member [member ...]

    • 返回给定成员的经纬度坐标。

    • 示例:

    GEOPOS mygeokey "Palermo"  # 返回 [13.361389, 38.115556]

3. 获取两点之间的距离

  • GEODIST key member1 member2 [unit]

    • 返回两个成员之间的距离。unit 可以是 m(米)、km(千米)、mi(英里)、ft(英尺)。

    • 示例:

    GEODIST mygeokey "Palermo" "Catania" km  # 返回两者之间的距离

4 获取成员的周边

  • GEORADIUS key longitude latitude radius [unit] [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]

    • 返回给定坐标点半径范围内的所有成员。可以选择输出成员的坐标、距离和 Geohash 值。

    • 示例:

    GEORADIUS mygeokey 15 37 100 km WITHCOORD WITHDIST # 返回经纬度和距离
  • GEORADIUSBYMEMBER key member radius [unit] [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]

    • 在指定的成员周围返回半径范围内的所有成员。

    • 示例:

    GEORADIUSBYMEMBER mygeokey "Catania" 50 km WITHCOORD

5 获取成员的排序和排名

  • GEOSORT key [ASC|DESC] [BY pattern] [GET pattern] [COUNT count] [STORE destination]

    • 对 Geo 集合进行排序并返回排序结果。可以指定排序顺序和字段。

    • 示例:

    GEOSORT mygeokey ASC

1.7.3 使用 Geo 类型的场景

位置查询:可以用于找出给定位置附近的商店、餐馆或其他兴趣点

地图应用:如地图服务提供位置搜索和附近地点推荐功能

1.7.4 Geo 类型的实现原理

Redis 使用 Geohash 编码来存储地理空间数据。每个位置的经纬度会被转换成一个 Geohash 字符串,从而能够在一个空间内索引和排序数据。使用 Geohash 的好处在于,它支持空间的范围查询和点到点的距离计算,同时具有良好的性能和精确度

 

2. 持久化机制

2.1 RDB

2.1.1 定义

RDB 是以快照的形式将内存中的数据保存到磁盘的一种机制

2.1.2 工作原理

  • 在指定的时间间隔(或触发条件)生成数据库的快照,并保存到 .rdb 文件。
  • RDB 文件是一个紧凑的二进制文件,适合备份和传输。

优点

  • 文件小,加载速度快,适合冷启动和灾难恢复。
  • 对性能的影响较小,因为快照是在后台子进程中完成的。
  • 文件格式紧凑,便于跨平台迁移。

缺点

  • 不适合对数据一致性要求很高的场景,因为如果 Redis 在快照之间宕机,会丢失最后一次快照后的数据。
  • 需要占用额外的磁盘空间。

2.1.1 配置:

使用 save 指令控制快照条件。例如:

save 900 1    # 900秒内至少有1个写操作时触发快照
save 300 10   # 300秒内至少有10个写操作时触发快照
save 60 10000 # 60秒内至少有10000个写操作时触发快照

为什么 60秒不到 + 10000次写操作 会触发

  • save 60 10000 表示在最多 60 秒内,写操作数累计达到 10000 次时触发快照。
  • 如果 Redis 检测到在 10 秒 内已经达到了 10000 次写操作,时间和写操作条件都满足,立即触发快照,无需等待到第 60 秒。

为什么 900秒不到 + 1次写操作 不会触发

  • save 900 1 的设计目的是保障长时间低频写操作场景。
  • 这种规则的特点是写操作条件容易满足,但需要等时间条件达到,即完整的 900 秒窗口内至少有一次写操作才触发。

总结: Redis 不会因为一个低频的写操作立即触发快照,而是等待窗口结束后确认条件是否满足。这是为了避免频繁保存带来的性能开销。高频规则 (save 60 10000):条件满足立即触发,因为目的是保障高并发下的数据安全。低频规则 (save 900 1):时间窗口需要完成,因为目标是以较低频率保存数据。

2.2 AOF

2.2.1 定义

AOF 是将每次写操作以日志形式记录下来,从而实现持久化。

2.2.2 工作原理

  • Redis 将每个写命令追加到 .aof 文件中, 共有(基本文件、增量文件、清单文件)
  • AOF 文件定期进行重写(Rewrite)以压缩日志文件的大小。

优点

  • 提供更高的数据安全性,可以通过配置实现秒级甚至毫秒级的数据持久化。
  • AOF 文件更易于阅读和分析,因为它是纯文本格式。

缺点

  • 文件相对较大,恢复速度较慢。
  • 写入速度比 RDB 略低,对性能有一定影响。

2.2.3 配置

关键参数:

appendonly yes           # 启用AOF
appendfsync always       # 每次写入都同步到磁盘,性能最低,安全性最高
appendfsync everysec     # 每秒同步一次,性能与安全性折中(默认)
appendfsync no           # 不同步,由操作系统决定刷盘时机,性能高但不安全

2.3 两种方式对比

2.3.1 对比

特性 RDB AOF
数据安全性 丢失快照后数据 丢失最近未写入磁盘的命令
性能影响 性能开销低,适合大数据量备份 性能开销较大
文件大小 紧凑,较小 日志记录多,文件较大
恢复速度 恢复速度快 恢复速度较慢
可读性 二进制文件,不易读 文本格式,易于分析

2.3.2 混合持久化

Redis 从 4.0 开始支持混合持久化模式(Hybrid Persistence),将 RDB 和 AOF 的优点结合:

  • 在持久化时,先保存 RDB 快照,再将最近的 AOF 日志追加到 RDB 文件后。
  • 这样既保证了恢复速度(RDB),也减少了数据丢失(AOF)。

配置方式:

aof-use-rdb-preamble yes

 

3. 淘汰策略

3.1 过期策略

3.1.1. 设置键的过期时间

可以通过以下命令为键设置过期时间:

  • EXPIRE key seconds:为键设置过期时间,单位为秒。
  • PEXPIRE key milliseconds:为键设置过期时间,单位为毫秒。
  • EXPIREAT key timestamp:设置键在指定的 Unix 时间戳(秒)到期。
  • PEXPIREAT key timestamp:设置键在指定的 Unix 时间戳(毫秒)到期。

查询剩余过期时间:

  • TTL key:查询键的剩余过期时间(秒)。
  • PTTL key:查询键的剩余过期时间(毫秒)。

3.1.2 过期策略

.1 惰性删除(Lazy Deletion)

  • Redis 在读取某个键时会检查该键是否已过期。
  • 如果已过期,则立即删除该键,并返回空结果。
  • 优点:对 CPU 资源影响最小,仅在访问过期键时触发检查。
  • 缺点:如果过期键从未被访问,则可能一直占用内存。

2 定期删除(Periodic Deletion)

  • Redis 会定期扫描过期字典中的键,主动删除过期的键。
  • 扫描频率和时间片由配置参数控制:
    • hz:每秒钟 Redis 事件循环的执行次数,影响定期任务的频率(默认为 10)。
    • 定期删除的扫描是分片进行的,避免一次性检查大量键导致性能抖动。
  • 优点:能清理一部分过期键,避免内存占用过多。
  • 缺点:可能无法及时删除所有过期键,导致内存占用延迟释放。

3.2 内存淘汰

当 Redis 内存不足时,配合过期键的清理机制,Redis 提供了以下淘汰策略:

1 不淘汰(noeviction)

  • 当内存达到限制时,对写操作直接返回错误,不会删除任何键。
  • 默认策略。

2 删除最近最少使用的键(LRU,Least Recently Used)

  • volatile-lru:从设置了过期时间的键中,删除最近最少使用的键。
  • allkeys-lru:从所有键中删除最近最少使用的键。

3 删除最近最少访问的键(LFU,Least Frequently Used)

  • volatile-lfu:从设置了过期时间的键中,删除访问频率最低的键。
  • allkeys-lfu:从所有键中删除访问频率最低的键。

4 随机删除(Random)

  • volatile-random:从设置了过期时间的键中,随机删除。
  • allkeys-random:从所有键中,随机删除。

5 删除即将过期的键(TTL,Time To Live)

  • volatile-ttl:从设置了过期时间的键中,删除过期时间最接近的键。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇