From 58fa0617ce1edc2c773df32299513095d9127b27 Mon Sep 17 00:00:00 2001 From: asahi Date: Wed, 17 Sep 2025 14:32:35 +0800 Subject: [PATCH] =?UTF-8?q?doc:=20=E9=98=85=E8=AF=BBredis=20stream=20docum?= =?UTF-8?q?ent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 中间件/redis/redis.md | 86 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/中间件/redis/redis.md b/中间件/redis/redis.md index fd5bb39..99e575e 100644 --- a/中间件/redis/redis.md +++ b/中间件/redis/redis.md @@ -114,6 +114,12 @@ - [Enhanced deletion control in Redis 8.2](#enhanced-deletion-control-in-redis-82) - [Stream Observability](#stream-observability) - [Difference with kafka partitions](#difference-with-kafka-partitions) + - [Capped Streams](#capped-streams) + - [XADD with MAXLEN](#xadd-with-maxlen) + - [XTRIM](#xtrim) + - [Trimming with consumer group Awareness](#trimming-with-consumer-group-awareness) + - [Special IDs in streams API](#special-ids-in-streams-api) + - [Persistence, replication and message safety](#persistence-replication-and-message-safety) # redis @@ -2065,3 +2071,83 @@ Redis stream中的consumer group可能在某些方面类似于kafka中基于分 - 如果stream的数量为1,consumer的数量为n,那么可以将负载均衡给n个consumers,但是,在这种情况下消息的消费可能是无序的 - 当使用n个stream和n个consumers时,一个consumer只用于处理所有streams中的一部分,可以将`1 stream->1 consumer`拓展到`n stream->n consuimer` +#### Capped Streams +在许多应用中,并不想在stream中永久存储data。有时,需要限制stream中entries的最大数量。 + +##### XADD with MAXLEN +redis stream对上述特性提供了支持,在使用`XADD`命令时,支持指定`MAXLEN`选项,示例如下所示: +```redis-cli +> XADD race:italy MAXLEN 2 * rider Jones +"1692633189161-0" +> XADD race:italy MAXLEN 2 * rider Wood +"1692633198206-0" +> XADD race:italy MAXLEN 2 * rider Henshaw +"1692633208557-0" +> XLEN race:italy +(integer) 2 +> XRANGE race:italy - + +1) 1) "1692633198206-0" + 2) 1) "rider" + 2) "Wood" +2) 1) "1692633208557-0" + 2) 1) "rider" + 2) "Henshaw" +``` + +当使用`MAXLEN`选项时,如果达到了指定长度,那么old entries将自动被淘汰,从而确保stream处于恒定的大小。 + +`trimming with MAXLEN`的开销在部分场景下可能会变得很大:为了内存效率,stream由radix-tree结构表示。radix-tree由macro nodes组成,单个macro node中包含多个elements,对单个macro node的修改并不高效。 + +故而,支持按照如下形式来使用`XADD`命令,并支持`MAXLEN`选项: +```redis-cli +XADD race:italy MAXLEN ~ 1000 * ... entry fields here ... +``` + +在上述示例中,在`MAXLEN`和`count`之间指定了`~`,代表`并不需要将长度上限严格限制为1000`。该长度可以是`1000`,可以是`1010`,只保证该长度比1000大。在指定了`~`后,只有当允许移除整个节点时,trimming操作才会被实际执行。指定`~`能够让`MAXLEN`操作更加高效。 + +##### XTRIM +同样的,redis还支持`XTRIM`命令,其执行和`MAXLEN`类似: +```redis-cli +> XTRIM race:italy MAXLEN 10 +(integer) 0 + +> XTRIM mystream MAXLEN ~ 10 +(integer) 0 +``` + +除此之外,`XTRIM`命令还支持不同的trimming strategies: +- `MINID`:该trimming strategy支持对`entries with IDs lower than the on specified`进行淘汰 + +##### Trimming with consumer group Awareness +从redis 8.2开始,`XADD with trimming options`和`XTRIM`命令都支持`enhanced control over how trimming interacts with consumer groups`,其支持`KEEPREF, DELREF, ACKED`三个选项: +```redis-cli +XADD mystream KEEPREF MAXLEN 1000 * field value +XTRIM mystream ACKED MAXLEN 1000 +``` +- `KEEPREF`(default): Trim entries according to the strategy but preserves references references in consumer groups' PELs +- `DELREF`: Trims entries and removes all references from consumer groups' PELs +- `ACKED`: Only Trims entries that have been acknowledged by all consumer groups + +`ACKED`模式在多个consumer groups之间维护数据完整性十分有用,其能够保证entries只有`当被所有的consumer groups都处理完成之后`才会被移除 + +#### Special IDs in streams API +在redis API中,存在部分`Special IDs`: +- `-, +`: 这两个特殊ID分别代表`the smallest ID possible`和`the greatest ID possible` +- `$`: 该ID代表`stream中已经存在的最大ID`。在使用`XREADGROUP`命令时,如果只希望读取new entries,可以使用该`special ID`。同样的,可以将consumer group的`last delivered ID`设置为`$`,从而`just deliver new entries to consumers in the group`。 +- `>`: 该ID代表`last delivered ID of a consumer group`,该ID的适用范围仅位于同一`consumer group`内,并且该ID仅在`XREADGROUP`命令中使用,代表`we want only entries that were never delivered to other consumers so far`。 +- `*`: 该ID仅在`XADD`命令中被使用,代表为new entry自动选中ID + +#### Persistence, replication and message safety +stream和redis中的其他数据结构一样,`is asynchronously replicated to replicas`,并且持久化到`RDB`和`AOF`文件中。并且,`consumer group的full state也会被传播到AOF, RDB, replcias中`。 + +故而,如果`message is pending in the master, also the replica will have the same information`。并且,当重启后,AOF也会恢复consumer group的状态。 + +redis streams和consumer groups将会被持久化,并且`replicated using the Redis default replication`: +- 如果消息的持久化十分重要,那么`AOF必须使用strong fsync policy` +- `redis asynchronously replication`并不能保证`xadd`/`consumer group state changes`能被同步到replica: + - 当发生failover(故障转移,指哨兵或集群模式下主节点发生故障,replica节点被升级为主节点),可能主节点的变化尚未被同步到replica,此时failover将会产生data missing +- `WAIT命令可以强制使changes被传播给replicas`,该命令仅会降低数据丢失的可能,但是并无法完全避免数据的丢失。 + - 在发生故障转移时,redis仅会执行`best effort check`,从而转移到`replica which is the most updated`,在某些失败场景下,转移到的replica仍然可能缺失部分数据 + + +