python 实现redis stream类型简单消息队列

class RedisStream(object):
    """
    redis 使用stream 数据结构  实现消息队列  
     使用消费者组模式  实现组内多个消息 分给多个不同的消费者消费
    """
    def __init__(self) -> None:
        self.response = {'code': 200, 'msg': '成功', 'data': None}
        self.conn = redis.StrictRedis(host='127.0.0.1', port=6379)
        self.stream_name = 'stream'
        self.group_name = 'group'
        self.consumer_name = 'consumer1'

    def xadd_info(self, data):
        """添加数据到队列 设置最大长度为2"""
        res = self.conn.xadd(self.stream_name, data, '*', maxlen=2)
        if not res:
            self.response['code'] = 500
            self.response['msg'] = '失败'
        return self.response
    
    def create_group(self):
        """创建消费者组,判断消费者组是否存在"""
        flag = self.check_consumer_group_exists()
        if flag:
            self.response['code'] = 201
            self.response['msg'] = '消费者组已存在'
            return self.response
        else:
            res = self.conn.xgroup_create(self.stream_name, self.group_name, 0)
            if not res:
                self.response['code'] = 500
                self.response['msg'] = '创建消费者组失败'
            return self.response
   
    def consumer(self):
        """消费消息 消费完成标记信息已完成
        '>' : 获取到目前为止,从未传递给其他消费者的消息,并且会更新last_delivered_id,通常都是传递这个参数
        """
        response = self.create_group()
        if response.get('code') == 500:
            return response
        while True:
            res = self.conn.xreadgroup(self.group_name, self.consumer_name, {self.stream_name: '>'}, count=1)
            if not res:
                self.response['code'] = 404
                self.response['msg'] = '当前没有可消费数据'
                return self.response
            for stream, data in res[0][1]:
                message_id = stream.decode('utf-8')
                message_data = dict()
                for key, val in data.items():
                    message_data[key.decode('utf-8')] = val.decode('utf-8')
                self.xack_stream(message_id)

    def xack_stream(self, id):
        """标记消息为已完成"""
        res = self.conn.xack(self.stream_name, self.group_name, id)
        if not res:
            self.response['code'] = 500
            self.response['msg'] = '记录消息处理完成失败'
        return self.response

    def check_consumer_group_exists(self):
        # 获取指定Stream的消费者组列表
        groups = self.conn.xinfo_groups(self.stream_name)
        for group in groups:
            if group['name'].decode('utf-8') == self.group_name:
                return True
        return False


if __name__ == "__main__":
    stream = RedisStream()
    # print(stream.xadd_info({'name': 'gjj', 'sex': 'nv'}))
    # print(stream.xadd_info({'name': 'yyy', 'sex': 'nan'}))
    print(stream.consumer())
<think>好的,用户想知道如何使用Redis Stream实现消息队列的最佳实践和示例代码。首先,我需要回顾一下Redis Stream的基本概念和命令。Redis StreamRedis 5.0引入的数据结构,适用于消息队列场景,支持多消费者组和消息持久化等特性。用户之前提供的引用内容提到了使用XREAD命令和消费者组,这应该是关键点。 接下来,我需要确定最佳实践的几个方面。首先是消息的生产和消费流程,如何添加消息到Stream,如何读取。然后要考虑消费者组的配置,确保消息的可靠传递,比如处理未确认的消息,避免消息丢失。另外,可能还需要考虑消息的持久化、错误处理以及性能优化。 示例代码部分,用户可能需要Python的示例,因为之前的引用中有Python代码。需要使用redis-py库,演示生产者和消费者的实现。要注意XADD命令的使用,指定Stream名称和字段键值对。消费者部分要展示如何创建消费者组,使用XREADGROUP读取消息,处理消息后确认。 还要注意,用户可能关心消息的可靠性,比如如何处理消费者失败后的消息重新投递。需要提到XACK命令来确认消息,以及检查未确认的消息,使用XPENDING命令。此外,消息队列的监控和管理也是最佳实践的一部分,比如监控Pending列表的长度,及时处理堆积。 可能需要提醒用户关于消费者组的初始化问题,确保在使用前创建消费者组,避免错误。另外,消息的格式设计也很重要,比如包含唯一ID和时间戳,方便追踪和调试。 最后,需要总结Redis Stream的优势,比如高吞吐量、持久化、消费者组支持,适用的场景如实时数据处理、任务队列等。同时,对比其他消息队列如RabbitMQ,指出Redis Stream的轻量级和与Redis其他功能的协同优势。 检查是否有遗漏的点,比如错误处理的具体示例,或者如何配置Redis实例的持久化策略以确保数据不丢失。可能需要简要提到AOF和RDB配置,但用户的问题更关注Stream的使用,所以可以保持重点在代码和实践上。 现在整理步骤,确保逻辑清晰,代码示例正确,并引用提供的参考资料,特别是引用[2]和[3]中提到的Redis Stream实现消息队列的内容。需要将引用标记自然地融入回答中,比如在提到消费者组或可靠消息队列时添加引用标识。</think>### Redis Stream实现消息队列的最佳实践 #### 核心特性 Redis Stream 是专为消息队列设计的持久化数据结构,支持: - 多消费者组协作模式 - 消息ID序列化控制(时间戳-序号) - 消息确认机制(XACK) - 消息回溯能力(XRANGE) #### 实现步骤 1. **生产者代码示例**(Python): ```python import redis def produce_message(stream_key, data): r = redis.Redis() return r.xadd(stream_key, data) # 发送示例消息 message_id = produce_message('order_stream', { 'user_id': '1001', 'product': 'RTX4090', 'quantity': 1 }) ``` 2. **消费者组初始化**: ```bash # 创建消费者组(需Redis 6.2+) XGROUP CREATE order_stream order_group $ MKSTREAM ``` 3. **消费者代码示例**: ```python def consume_messages(consumer_name): r = redis.Redis() while True: messages = r.xreadgroup( groupname='order_group', consumername=consumer_name, streams={'order_stream': '>'}, count=1, block=5000 ) if messages: process_message(messages[0][1][0]) def process_message(msg): try: print(f"处理消息: {msg}") r.xack('order_stream', 'order_group', msg[0]) except Exception as e: print(f"处理失败: {msg}, 错误: {e}") # 可添加重试逻辑 ``` #### 最佳实践 1. **消息可靠性保障**: - 使用`XAUTOCLAIM`自动转移未确认消息 - 设置合理的`MAXLEN`防止内存溢出:`XADD mystream MAXLEN ~ 1000 * field value` - 启用Redis持久化(AOF+RDB) 2. **消费者设计规范**: ```python # 检查未确认消息示例 pending = r.xpending('order_stream', 'order_group') if pending['pending'] > 100: handle_backlog(pending) ``` 3. **流量控制策略**: - 使用`BLOCK`参数实现长轮询 - 通过`COUNT`控制批量处理数量 - 结合CLIENT PAUSE实现背压控制 #### 应用场景 1. 电商订单处理流水线[^2] 2. IoT设备数据采集队列 3. 微服务间异步通信[^3] ```mermaid graph LR Producer-->|XADD|Stream Stream-->|XREADGROUP|Consumer1 Stream-->|XREADGROUP|Consumer2 Consumer1-->|XACK|Stream Consumer2-->|XACK|Stream ``` #### 性能优化技巧 1. 批量操作:使用`XRANGE/XREAD`批量获取消息 2. 内存管理:定期执行`XTRIM`维护Stream长度 3. 集群部署:分片键设计避免热键问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值