Redis-Python交互:流Stream

1、增删改查:

xadd(self, name, fields, id=’’, maxlen=None, approximate=True):追加消息 name:流的名字; fields:追加的消息key-value,字典表形式; id:表示由服务器自动生成id,也可以自己生成,但后面加入的消息的ID要大于前面的消息ID; maxlen:截断超出此大小的旧有的stream成员; approximate:实际流长度可能略大于maxlen,~ xdel(self, name, *ids):删除消息,这里的删除仅仅是设置了标志位,不影响消息总长度 xlen(self, name):Stream内消息的长度 xrange(self, name, min=’-’, max=’+’, count=None):获取消息列表,会自动过滤已经删除的消息

 if r.exists('stream_1'):
     r.delete('stream_1')
 message1 = {'name': 'Flask', 'price': 10}
 message1_id = r.xadd('stream_1', message1)
 message2 = {'name': 'Django', 'price': 15}
 message2_id = r.xadd('stream_1', message2)
 print(f"message1_id:{message1_id}\nmessage2_id: {message2_id}")
 # message1_id:b'1543370219288-0'
 # message2_id: b'1543370219288-1'
 print(f"stream len:{r.xlen('stream_1')}")
 # 2
 print(f"stream messages:{r.xrange('stream_1')}")
 #stream messages:[(b'1543370219288-0', {b'name': b'Flask', b'price': b'10'}), (b'1543370219288-1', {b'name': b'Django', b'price': b'15'})]
 r.xdel('stream_1', message1_id)
 print(f"stream messages:{r.xrange('stream_1')}")
 # stream messages:[(b'1543370219288-1', {b'name': b'Django', b'price': b'15'})]
 ​

2、独立消费

可以在不定义消费组的情况下进行Stream消息的独立消费,当Stream没有新消息时,甚至可以阻塞等待。

xread(self, streams, count=None, block=None): 字典表形式{流的名称:消息id},其中id时已被读取的最后一条消息的id。 streams: 要进行读取的流; count:读取的数据数量; block:阻塞的时间,毫秒;

 if r.exists('stream_2'):
     r.delete('stream_2')
 countrys = ['CN', 'US', 'UK', 'EU', 'JP']
 i = 0
 ret = []
 for country in countrys:
     ret.append(r.xadd('stream_2', {'country': country, 'id': i}))
 print(r.xread({'stream_2': ret[1], 'stream_1': 0}, 2))
 # [['stream_2', [(b'1543373133225-2', {b'country': b'UK', b'id': b'0'}), (b'1543373133226-0', {b'country': b'EU', b'id': b'0'})]], ['stream_1', [(b'1543373133224-1', {b'name': b'Django', b'price': b'15'})]]]
 ​
 # 0-0 从头开始
 print(r.xread({'stream_2': '0-0'}))
 # [['stream_2', [(b'1543373133225-0', {b'country': b'CN', b'id': b'0'}), (b'1543373133225-1', {b'country': b'US', b'id': b'0'}), (b'1543373133225-2', {b'country': b'UK', b'id': b'0'}), (b'1543373133226-0', {b'country': b'EU', b'id': b'0'}), (b'1543373133226-1', {b'country': b'JP', b'id': b'0'})]]]

阻塞模式

 # 从尾端读取数据, 阻塞时间60s
 print(r.xread({'stream_2': '$'}, block=1000 * 60))

等待60s后返回

 []

在阻塞的过程中,另一界面

 r.xadd('stream_2', {'name': 'jack', 'age': 11})

读取到stream_2尾部的消息:

 [['stream_2', [(b'1543373840860-0', {b'name': b'jack', b'age': b'11'})]]]

3、创建消费组

消费组消费模型:

