Redis的List数据类型作为消息队列,已经比较合适了,但存在一些不足,比如只能独立消费,订阅发布又无法支持数据的持久化,相对前两者,Redis Stream作为消息队列的使用更为有优势。
 
相信球迷小伙伴们对文字直播这个东西都不陌生,时常在想,这个功能是怎么实现的?
具体说就是用什么技术实现最为合适?如何面对数以百万计的读压力?广告消息是如何插播进来的?最后的历史消息如何归档,如何持久化存储?
文字直播其实就是解说员作为生产者,生产消息(文字信息),各种客户端作为消费者,消费信息(刷新文字内容)。
典型的消息队列实现,可以用队列或者类似队列的功能实现,这里只是简单想象一下,结合redis中的stream数据类型,来学习stream作为消息队列的功能实现。
 
 
1,生成者:生产者队列的创建,与消息的增删改
1.1 创建并写入消息
  语法:xadd queue_name Id filed value(filed value)
     1,每一组消息需要一个唯一的Id,*号表示服务器自动生成ID,后面顺序跟着一组或者多组消息(filed value)
     2,消息ID的形式是timestampInMillis-sequence,例如1527846880572-5,它表示当前的消息在毫米时间戳1527846880572时产生,并且是该毫秒内产生的第5条消息。
           消息ID可以由服务器自动生成,也可以由客户端自己指定,但是形式必须是整数-整数,而且必须是后面加入的消息的ID要大于前面的消息ID。
     3,消息元素的的结构为key-value,必须成对出现,如果key或者value元素中有空格,必须用"abc  def"或者'abc  def'括起来
 
1.2 生产者写入消息
  语法:xadd queue_name *|Id filed value    
 
1.3 xlen 当前stream的长度:xlen stream_name
  xlen "NBA_Match_001" ,也就是上面写入的10条消息
    
1.4 限制某一个stream的最大长度,maxlen 
  依据先进先出的原则,自动删除超出最长长度的消息
  xadd "NBA_Match_001" maxlen 50000 * "2019-07-13 08:26:39" "反击哈腾,一条龙上篮得分"
  
1.5 查询消息(查询是生产者查询自己生产的消息,跟消费者的消费是两码事)

正向查询
xrange "NBA_Match_001"              # 查询所有消息
xrange "NBA_Match_001" - +              # -表示最小值, +表示最大值
xrange "NBA_Match_001" 1562980142175-0 +    # 指定最小消息ID的列表
xrange "NBA_Match_001"- 1562980142175-0      # 指定最大消息ID的列表
反向查询
xrevrange "NBA_Match_001"
xrevrange "NBA_Match_001" + -
xrevrange "NBA_Match_001" + 1562980142175-0
xrevrange "NBA_Match_001" 1562980142175-0 -

1.6 删除消息
  xdel stream_name id,删除消息并不是真正的物理删除,队列的长度不变,指示标记当前消息被删除

1.7 查看stream属性xinfo stream stream_name 
1.8 del stream_name
删除 stream :del NBA_Match_001
删除本质上本Redis中的其他数据类型一致,stream本身就是一个key值,del key值就删除了整个消息的全部信息。
 
 
2 xread:独立消费
类似于List,生产者往list中写数据,消费者从list中读数据,只能有一个消费者
 
2. 1,从头部读取消息,从某个streams中读取n条消息,0-0只从头开始,或者指定从streams的Id开始
  xread count 1 streams "NBA_Match_001" 0-0
  xread count 1 streams "NBA_Match_001" 1562980142175-0
  
2.2,从尾部读取最新的一条消息
xread count 1 streams "NBA_Match_001" $
此时默认不返回任何消息
xread  block 0 count 1 streams "NBA_Match_001" $
以阻塞的方式读取尾部最新的一条消息,直到新的消息的到来

  

 
3 多消费者xgroup :消费组,每个组中的消费者独立消费stream中的消息
典型的比如文字直播的安卓App客户端,苹果App客户端,网页客户端等等。多个终端,都可以独立地消费队列里面的

