Redis 作为一个高性能的内存数据库,支持多种实现消息队列的方式,主要包括:
不同的方式适用于不同的场景,下面详细讲解各自的实现原理、适用场景以及示例代码。
Redis 的 List
结构(链表)可以用来实现 任务队列,支持持久化存储,并允许消费者从队列中取出任务进行处理。
LPUSH queue_name message
:将新任务加入队列 头部。RPUSH queue_name message
:将新任务加入队列 尾部。LPOP queue_name
/ RPOP queue_name
:从队列头部/尾部取出任务(非阻塞)。BRPOP queue_name timeout
:阻塞方式获取任务,如果队列为空,会等待新的任务到来。import redis
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
# 添加任务到队列
r.lpush('task_queue', 'task1')
r.lpush('task_queue', 'task2')
print("Tasks added!")
import redis
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
while True:
task = r.brpop('task_queue', timeout=0) # 阻塞模式
if task:
print(f"Processing task: {task[1]}")
RPOPLPUSH
实现任务持久化:task = r.rpoplpush('task_queue', 'processing_queue')
if task:
process(task)
r.lrem('processing_queue', 1, task) # 任务完成后删除
Redis Pub/Sub
适用于实时广播通知,但不支持消息存储。
PUBLISH channel message
:发布消息到频道。SUBSCRIBE channel
:订阅者监听频道消息。import redis
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
r.publish('news_channel', 'Breaking News: Redis is awesome!')
import redis
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
pubsub = r.pubsub()
pubsub.subscribe('news_channel')
for message in pubsub.listen():
if message['type'] == 'message':
print(f"Received message: {message['data']}")
Redis Stream 是一种高效、持久化的消息队列,支持消息存储、消费分组等特性,类似 Kafka。
XADD stream_name * field1 value1 field2 value2
:添加消息。XREAD COUNT 1 STREAMS stream_name last_id
:读取消息。XGROUP CREATE stream_name group_name $ MKSTREAM
:创建消费组。import redis
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
r.xadd('event_stream', {'event': 'user_signup', 'user_id': '12345'})
print("Event published!")
import redis
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
while True:
events = r.xread({'event_stream': '$'}, count=1, block=5000)
for stream, messages in events:
for message_id, message in messages:
print(f"Received: {message}")
Sorted Set(有序集合)可以用于定时任务调度。
import time
import redis
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
r.zadd('delay_queue', {'task1': time.time() + 10}) # 10秒后执行
import time
import redis
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
while True:
now = time.time()
tasks = r.zrangebyscore('delay_queue', 0, now)
for task in tasks:
print(f"Processing {task}")
r.zrem('delay_queue', task)
time.sleep(1)
方案 | 持久化 | 支持多消费者 | 适用场景 |
---|---|---|---|
List | ✅ | 竞争消费 | 任务队列、异步任务 |
Pub/Sub | ❌ | 广播消费 | 实时推送、通知 |
Stream | ✅ | 组消费 | 事件流、日志收集 |
Sorted Set | ✅ | 竞争消费 | 延迟任务 |
List
(支持竞争消费,适合任务调度)。Pub/Sub
(广播消息,不存储)。Stream
(类似 Kafka,支持回放)。Sorted Set
(适合延迟队列)。