xgroup_create(self, name, groupname, id=’$’, mkstream=False):在stream上创建新的消费组; name:stream的名字; groupname:消费组名称; id:起始消息ID,用来初始化last_delivered_id变量,默认$从尾部开始消费,只接受新消息,当前Stream消息会全部忽略; xgroup_destroy(self, name, groupname):删除消费组; xinfo_groups(self, name):stream的消费组信息; xinfo_stream(self, name):流的信息; if r.exists('stream_3'):

 if r.exists('stream_3'):
     r.delete('stream_3')
 r.xadd('stream_3', {'id': 0})
 r.xadd('stream_3', {'id': 1})
 # 从头部开始消费
 r.xgroup_create('stream_3', 'group_2', id=0)
 # 从尾部开始消费
 r.xgroup_create('stream_3', 'group_1', id="$")
 # 流的信息
 print(r.xinfo_stream('stream_3'))
 #{'length': 2, 'radix-tree-keys': 1, 'radix-tree-nodes': 2, 'groups': 2, 'last-generated-id': b'1543375608869-1', 'first-entry': (b'1543375608869-0', {b'id': b'0'}), 'last-entry': (b'1543375608869-1', {b'id': b'1'})}
 # 消费组信息
 print(r.xinfo_groups('stream_3'))
 # pending 待处理消息
 # [{'name': b'group_1', 'consumers': 0, 'pending': 0, 'last-delivered-id': b'1543375608869-1'}, {'name': b'group_2', 'consumers': 0, 'pending': 0, 'last-delivered-id': b'0-0'}]
 # 移除消费组
 r.xgroup_destroy('stream_3', 'group_2')
 print(r.xinfo_groups('stream_3'))
 # [{'name': b'group_1', 'consumers': 0, 'pending': 0, 'last-delivered-id': b'1543375608869-1'}]
 ​

4、消费

Stream提供了xreadgroup指令可以进行消费组的组内消费,需要提供消费组名称、消费者名称和起始消息ID。它同xread一样,也可以阻塞等待新消息。读到新消息后,对应的消息ID就会进入消费者的PEL(正在处理的消息)结构里,客户端处理完毕后使用xack指令通知服务器,本条消息已经处理完毕,该消息ID就会从PEL中移除。如果消费者收到了消息处理完了但是没有回复ack,就会导致PEL列表不断增长,如果有很多消费组的话,那么这个PEL占用的内存就会放大。

xgroup_delconsumer(self, name, groupname, consumername):从消费组移除特定消费者 xinfo_consumers(self, name, groupname):消费者信息; xreadgroup(self, groupname, consumername, streams, count=None, block=None):消费组的组内消费 xack(self, name, groupname, *ids): 正确处理消息后的响应 xpending(self, name, groupname):消费组内待处理的消息的信息

 if r.exists('stream_4'):
     r.delete('stream_4')
 r1 = r.xadd('stream_4', {'name': 'jack'})
 r2 = r.xadd('stream_4', {'name': 'Tom'})
 r3 = r.xadd('stream_4', {'name': 'Will'})
 r.xgroup_create('stream_4', 'group_1', id=0)
 # >号表示从当前消费组的last_delivered_id后面开始读
 # 每当消费者读取一条消息,last_delivered_id变量就会前进
 ret = r.xreadgroup('group_1', 'consumer_1', {'stream_4': ">"}, count=1)
 print(ret)
 # [['stream_4', [(b'1543455084777-0', {b'name': b'jack'})]]]
 r.xreadgroup('group_1', 'consumer_1', {'stream_4': ">"}, count=2)
 print(r.xinfo_consumers('stream_4', 'group_1'))
 # idle空闲了多长时间ms没有读取消息了
 # [{'name': b'consumer_1', 'pending': 3, 'idle': 1}]
 print(r.xpending('stream_4', 'group_1'))
 # {'pending': 3, 'min': b'1543455084777-0', 'max': b'1543455084777-2', 'consumers': [{'name': b'consumer_1', 'pending': 3}]}
 # ack 2条消息
 r.xack('stream_4', 'group_1', *[r1, r2])
 print(r.xinfo_consumers('stream_4', 'group_1'))
 # [{'name': b'consumer_1', 'pending': 1, 'idle': 1}] pending减少了
 ​

5、控制消息的长度

xadd 的maxlen参数可以将消息控制在一定长度,但要设置approximate=False; xtrim(self, name, maxlen, approximate=True):同样可以将stream内的消息修剪为指定长度

 if r.exists('stream_5'):
     r.delete('stream_5')
 for i in range(0, 10):
     r.xadd('stream_5', {'id': i})
 print(r.xlen('stream_5'))
 # 10
 r.xadd('stream_5', {'id': 10}, maxlen=5, approximate=False)
 print(r.xlen('stream_5'))
 # 5
 r.xtrim('stream_5', maxlen=3, approximate=False)
 print(r.xlen('stream_5'))
 # 3
 print(r.xrange('stream_5'))
 # [(b'1543455600180-4', {b'id': b'8'}), (b'1543455600181-0', {b'id': b'9'}), (b'1543455600181-1', {b'id': b'10'})]
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值