3.1 创建消费组

对消息队列"NBA_Match_001"创建了两个消费组,一个是cg1,一个是cg2,比如网页客户端与App客户端

1,xgroup create "NBA_Match_001" cg1 0-0  #  表示从头开始消费

创建消费组cg1,消费组必须绑定一个steam(NBA_Match_001),从头(0-0 )开始消费"NBA_Match_001"中的消息
2,xgroup create "NBA_Match_001" cg2 0-0  #  表示从头开始消费
3,2 从消费组中创建消费者
xreadgroup指令可以进行消费组的组内消费
xreadgroup GROUP cg1 c1 count 1 streams "NBA_Match_001" >
>号表示从当前消费组的last_delivered_id后面开始读 , 每当消费者读取一条消息,last_delivered_id变量就会前进 
当一个组的消费则消费完全部消息之后,就没有新的消息了
 

每个消费组(Consumer Group)的状态都是独立的,相互不受影响。也就是说同一份Stream内部的消息会被每个消费组都消费到。
同一个消费组(Consumer Group)可以挂接多个消费者(Consumer),这些消费者之间是竞争关系,任意一个消费者读取了消息都会使游标last_delivered_id往前移动。
每个消费者者有一个组内唯一名称。

关于消费组,可能不太好理解,举个例子就比较清楚
假设有2个消费组cg1,cg2,对于cg1,其组内共有3个消费者c1,、c2、c3。一个消息队列中共有5条消息a,b,c,d,e,那么一种可能的消费方式如下
a -> c1
b -> c2
c -> c3
d -> c1
e -> c2
也就是说3个消费者,对于消息的消费是互斥的,消费的消息是没有交集的
而对于cg2,同样可以消费a,b,c,d,e这5条消息,不依赖于cg1消费组以及消费情况,同理,具体怎么消费,取决于其组内的消费者数量
就好比体育直播的客户端,正常情况下,网页客户端可以收到所有的直播消息,手机App客户端也可以收到所有的直播消息一样,不同消费组间对消息的消费互不干扰。

4 多个生产者和多个消费者

  这种情况类似以上,不用的是增加了多个消费者,在上面的基础上做了扩展。
  其实不难想象,文字直播插播的广告消息,可能是类似如下结构,是另外一个独立的生产者,与文字直播员一样生成写入消息到队列,然后客户端看到的就是夹杂了广告的直播。

目前就个人认识而言,stream数据类型实现消息队列并不完美,最大的问题就是单点压力问题:这里是说单点压力,而不是单点故障,stream类型数据,其实从逻辑上看,是一个key值(stream_name),跟着一系列value(消息),这些消息只能存储在一个Redis实例中,如何缓解多个消费者对单个Key值中的消息消费压力?说来说去,不就是想说kafka的partition么……

参考:

http://database.51cto.com/art/201812/588189.htm

https://www.zhihu.com/question/279540635

