它使本次 5.x 版本迭代中,Redis 作为消息队列使用时,得到更完善,更强大的原生支持,其中尤为明显的是持久化消息队列。...除了服务端自动生成 Id 方式外,也支持指定 Id 的生成,但是指定 Id 有以下条件限制: Id 中的前后部分必须为数字。 最小 Id 为 0-1,不能为 0-0,但是 2-0,3-0 .......是被允许的。 添加的消息,Id 的前半部分不能比存在 Id 最大的值小,Id 后半部分不能比存在前半部分相同的最大后半部分小。...即使添加消息时,由于 Id 异常,也可以在 Redis 中存在以当前 Streams 的名称。Streams 中 Id 也可作为指针使用,因为它是一个有序的标记。...消费消息 在 Redis 的 PUB/SUB 中,我们是通过订阅来消费消息,在 Streams 数据结构中,同样也能实现同等功能,当没有新的消息时,可进行阻塞等待。
streams数据结构 streams数据结构本身非常简单,但是streams依然是Redis到目前为止最复杂的类型,其原因是实现的一些额外的功能:一系列的阻塞操作允许消费者等待生产者加入到streams...XADD命令也支持显示指定ID,例如:XADD streamname 0-2 foo bar。 时钟回拨 需要注意的是,ID的时间戳部分是部署Redis服务器的本地时间,如果发生时钟回拨会怎么样?...这个命令用来返回streams某个顺序范围下的元素,start参数是更小的ID,end参数是更大的ID。...有两个特殊的ID用符号"-"和"+"表示,符号"-"表示最小的ID,符号"+"表示最大的ID: 127.0.0.1:6379> XRANGE userInfo "1540014096298-0" "1540014477236...需要注意的是,Redis的streams和消费者组使用Redis默认复制进行持久化和复制,因此:如果消息的持久性在您的应用程序中很重要,则必须将AOF与强fsync策略一起使用。
在《消息顺序性为何这么难?》中,介绍了一种为了保证“所有群友展示的群消息时序都是一致的”所使用的“ID串行化”的方法:让同一个群gid的所有消息落在同一台服务器上处理。 ID串行化是如何实现的呢?...这里的“服务层”至关重要,ID串行化保证的是,同一个群gid的消息落在同一个服务上。 画外音:服务集群有很多节点,如果能落在同一个服务节点上,就可以利用这个服务节点做消息串行化。...如上图: (1)上游是业务应用; (2)下游是服务集群; (3)业务应用,它又分为了这么几个部分: - 上层是任务队列(粉色); - 中间是工作线程(蓝色),每个工作线程完成实际的业务任务,典型的工作任务是通过服务连接池进行...需要注意的是,连接池不关心传入的long id是什么业务含义: (1)传入群gid,同gid的请求落在同一个服务上; (2)传入用户uid,同uid的请求落在同一个服务上; (3)传入任何业务xid,同业务...不会,只要数据访问id是均衡的,从全局来看,由id取模获取各连接的概率也是均等的,即负载是均衡的。 获取连接,ID取模,希望大家有收获。
至少在概念上是这样,因为Redis Streams是一种在内存中的抽象数据类型,所以它实现了更强大的操作,以克服日志文件本身的限制。...序列号用于在相同毫秒内创建的条目。由于序列号是64位的,所以在相同的毫秒内可以生成的条目数是没有限制的。 这些ID的格式最初看起来可能很奇怪,善意的读者可能想知道为什么时间是ID的一部分。...,就像下面的例子这样: XADD somestream 0-1 field value 0-1 > XADD somestream 0-2 foo bar 0-2 请注意,在这种情况下,最小ID为0-1...返回的范围将包括开始和结束ID的元素,因此范围是包含首项与末项的。这两种特殊ID-和+分别意味着可能的最小和最大的ID。...这两个ID分别表示可能的最小ID(基本上是0-1)和可能的最大ID(即18446744073709551615-18446744073709551615)。
还可以从以下几个方面来理解: 1.字节(Byte)是电脑中表示信息含义的最小单位,因为在通常情况下一个ACSII码就是一个字节的空间来存放。...而事实上电脑中还有比字节更小的单位,因为一个字节是由八个二进制位组成的,换一句话说,每个二进制位所占的空间才是电脑中最小的单位,我们把它称为位,也称比特(bit)。由此可见,一个字节等于八个位。...另外,内存中运算的最小存储单位是字节,位运算也是在一个字节的存储单位的基础上进行的,所以存储的最小单位可以理解为字节。...2.bit是二进制数的一位包含的信息或2个选项中特别指定1个的需要信息量称为一比特,是表示信息的最小单位,只有两种状态:0和1。...电脑内部的电路工作有高电平和低电平两种状态.所以就用二进制来表示信号,以便计算机识别。所以计算机能传输的最小单位当然是你信号的单位bit,而不是字节,串口最小也有一位传递的。
就是效率最高的,为什么呢,因为多线程的本质就是 CPU 模拟出来多个线程的情况,这种模拟出来的情况就有一个代价,就是上下文的切换,对于一个内存的系统来说,它没有上下文的切换就是效率最高的。...答案是:下层的存储等慢速的情况。比如磁盘 内存是一个 IOPS 非常高的系统,因为我想申请一块内存就申请一块内存,销毁一块内存我就销毁一块内存,内存的申请和销毁是很容易的。...而且内存是可以动态的申请大小的。 磁盘的特性是:IPOS很低很低,但吞吐量很高。这就意味着,大量的读写操作都必须攒到一起,再提交到磁盘的时候,性能最高。为什么呢?...终于把 redis 为什么是单线程说清楚了,把什么时候用单线程跟多线程也说清楚了,其实也是些很简单的东西,只是基础不好的时候,就真的尴尬。。。。 ...顺便再提一句:redis 的瓶颈在网络上 。。。。
就是效率最高的,为什么呢,因为多线程的本质就是 CPU 模拟出来多个线程的情况,这种模拟出来的情况就有一个代价,就是上下文的切换,对于一个内存的系统来说,它没有上下文的切换就是效率最高的。...答案是:下层的存储等慢速的情况。比如磁盘 内存是一个 IOPS 非常高的系统,因为我想申请一块内存就申请一块内存,销毁一块内存我就销毁一块内存,内存的申请和销毁是很容易的。...而且内存是可以动态的申请大小的。 磁盘的特性是:IPOS很低很低,但吞吐量很高。这就意味着,大量的读写操作都必须攒到一起,再提交到磁盘的时候,性能最高。为什么呢?...终于把 redis 为什么是单线程说清楚了,把什么时候用单线程跟多线程也说清楚了,其实也是些很简单的东西,只是基础不好的时候,就真的尴尬。。。。 ...CPU内核,为了优化Redis,我们可以使用工具为单线程绑定固定的CPU内核,减少不必要的性能损耗!
除了服务端自动生成 Id 方式外,也支持指定 Id 的生成,但是指定 Id 有以下条件限制: Id 中的前后部分必须为数字。最小 Id 为 0-1,不能为 0-0,但是 2-0,3-0 .......即使添加消息时,由于 Id 异常,也可以在 Redis 中存在以当前 Streams 的名称。Streams 中 Id 也可作为指针使用,因为它是一个有序的标记。...时间戳是毫秒级单位,是生成消息的 Redis 服务器时间,它是个 64 位整型(int64)。序号是在这个毫秒时间点内的消息序号,它也是个 64 位整型。...为了保证消息是有序的,因此 Redis 生成的 ID 是_单调递增_有序的。...读取消息(消费消息) 在 Redis 的 PUB/SUB 中,我们是通过订阅来消费消息,在 Streams 数据结构中,同样也能实现同等功能,当没有新的消息时,可进行阻塞等待。
如果指定的ID参数是*字符,XADD命令将自动生成唯一的ID。自动生成ID时,第一部分是生成ID的Redis实例的Unix时间(以毫秒为单位)。第二部分只是序列号,用于区分在同一毫秒内生成的ID。...当用户为XADD指定显式ID时,最小有效ID为0-1,并且用户必须指定一个大于流中当前任何其他ID的ID,否则命令将失败并返回错误。...读取消息 XREAD XREAD可用于从消息流中读取数据。 格式应该看得出来吧。 最后的参数是消息ID,redis会返回大于该ID的消息。...“0-0”是一个特殊的ID,代表最小的消息ID,使用它可以要求redis从头读取消息。 XREAD 也可以阻塞客户端,等待消息流中接收新的消息。...通常这个命令这样使用乎好一些: XREAD BLOCK 1000 STREAMS mystream $ $ 也是一个特殊ID,表示当前最大的消息ID。使用它可以要求redis读取最新的消息。
如果你在以前面试的时候还没有遇到过面试官问你《为什么说Redis是单线程的以及Redis为什么这么快!》,那么你看到这篇文章的时候,你应该觉得是一件很幸运的事情!...我们先探讨一下Redis是什么,Redis为什么这么快、然后在探讨一下为什么Redis是单线程的?...二、Redis简介 Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间件。...五、那么为什么Redis是单线程的 我们首先要明白,上边的种种分析,都是为了营造一个Redis很快的氛围!...“SID”栏表示线程ID,而“CMD”栏则显示了线程名称。 警告2:在上图中FAQ中的最后一段,表述了从Redis 4.0版本开始会支持多线程的方式,但是,只是在某一些操作上进行多线程的操作!
Redis5.0迎来了一种新的数据结构Streams,没有了解过的同学可以先阅读前文,今天来介绍一下Streams相关的命令。...然而在生产环境中并不常用,通常需要我们指定一种格式较好的唯一ID。 默认的ID生成策略是:“Unix毫秒时间戳-同一毫秒值内的序列号”。 当用户显式指定ID时,最小值是0-1,且ID必须是递增的。...对于长度为0的stream,Redis不会删除,因为可能存在关联的消费者组。...时间复杂度:O(N),N是返回的元素数量 用法:XRANGE key start end [COUNT count] 该命令用于返回stream中指定ID范围的数据,可以使用-和+表示最小和最大ID。...STREAMS项必须在最后,用于指定stream和ID。 XREADGROUP 最早可用版本:5.0.0 时间复杂度:O(log(N)+M) ,N是返回的元素数量,M是一个常量。
如果你在以前面试的时候还没有遇到过面试官问你:为什么说Redis是单线程或者Redis为什么这么快?,那么你看到这篇文章的时候,你应该觉得是一件很幸运的事情!...我们先探讨一下Redis是什么,Redis为什么这么快、然后在探讨一下为什么Redis是单线程的?...二、Redis简介 Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间件。...五、那么为什么Redis是单线程的 我们首先要明白,上边的种种分析,都是为了营造一个Redis很快的氛围!...ps命令的“-T”参数表示显示线程(Show threads, possibly with SPID column.)“SID”栏表示线程ID,而“CMD”栏则显示了线程名称。
如果你在以前面试的时候还没有遇到过面试官问你:为什么说Redis是单线程或者Redis为什么这么快?,那么你看到这篇文章的时候,你应该觉得是一件很幸运的事情!...我们先探讨一下Redis是什么,Redis为什么这么快、然后在探讨一下为什么Redis是单线程的? ?...一、Redis简介 Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间件。...四、那么为什么Redis是单线程的 我们首先要明白,上边的种种分析,都是为了营造一个Redis很快的氛围!...ps命令的“-T”参数表示显示线程(Show threads, possibly with SPID column.)“SID”栏表示线程ID,而“CMD”栏则显示了线程名称。
在Redis5之前版本存在如下两个关键问题: (1)Redis的PubSub消息不会持久化,Redis宕机后消息就会被抛弃。 (2)Redis的消息队列没有太多高级特性,没有ack保证,可靠性不高。...三、总结 由于Redis5.9开始引入了Stream,Stream借鉴了Kafka的设计,加入了ack以及PEL以及高可用机制来避免消息丢失。 具体参见《Redis深度历险》Stream部分章节。...其中Stream的高可用章节提到: "鉴于Redis的指令复制是异步的,在failover发生时,Redis可能会丢失极小部分数据,这一点Redis的其他数据结构也是一样。"...总之消息队列这一块安全性和可用性提升很大。 但是如果延时队列还是用的是之前的PubSub,风险依然很大。...四、附录 介绍Stream的参考文章 https://redis.io/topics/streams-intro http://xiaorui.cc/2018/06/07/%E6%B5%85%E5%85%
) Redis 5.0 之前,实现消息队列的两种方案: 方案一:List实现 方案二:发布订阅(Pub/Sub) Redis 5.0 后: Redis Steam 是redis 5.0 新增的一种数据结构...Redis Stram可以用来实现消息队列,它支持消息的持久化、支持自动生成全局唯一ID、支持ack确认消息的模式、支持消费组模式等,让消息队列更加稳定和可靠 Stream 结构: Stream本质是一个消息链表...[LIMIT count] MAXLEN : 允许的最大长度,超过就会对流进行截取 MINID : 允许的最小ID,从某个ID值开始,比这个ID值小的将会被抛弃 # 1681007772647-0作为最小...ID作为最后一个ID,当前Stream中不存在大于当前最大ID的消息,因此此时返回nil xread count 2 streams mystream $ # 0-0代表从最小的ID开始获取Stream...但是,不同消费组中的消费者可以消费同一条消息。 消费组的目的: 让组内多个消费者共同分担读取消息,所以,我们通常会让每个消费者读取部分消息,从而实现消息读取负载在多个消费者间是均衡分布的。
事实上Redis的数据类型一直都是二进制安全的,几乎每一种数据类型都是可以用来存储流的。那为什么Redis 5.0要引用Stream数据类型呢? 具体如何使用?...因此简单地说,流是Redis一种新的数据结构,不需要读取原有key的值,就可以在此key中添加新内容的数据类型。 Stream添加 Stream可以用更抽象的方式来记录数据,比如说日志。...添加新的数据 { "sensor-id": 1234, "temperature": 19.8 }, *代表服务器端生成一个新的EntryID 1518951480106-0 是代表这组数据的EntryID...0-2 foo bar 0-2 流是只增不减的,所以如果entryid值比之前的小,则会报错: > XADD somestream 0-1 foo bar (error) ERR The ID specified...流介绍 https://redis.io/topics/streams-intro Redis 5.0的主要改进: 1.新的Stream数据类型。
前言 redis 5 中有一个重大新特性:stream。 stream 是一个日志形式的存储结构,可以往里追加数据,每条数据都会生成一个时间戳ID,stream 也有便捷的读取数据的模型。...1531989605376-0 解析: mystream 是 stream的key * 所在位置的参数的含义是元素ID,* 表示由系统自动生成一个元素ID 添加的元素包含2个键值对,sensor-id..." STREAMS 后面的 mystream 指定的是目标 stream 的 key, 0 是指最小的ID,就是获取指定stream中的大于指定ID的元素, COUNT 指获取的数量 可以一起指定多个stream...ID、所有者、此条消息的闲置时间(毫秒)、此消息被传递的次数。...的消息给了Gates,3600 是指最小闲置时间,就是把指定消息中闲置时间大于3600的分配给Gates,注意Gates是全新的消费者,之前没有声明过,说明分配给新的消费者也是可以的。
不持久化消息: 如果 Redis 停机重启,PubSub 的消息是不会持久化的,毕竟 Redis 宕机就相当于一个消费者都没有,所有的消息都会被直接丢弃。...这些 ID 的格式看起来有一些奇怪,为什么要使用时间来当做 ID 的一部分呢? 一方面,我们要 满足 ID 自增 的属性,另一方面,也是为了 支持范围查找 的功能。...当然消息 ID 也可以由客户端自定义,但是形式必须是 "整数-整数",而且后面加入的消息的 ID 必须要大于前面的消息 ID。 消息内容 消息内容就是普通的键值对,形如 hash 结构的键值对。...不过此时 xreadgroup 的起始消息 ID 不能为参数 > ,而必须是任意有效的消息 ID,一般将参数设为 0-0,表示读取所有的 PEL 消息以及自 last_delivered_id 之后的新消息...不过如果您想以 最小延迟 实时处理消息的话,您可以考虑 Redis,但是如果 消息很大并且应该重用数据 的话,则应该首先考虑使用 Kafka。
简介 Redis是一个高性能的键值存储系统,支持多种数据结构和丰富的功能。其中,发布/订阅模式是Redis的一个重要特性,它可以实现实时消息传递,广泛应用于聊天室、实时数据更新等场景。...在Redis中,频道是一个字符串,可以使用subscribe命令订阅一个或多个频道,使用publish命令向指定频道发布消息。当有消息发布到某个频道时,所有订阅该频道的客户端都会收到该消息。...例如,取消订阅名为news和weather的两个频道: unsubscribe news weather 实现原理 Redis的发布/订阅模式是基于消息通知机制实现的。...在Redis中,每个客户端都有一个独立的消息队列,用于存储订阅的频道中发布的消息。...总结 Redis的发布/订阅模式是一种高效的实时消息传递机制,可以广泛应用于聊天室、实时数据更新等场景。
Redis Stream的结构如上图所示,它有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的ID和对应的内容。消息是持久化的,Redis重启后,内容还在。...消息ID 消息ID的形式是timestampInMillis-sequence,例如1527846880572-5,它表示当前的消息在毫米时间戳1527846880572时产生,并且是该毫秒内产生的第5...消息ID可以由服务器自动生成,也可以由客户端自己指定,但是形式必须是整数-整数,而且必须是后面加入的消息的ID要大于前面的消息ID。...不过此时xreadgroup的起始消息ID不能为参数>,而必须是任意有效的消息ID,一般将参数设为0-0,表示读取所有的PEL消息以及自last_delivered_id之后的新消息。...如果读者稍微研究过Redis作者的另一个开源项目Disque的话,这极可能是作者意识到Disque项目的活跃程度不够,所以将Disque的内容移植到了Redis里面。
领取专属 10元无门槛券
手把手带您无忧上云