淘宝客的网站是自己做的吗,辽宁建设工程信息网官网查不良行为,河南衣柜网站建设公司,怎么查看一个网站的浏览量Redis5.0 中还增加了一个数据类型Stream#xff0c;它借鉴了Kafka的设计#xff0c;是一个新的强大的支持多播的可持久化的消息队列。pdai Redis入门 - 数据类型#xff1a;Stream详解 为什么会设计StreamStream详解 Stream的结构增删改查独立消费消费组消费信息监控 更深入… Redis5.0 中还增加了一个数据类型Stream它借鉴了Kafka的设计是一个新的强大的支持多播的可持久化的消息队列。pdai Redis入门 - 数据类型Stream详解 为什么会设计StreamStream详解 Stream的结构增删改查独立消费消费组消费信息监控 更深入理解 Stream用在什么样场景消息ID的设计是否考虑了时间回拨的问题消费者崩溃带来的会不会消息丢失问题?消费者彻底宕机后如何转移给其它消费者处理坏消息问题Dead Letter死信问题 参考文章
为什么会设计Stream Redis5.0 中还增加了一个数据结构Stream从字面上看是流类型但其实从功能上看应该是Redis对消息队列MQMessage Queue的完善实现。 用过Redis做消息队列的都了解基于Reids的消息队列实现有很多种例如
PUB/SUB订阅/发布模式 但是发布订阅模式是无法持久化的如果出现网络断开、Redis 宕机等消息就会被丢弃 基于List LPUSHBRPOP 或者 基于Sorted-Set的实现 支持了持久化但是不支持多播分组消费等
为什么上面的结构无法满足广泛的MQ场景 这里便引出一个核心的问题如果我们期望设计一种数据结构来实现消息队列最重要的就是要理解设计一个消息队列需要考虑什么初步的我们很容易想到
消息的生产消息的消费 单播和多播多对多阻塞和非阻塞读取 消息有序性消息的持久化
其它还要考虑啥嗯借助美团技术团队的一篇文章消息队列设计精要 中的图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-897sCe4r-1618488032466)(https://pdai.tech/_images/db/redis/db-redis-stream-1.png)]
我们不妨看看Redis考虑了哪些设计
消息ID的序列化生成消息遍历消息的阻塞和非阻塞读取消息的分组消费未完成消息的处理消息队列监控… 这也是我们需要理解Stream的点但是结合上面的图我们也应该理解Redis Stream也是一种超轻量MQ并没有完全实现消息队列所有设计要点这决定着它适用的场景。 Stream详解 经过梳理总结我认为从以下几个大的方面去理解Stream是比较合适的总结如下pdai Stream的结构设计生产和消费 基本的增删查改单一消费者的消费消费组的消费 监控状态
Stream的结构
每个 Stream 都有唯一的名称它就是 Redis 的 key在我们首次使用 xadd 指令追加消息时自动创建。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jMAbo6d6-1618488032470)(https://pdai.tech/_images/db/redis/db-redis-stream-2.png)]
上图解析
Consumer Group 消费组使用 XGROUP CREATE 命令创建一个消费组有多个消费者(Consumer), 这些消费者之间是竞争关系。last_delivered_id 游标每个消费组会有个游标 last_delivered_id任意一个消费者读取了消息都会使游标 last_delivered_id 往前移动。pending_ids 消费者(Consumer)的状态变量作用是维护消费者的未确认的 id。 pending_ids 记录了当前已经被客户端读取的消息但是还没有 ack (Acknowledge character确认字符。如果客户端没有ack这个变量里面的消息ID会越来越多一旦某个消息被ack它就开始减少。这个pending_ids变量在Redis官方被称之为PEL也就是Pending Entries List这是一个很核心的数据结构它用来确保客户端至少消费了消息一次而不会在网络传输的中途丢失了没处理。
此外我们还需要理解两点
消息ID: 消息ID的形式是timestampInMillis-sequence例如1527846880572-5它表示当前的消息在毫米时间戳1527846880572时产生并且是该毫秒内产生的第5条消息。消息ID可以由服务器自动生成也可以由客户端自己指定但是形式必须是整数-整数而且必须是后面加入的消息的ID要大于前面的消息ID。消息内容: 消息内容就是键值对形如hash结构的键值对这没什么特别之处。
增删改查
消息队列相关命令
XADD - 添加消息到末尾XTRIM - 对流进行修剪限制长度XDEL - 删除消息XLEN - 获取流包含的元素数量即消息长度XRANGE - 获取消息列表会自动过滤已经删除的消息XREVRANGE - 反向获取消息列表ID 从大到小XREAD - 以阻塞或非阻塞方式获取消息列表
# *号表示服务器自动生成ID后面顺序跟着一堆key/value
127.0.0.1:6379 xadd codehole * name laoqian age 30 # 名字叫laoqian年龄30岁
1527849609889-0 # 生成的消息ID
127.0.0.1:6379 xadd codehole * name xiaoyu age 29
1527849629172-0
127.0.0.1:6379 xadd codehole * name xiaoqian age 1
1527849637634-0
127.0.0.1:6379 xlen codehole
(integer) 3
127.0.0.1:6379 xrange codehole - # -表示最小值, 表示最大值
127.0.0.1:6379 xrange codehole -
1) 1) 1527849609889-01) 1) name1) laoqian2) age3) 30
2) 1) 1527849629172-01) 1) name1) xiaoyu2) age3) 29
3) 1) 1527849637634-01) 1) name1) xiaoqian2) age3) 1
127.0.0.1:6379 xrange codehole 1527849629172-0 # 指定最小消息ID的列表
1) 1) 1527849629172-02) 1) name2) xiaoyu3) age4) 29
2) 1) 1527849637634-02) 1) name2) xiaoqian3) age4) 1
127.0.0.1:6379 xrange codehole - 1527849629172-0 # 指定最大消息ID的列表
1) 1) 1527849609889-02) 1) name2) laoqian3) age4) 30
2) 1) 1527849629172-02) 1) name2) xiaoyu3) age4) 29
127.0.0.1:6379 xdel codehole 1527849609889-0
(integer) 1
127.0.0.1:6379 xlen codehole # 长度不受影响
(integer) 3
127.0.0.1:6379 xrange codehole - # 被删除的消息没了
1) 1) 1527849629172-02) 1) name2) xiaoyu3) age4) 29
2) 1) 1527849637634-02) 1) name2) xiaoqian3) age4) 1
127.0.0.1:6379 del codehole # 删除整个Stream
(integer) 1独立消费
我们可以在不定义消费组的情况下进行Stream消息的独立消费当Stream没有新消息时甚至可以阻塞等待。Redis设计了一个单独的消费指令xread可以将Stream当成普通的消息队列(list)来使用。使用xread时我们可以完全忽略消费组(Consumer Group)的存在就好比Stream就是一个普通的列表(list)。
# 从Stream头部读取两条消息
127.0.0.1:6379 xread count 2 streams codehole 0-0
1) 1) codehole2) 1) 1) 1527851486781-02) 1) name2) laoqian3) age4) 302) 1) 1527851493405-02) 1) name2) yurui3) age4) 29
# 从Stream尾部读取一条消息毫无疑问这里不会返回任何消息
127.0.0.1:6379 xread count 1 streams codehole $
(nil)
# 从尾部阻塞等待新消息到来下面的指令会堵住直到新消息到来
127.0.0.1:6379 xread block 0 count 1 streams codehole $
# 我们从新打开一个窗口在这个窗口往Stream里塞消息
127.0.0.1:6379 xadd codehole * name youming age 60
1527852774092-0
# 再切换到前面的窗口我们可以看到阻塞解除了返回了新的消息内容
# 而且还显示了一个等待时间这里我们等待了93s
127.0.0.1:6379 xread block 0 count 1 streams codehole $
1) 1) codehole2) 1) 1) 1527852774092-02) 1) name2) youming3) age4) 60
(93.11s)客户端如果想要使用xread进行顺序消费一定要记住当前消费到哪里了也就是返回的消息ID。下次继续调用xread时将上次返回的最后一个消息ID作为参数传递进去就可以继续消费后续的消息。
block 0表示永远阻塞直到消息到来block 1000表示阻塞1s如果1s内没有任何消息到来就返回nil
127.0.0.1:6379 xread block 1000 count 1 streams codehole $
(nil)
(1.07s)消费组消费
消费组消费图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oVJE29jp-1618488032473)(https://pdai.tech/_images/db/redis/db-redis-stream-3.png)] 相关命令 XGROUP CREATE - 创建消费者组XREADGROUP GROUP - 读取消费者组中的消息XACK - 将消息标记为已处理XGROUP SETID - 为消费者组设置新的最后递送消息IDXGROUP DELCONSUMER - 删除消费者XGROUP DESTROY - 删除消费者组XPENDING - 显示待处理消息的相关信息XCLAIM - 转移消息的归属权XINFO - 查看流和消费者组的相关信息XINFO GROUPS - 打印消费者组的信息XINFO STREAM - 打印流信息 创建消费组
Stream通过xgroup create指令创建消费组(Consumer Group)需要传递起始消息ID参数用来初始化last_delivered_id变量。
127.0.0.1:6379 xgroup create codehole cg1 0-0 # 表示从头开始消费
OK
# $表示从尾部开始消费只接受新消息当前Stream消息会全部忽略
127.0.0.1:6379 xgroup create codehole cg2 $
OK
127.0.0.1:6379 xinfo stream codehole # 获取Stream信息1) length2) (integer) 3 # 共3个消息3) radix-tree-keys4) (integer) 15) radix-tree-nodes6) (integer) 27) groups8) (integer) 2 # 两个消费组9) first-entry # 第一个消息
10) 1) 1527851486781-02) 1) name2) laoqian3) age4) 30
11) last-entry # 最后一个消息
12) 1) 1527851498956-02) 1) name2) xiaoqian3) age4) 1
127.0.0.1:6379 xinfo groups codehole # 获取Stream的消费组信息
1) 1) name2) cg13) consumers4) (integer) 0 # 该消费组还没有消费者5) pending6) (integer) 0 # 该消费组没有正在处理的消息
2) 1) name2) cg23) consumers # 该消费组还没有消费者4) (integer) 05) pending6) (integer) 0 # 该消费组没有正在处理的消息消费组消费
Stream提供了xreadgroup指令可以进行消费组的组内消费需要提供消费组名称、消费者名称和起始消息ID。它同xread一样也可以阻塞等待新消息。读到新消息后对应的消息ID就会进入消费者的PEL(正在处理的消息)结构里客户端处理完毕后使用xack指令通知服务器本条消息已经处理完毕该消息ID就会从PEL中移除。
# 号表示从当前消费组的last_delivered_id后面开始读
# 每当消费者读取一条消息last_delivered_id变量就会前进
127.0.0.1:6379 xreadgroup GROUP cg1 c1 count 1 streams codehole
1) 1) codehole2) 1) 1) 1527851486781-02) 1) name2) laoqian3) age4) 30
127.0.0.1:6379 xreadgroup GROUP cg1 c1 count 1 streams codehole
1) 1) codehole2) 1) 1) 1527851493405-02) 1) name2) yurui3) age4) 29
127.0.0.1:6379 xreadgroup GROUP cg1 c1 count 2 streams codehole
1) 1) codehole2) 1) 1) 1527851498956-02) 1) name2) xiaoqian3) age4) 12) 1) 1527852774092-02) 1) name2) youming3) age4) 60
# 再继续读取就没有新消息了
127.0.0.1:6379 xreadgroup GROUP cg1 c1 count 1 streams codehole
(nil)
# 那就阻塞等待吧
127.0.0.1:6379 xreadgroup GROUP cg1 c1 block 0 count 1 streams codehole
# 开启另一个窗口往里塞消息
127.0.0.1:6379 xadd codehole * name lanying age 61
1527854062442-0
# 回到前一个窗口发现阻塞解除收到新消息了
127.0.0.1:6379 xreadgroup GROUP cg1 c1 block 0 count 1 streams codehole
1) 1) codehole2) 1) 1) 1527854062442-02) 1) name2) lanying3) age4) 61
(36.54s)
127.0.0.1:6379 xinfo groups codehole # 观察消费组信息
1) 1) name2) cg13) consumers4) (integer) 1 # 一个消费者5) pending6) (integer) 5 # 共5条正在处理的信息还有没有ack
2) 1) name2) cg23) consumers4) (integer) 0 # 消费组cg2没有任何变化因为前面我们一直在操纵cg15) pending6) (integer) 0
# 如果同一个消费组有多个消费者我们可以通过xinfo consumers指令观察每个消费者的状态
127.0.0.1:6379 xinfo consumers codehole cg1 # 目前还有1个消费者
1) 1) name2) c13) pending4) (integer) 5 # 共5条待处理消息5) idle6) (integer) 418715 # 空闲了多长时间ms没有读取消息了
# 接下来我们ack一条消息
127.0.0.1:6379 xack codehole cg1 1527851486781-0
(integer) 1
127.0.0.1:6379 xinfo consumers codehole cg1
1) 1) name2) c13) pending4) (integer) 4 # 变成了5条5) idle6) (integer) 668504
# 下面ack所有消息
127.0.0.1:6379 xack codehole cg1 1527851493405-0 1527851498956-0 1527852774092-0 1527854062442-0
(integer) 4
127.0.0.1:6379 xinfo consumers codehole cg1
1) 1) name2) c13) pending4) (integer) 0 # pel空了5) idle6) (integer) 745505信息监控
Stream提供了XINFO来实现对服务器信息的监控可以查询
查看队列信息
127.0.0.1:6379 Xinfo stream mq1) length2) (integer) 73) radix-tree-keys4) (integer) 15) radix-tree-nodes6) (integer) 27) groups8) (integer) 19) last-generated-id
10) 1553585533795-9
11) first-entry
12) 1) 1553585533795-32) 1) msg2) 4
13) last-entry
14) 1) 1553585533795-92) 1) msg2) 10消费组信息
127.0.0.1:6379 Xinfo groups mq
1) 1) name2) mqGroup3) consumers4) (integer) 35) pending6) (integer) 37) last-delivered-id8) 1553585533795-4消费者组成员信息
127.0.0.1:6379 XINFO CONSUMERS mq mqGroup
1) 1) name2) consumerA3) pending4) (integer) 15) idle6) (integer) 18949894
2) 1) name2) consumerB3) pending4) (integer) 15) idle6) (integer) 3092719
3) 1) name2) consumerC3) pending4) (integer) 15) idle6) (integer) 23683256至此消息队列的操作说明大体结束
更深入理解 我们结合MQ中常见问题看Redis是如何解决的来进一步理解Redis。 Stream用在什么样场景
可用作时通信等大数据分析异地数据备份等
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KhCn50VW-1618488032475)(https://pdai.tech/_images/db/redis/db-redis-stream-4.png)]
客户端可以平滑扩展提高处理能力
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mmcKk7BA-1618488032477)(https://pdai.tech/_images/db/redis/db-redis-stream-5.png)]
消息ID的设计是否考虑了时间回拨的问题 在 分布式算法 - ID算法设计中, 一个常见的问题就是时间回拨问题那么Redis的消息ID设计中是否考虑到这个问题呢 XADD生成的1553439850328-0就是Redis生成的消息ID由两部分组成:时间戳-序号。时间戳是毫秒级单位是生成消息的Redis服务器时间它是个64位整型int64。序号是在这个毫秒时间点内的消息序号它也是个64位整型。
可以通过multi批处理来验证序号的递增
127.0.0.1:6379 MULTI
OK
127.0.0.1:6379 XADD memberMessage * msg one
QUEUED
127.0.0.1:6379 XADD memberMessage * msg two
QUEUED
127.0.0.1:6379 XADD memberMessage * msg three
QUEUED
127.0.0.1:6379 XADD memberMessage * msg four
QUEUED
127.0.0.1:6379 XADD memberMessage * msg five
QUEUED
127.0.0.1:6379 EXEC
1) 1553441006884-0
2) 1553441006884-1
3) 1553441006884-2
4) 1553441006884-3
5) 1553441006884-4由于一个redis命令的执行很快所以可以看到在同一时间戳内是通过序号递增来表示消息的。
为了保证消息是有序的因此Redis生成的ID是单调递增有序的。由于ID中包含时间戳部分为了避免服务器时间错误而带来的问题例如服务器时间延后了Redis的每个Stream类型数据都维护一个latest_generated_id属性用于记录最后一个消息的ID。若发现当前时间戳退后小于latest_generated_id所记录的则采用时间戳不变而序号递增的方案来作为新消息ID这也是序号为什么使用int64的原因保证有足够多的的序号从而保证ID的单调递增性质。
强烈建议使用Redis的方案生成消息ID因为这种时间戳序号的单调递增的ID方案几乎可以满足你全部的需求。但同时记住ID是支持自定义的别忘了
消费者崩溃带来的会不会消息丢失问题?
为了解决组内消息读取但处理期间消费者崩溃带来的消息丢失问题STREAM 设计了 Pending 列表用于记录读取但并未处理完毕的消息。命令XPENDIING 用来获消费组或消费内消费者的未处理完毕的消息。演示如下
127.0.0.1:6379 XPENDING mq mqGroup # mpGroup的Pending情况
1) (integer) 5 # 5个已读取但未处理的消息
2) 1553585533795-0 # 起始ID
3) 1553585533795-4 # 结束ID
4) 1) 1) consumerA # 消费者A有3个2) 32) 1) consumerB # 消费者B有1个2) 13) 1) consumerC # 消费者C有1个2) 1127.0.0.1:6379 XPENDING mq mqGroup - 10 # 使用 start end count 选项可以获取详细信息
1) 1) 1553585533795-0 # 消息ID2) consumerA # 消费者3) (integer) 1654355 # 从读取到现在经历了1654355msIDLE4) (integer) 5 # 消息被读取了5次delivery counter
2) 1) 1553585533795-12) consumerA3) (integer) 16543554) (integer) 4
# 共5个余下3个省略 ...127.0.0.1:6379 XPENDING mq mqGroup - 10 consumerA # 在加上消费者参数获取具体某个消费者的Pending列表
1) 1) 1553585533795-02) consumerA3) (integer) 16410834) (integer) 5
# 共3个余下2个省略 ...每个Pending的消息有4个属性
消息ID所属消费者IDLE已读取时长delivery counter消息被读取次数
上面的结果我们可以看到我们之前读取的消息都被记录在Pending列表中说明全部读到的消息都没有处理仅仅是读取了。那如何表示消费者处理完毕了消息呢使用命令 XACK 完成告知消息处理完成演示如下
127.0.0.1:6379 XACK mq mqGroup 1553585533795-0 # 通知消息处理结束用消息ID标识
(integer) 1127.0.0.1:6379 XPENDING mq mqGroup # 再次查看Pending列表
1) (integer) 4 # 已读取但未处理的消息已经变为4个
2) 1553585533795-1
3) 1553585533795-4
4) 1) 1) consumerA # 消费者A还有2个消息处理2) 22) 1) consumerB2) 13) 1) consumerC2) 1
127.0.0.1:6379有了这样一个Pending机制就意味着在某个消费者读取消息但未处理后消息是不会丢失的。等待消费者再次上线后可以读取该Pending列表就可以继续处理该消息了保证消息的有序和不丢失。
消费者彻底宕机后如何转移给其它消费者处理 还有一个问题就是若某个消费者宕机之后没有办法再上线了那么就需要将该消费者Pending的消息转义给其他的消费者处理就是消息转移。 消息转移的操作时将某个消息转移到自己的Pending列表中。使用语法XCLAIM来实现需要设置组、转移的目标消费者和消息ID同时需要提供IDLE已被读取时长只有超过这个时长才能被转移。演示如下
# 当前属于消费者A的消息1553585533795-1已经15907,787ms未处理了
127.0.0.1:6379 XPENDING mq mqGroup - 10
1) 1) 1553585533795-12) consumerA3) (integer) 159077874) (integer) 4# 转移超过3600s的消息1553585533795-1到消费者B的Pending列表
127.0.0.1:6379 XCLAIM mq mqGroup consumerB 3600000 1553585533795-1
1) 1) 1553585533795-12) 1) msg2) 2# 消息1553585533795-1已经转移到消费者B的Pending中。
127.0.0.1:6379 XPENDING mq mqGroup - 10
1) 1) 1553585533795-12) consumerB3) (integer) 84404 # 注意IDLE被重置了4) (integer) 5 # 注意读取次数也累加了1次以上代码完成了一次消息转移。转移除了要指定ID外还需要指定IDLE保证是长时间未处理的才被转移。被转移的消息的IDLE会被重置用以保证不会被重复转移以为可能会出现将过期的消息同时转移给多个消费者的并发操作设置了IDLE则可以避免后面的转移不会成功因为IDLE不满足条件。例如下面的连续两条转移第二条不会成功。
127.0.0.1:6379 XCLAIM mq mqGroup consumerB 3600000 1553585533795-1
127.0.0.1:6379 XCLAIM mq mqGroup consumerC 3600000 1553585533795-1这就是消息转移。至此我们使用了一个Pending消息的ID所属消费者和IDLE的属性还有一个属性就是消息被读取次数delivery counter该属性的作用由于统计消息被读取的次数包括被转移也算。这个属性主要用在判定是否为错误数据上。
坏消息问题Dead Letter死信问题
正如上面所说如果某个消息不能被消费者处理也就是不能被XACK这是要长时间处于Pending列表中即使被反复的转移给各个消费者也是如此。此时该消息的delivery counter就会累加上一节的例子可以看到当累加到某个我们预设的临界值时我们就认为是坏消息也叫死信DeadLetter无法投递的消息由于有了判定条件我们将坏消息处理掉即可删除即可。删除一个消息使用XDEL语法演示如下
# 删除队列中的消息
127.0.0.1:6379 XDEL mq 1553585533795-1
(integer) 1
# 查看队列中再无此消息
127.0.0.1:6379 XRANGE mq -
1) 1) 1553585533795-02) 1) msg2) 1
2) 1) 1553585533795-22) 1) msg2) 3注意本例中并没有删除Pending中的消息因此你查看Pending消息还会在。可以执行XACK标识其处理完毕
参考文章
本文主要梳理总结自
https://www.runoob.com/redis/redis-stream.htmlhttps://www.zhihu.com/question/279540635https://zhuanlan.zhihu.com/p/60501638
知识体系
知识体系 相关文章 首先我们通过学习Redis的概念基础了解它适用的场景。 Redis入门 - Redis概念和基础 Redis是一种支持key-value等多种数据结构的存储系统。可用于缓存事件发布或订阅高速队列等场景。支持网络提供字符串哈希列表队列集合结构直接存取基于内存可持久化。 其次这些适用场景都是基于Redis支持的数据类型的所以我们需要学习它支持的数据类型同时在redis优化中还需要对底层数据结构了解所以也需要了解一些底层数据结构的设计和实现。 Redis入门 - 数据类型5种基础数据类型详解 Redis所有的key键都是字符串。我们在谈基础数据结构时讨论的是存储值的数据类型主要包括常见的5种数据类型分别是String、List、Set、Zset、Hash Redis入门 - 数据类型3种特殊类型详解 Redis除了上文中5种基础数据类型还有三种特殊的数据类型分别是 HyperLogLogs基数统计 Bitmaps (位图) 和 geospatial 地理位置 Redis入门 - 数据类型Stream详解 Redis5.0 中还增加了一个数据结构Stream它借鉴了Kafka的设计是一个新的强大的支持多播的可持久化的消息队列。 Redis进阶 - 底层数据结构对象机制详解 我们在前文已经阐述了Redis 5种基础数据类型详解分别是字符串(string)、列表(list)、哈希(hash)、集合(set)、有序集合(zset)以及5.0版本中Redis Stream结构详解那么这些基础类型的底层是如何实现的呢Redis的每种对象其实都由对象结构(redisObject) 与 对应编码的数据结构组合而成, 本文主要介绍对象结构(redisObject) 部分。。 Redis进阶 - 底层数据结构底层数据结构详解 前文是第一部分底层设计对象机制详解, 本文主要介绍底层数据结构 部分。 Redis进阶 - 底层数据结构redis对象与编码(底层结构)对应关系详解 在学习完底层数据结构之后我们终于可以结合前文内容阐述redis对象及编码之间的关系了。 再者需要学习Redis支持的核心功能包括持久化消息事务高可用高可用方面包括主从哨兵等高可拓展方面比如 分片机制等。 Redis进阶 - 持久化RDB和AOF机制详解 为了防止数据丢失以及服务重启时能够恢复数据Redis支持数据的持久化主要分为两种方式分别是RDB和AOF; 当然实际场景下还会使用这两种的混合模式。 Redis进阶 - 消息传递发布订阅模式详解 Redis 发布订阅(pub/sub)是一种消息通信模式发送者(pub)发送消息订阅者(sub)接收消息。 Redis进阶 - 事件Redis事件机制详解 Redis 采用事件驱动机制来处理大量的网络IO。它并没有使用 libevent 或者 libev 这样的成熟开源方案而是自己实现一个非常简洁的事件驱动库 ae_event。 Redis进阶 - 事务Redis事务详解 Redis 事务的本质是一组命令的集合。事务支持一次执行多个命令一个事务中所有命令都会被序列化。在事务执行过程会按照顺序串行化执行队列中的命令其他客户端提交的命令请求不会插入到事务执行命令序列中。 Redis进阶 - 高可用主从复制详解 我们知道要避免单点故障即保证高可用便需要冗余副本方式提供集群服务。而Redis 提供了主从库模式以保证数据副本的一致主从库之间采用的是读写分离的方式。本文主要阐述Redis的主从复制。 Redis进阶 - 高可用哨兵机制Redis Sentinel详解 在上文主从复制的基础上如果注节点出现故障该怎么办呢 在 Redis 主从集群中哨兵机制是实现主从库自动切换的关键机制它有效地解决了主从复制模式下故障转移的问题。 Redis进阶 - 高可拓展分片技术Redis Cluster详解 前面两篇文章主从复制和哨兵机制保障了高可用就读写分离而言虽然slave节点来扩展主从的读并发能力但是写能力和存储能力是无法进行扩展的就只能是master节点能够承载的上限。如果面对海量数据那么必然需要构建master主节点分片)之间的集群同时必然需要吸收高可用主从复制和哨兵机制能力即每个master分片节点还需要有slave节点这是分布式系统中典型的纵向扩展集群的分片技术的体现所以在Redis 3.0版本中对应的设计就是Redis Cluster。 最后就是具体的实践以及实践中遇到的问题和解决方法了在不同版本中有不同特性所以还需要了解版本以及性能优化大厂实践等。 Redis进阶 - 缓存问题一致性, 穿击, 穿透, 雪崩, 污染等 Redis最常用的一个场景就是作为缓存本文主要探讨作为缓存在实践中可能会有哪些问题比如一致性, 穿击, 穿透, 雪崩, 污染等 Redis进阶 - 版本特性: Redis4.0、5.0、6.0特性整理 在学习Redis知识体系时我们难免会需要查看版本实现之间的差异本文主要整理Redis较为新的版本的特性。 Redis进阶 - 运维监控Redis的监控详解 Redis实战中包含开发集群 和 运维Redis用的好不好如何让它更好这是运维要做的本文主要在 Redis自身状态及命令可视化监控工具以及Redis监控体系等方面帮助你构建对redis运维/监控体系的认知它是性能优化的前提。 Redis进阶 - 性能调优Redis性能调优详解 Redis 的性能问题涉及到的知识点非常广几乎涵盖了 CPU、内存、网络、甚至磁盘的方方面面同时还需要对上文中一些基础或底层有详细的了解。针对Redis的性能调优这里整理分享一篇水滴与银弹公众号的文章这篇文章可以帮助你构筑Redis性能调优的知识体系。 Redis大厂经验 - 微博万亿级日访问量下Redis在微博的9年优化历程 再分享一篇微博使用redis的经验的文章因为Redis在微博内部分布在各个应用场景比如像现在春晚必争的“红包飞”活动还有像粉丝数、用户数、阅读数、转评赞、评论盖楼、广告推荐、负反馈、音乐榜单等等都有用到Redis我们可以通过大厂使用redis的经验来强化对redis使用上的认知。
学习资料 Redis官网:http://redis.io/ Redis官方文档:http://redis.io/documentation Redis教程:http://www.w3cschool.cn/redis/redis-intro.html Redis下载:http://redis.io/download redis英文文档 https://redis.io/topics/data-types redis中文文档 http://www.redis.cn/documentation.html 《redis设计与实现 3.0版本》 http://redisbook.com/index.html redis菜鸟教程 https://www.runoob.com/redis/redis-tutorial.html redis源码解读 3.2.8版本 https://blog.csdn.net/men_wen/article/details/75668345 本篇文章由一文多发平台ArtiPub自动发布