Redis中的Stream数据类型作为消息队列的尝试的更多相关文章

  1. 手把手教你用redis实现一个简单的mq消息队列(java)

    众所周知,消息队列是应用系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构.目前使用较多的消息队列有 ActiveMQ,RabbitMQ,Zero ...

  2. 面试官:Redis中哈希数据类型的内部实现方式是什么?

    面试官:Redis中基本的数据类型有哪些? 我:Redis的基本数据类型有:字符串(string).哈希(hash).列表(list).集合(set).有序集合(zset). 面试官:哈希数据类型的内 ...

  3. 使用Redis Stream来做消息队列和在Asp.Net Core中的实现

    写在前面 我一直以来使用redis的时候,很多低烈度需求(并发要求不是很高)需要用到消息队列的时候,在项目本身已经使用了Redis的情况下都想直接用Redis来做消息队列,而不想引入新的服务,kafk ...

  4. redis k-v数据库、高速缓存、消息队列代理

    Redis 简介   Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库. Redis 与其他 key - value 缓存产品有以下三个特点: Redis支持数据的 ...

  5. Redis 中的高级数据类型

    5个基础数据类型 高级功能 ① HyperLogLog (参考) 供不精确的去重计数功能,比较适合用来做大规模数据的去重统计,例如统计 UV > PFADD visitors alice bob ...

  6. Redis系列(五):消息队列

    消息队列已经成为现在互联网服务端的标配组件,现在比较常用的消息中间件有RabbitMQ.Kafka.RocketMQ.ActiveMQ.说出来你可能不信,Redis作为一个缓存中间件,居然也提供了消息 ...

  7. Redis 竟然能用 List 实现消息队列

    分布式系统中必备的一个中间件就是消息队列,通过消息队列我们能对服务间进行异步解耦.流量消峰.实现最终一致性. 目前市面上已经有 RabbitMQ.RochetMQ.ActiveMQ.Kafka等,有人 ...

  8. Redis中的简单事物以及消息订阅发布

    Redis支持简单的事物,但是没有mysql的Innodb支持的那么的完善 我们接下来看一下Redis和Mysql的事物的一个对比:   MySQL Redis 开启 start transactio ...

  9. php中对共享内存,消息队列的操作

    http://www.cnblogs.com/fengwei/archive/2012/09/12/2682646.html php作为脚本程序,通常生命周期都很短,如在web应用中,一次请求就是ph ...

随机推荐

  1. dom写法和jquery写法

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  2. 通通WPF随笔(2)——自己制作轻量级asp.net网站服务

    原文:通通WPF随笔(2)--自己制作轻量级asp.net网站服务 大学玩asp.net时就发现VS在Debug时会起一个web服务,这东西也太神奇了服务起得这么快,而相对于IIS又这么渺小. 前几个 ...

  3. miniui处理多重子表级联,一次性提交多表数据的ui要点

    在一个ui界面上 有a,b,c三个表 a表只有一条记录,b表有多条记录,c表有多条记录 b是a的子表,c是b的子表 都是一对多关系 一次性下载相关联的c表记录 然后mini-datagrid采用cli ...

  4. C#数字图像处理时注意图像的未用区域

    原文:C#数字图像处理时注意图像的未用区域 图1. 被锁定图像像素数组基本布局         如图1所示,数组的宽度并不一定等于图像像素数组的宽度,还有一部分未用区域.这是为了提高效率,系统要确定每 ...

  5. UWP 浏览本地图片及对图片的裁剪

    原文:UWP 浏览本地图片及对图片的裁剪 1.前言 准备给我的校园助手客户端添加一个修改头像的功能,但是查了好多资料都没有找到裁剪图片的简单的方法,最后才找到这个使用Launcher调用系统组件的简单 ...

  6. WPF获取和设置应用程序范围的资源

    设置资源: Application.Current.Resources["ApplicationScopeResource"] = Brushes.White; 使用代码获取资源: ...

  7. 如何线程调用C++类成员函数

    方法就是: 1,写成静态成员函数 2,参数为 (void* __this)用来传入类 对象指针(this) 3,进入函数首先    C类名 *_this = (C类名*)__this;  转化为对象指 ...

  8. memcached对中文key的支持问题

    默认的memcached客户端对非ANSI的key存取时会有问题,有2种方式解决: 1 在get和set前将缓存的key进行UrlEncode 2 修改memcached.config文件 <e ...

  9. -bash: /root/java/jdk/bin/java: cannot execute binary file

    错误 -bash: /root/java/jdk/bin/java: cannot execute binary file 错误原因 安装的Linux的版本是32位的,下载的软件是64位,版本不兼容, ...

  10. Setting up multi nodes live migration in Openstack Juno with devstack

    Setting up multi nodes live migration in Openstack Juno with devstack Summary Live migration overvie ...