Redis队列最佳实践

本文介绍了如何使用Redis创建简单的队列异步任务,包括生产消费者模式和订阅发布模式。通过Python示例展示了如何使用lpush和brpop进行任务分配,以及利用Redis的pub/sub功能实现任务分发。适合于不需等待处理结果的场景,如发送邮件、短信等。文章建议使用supervisord进行部署,并指出这种方案在实际运行中的稳定性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Redis队列简单应用-Python

@[redis|队列|异步任务|python]

大家通常会有这样需求,当我在一个web api中我想要去发送一个邮件,发送一个短信, 下发一个特别耗时的任务的时候,往往想到的是建一个celery吧,今天来说一下自己写一个简单redis队列异步任务worker。

Redis队列模式介绍

Redis的队列模式有两种应用:

1.生产消费模式:N个worker同时抢任务,适用于发邮件,发短信
2.订阅发布模式:N个worker同时都得到这个任务,适用于一个数据要存到多个地方去

生产消费者模式
这个用的是redis的 lpush 和 brpop 具体的逻辑看代码

worker端 (work.py):

import redis, json

r = redis.StrictRedis(host="localhost", port=6379, db=0)

def listen():
    while True:
        data = r.brpop("test:worker:push")
        run(json.loads(data[1]))

def run(data):
    print data

if __name__ == '__main__':
    listen()

client端 (client.py):

import redis, json

r = redis.StrictRedis(host="localhost", port=6379, db=0)

def send_task(num):
    task_data = json.dumps({            
        "name": "Jack",            
        "age": 16,            
        "num": num
    })
    r.lpush("test:worker:push", task_data)

if __name__ == '__main__':    
    for i in range(10):
        send_task(i)

执行 我启动了两个worker 然后client发送了10次任务, 输出如下:

worker1:
{u'age': 16, u'num': 0, u'name': u'Jack'}
{u'age': 16, u'num': 2, u'name': u'Jack'}
{u'age': 16, u'num': 3, u'name': u'Jack'}
{u'age': 16, u'num': 6, u'name': u'Jack'}
{u'age': 16, u'num': 8, u'name': u'Jack'}

worker2:
{u'age': 16, u'num': 1, u'name': u'Jack'}
{u'age': 16, u'num': 4, u'name': u'Jack'}
{u'age': 16, u'num': 5, u'name': u'Jack'}
{u'age': 16, u'num': 7, u'name': u'Jack'}
{u'age': 16, u'num': 9, u'name': u'Jack'}

发布订阅模式
这里使用的是Redis pub/sub 的功能

worker端 (worker.py):

# -*- coding: utf-8 -*-
# @Author: lxstar
# @Date:   2017-04-26 11:09:41
# @Last Modified by:   lxstar
# @Last Modified time: 2017-04-26 11:49:02

import redis, json

r = redis.StrictRedis(host="localhost", port=6379, db=0)
def listen():
    channel = "test:worker:pubsub"
    ps = r.pubsub()
    ps.subscribe(channel)    # 还可以订的多个频道 同时也能发布多个频道
    # ps.subscribe(["channel_1", "channel_2"])

    while True:        
        for item in ps.listen():            
            if item["channel"] == channel	            
                if item["type"] == "message":
                    run(json.loads(item["data"]))
                    
def run(data):
    print data

if __name__ == '__main__':
    listen()

client端 (client.py):

# -*- coding: utf-8 -*-
# @Author: lxstar
# @Date:   2017-04-26 11:11:25
# @Last Modified by:   lxstar
# @Last Modified time: 2017-04-26 11:33:09

import redis, json

r = redis.StrictRedis(host="localhost", port=6379, db=0)

def send_task(num):
    task_data = json.dumps({            
        "name": "Jack",            
        "age": 16,            
        "num": num
    })
    r.publish("test:worker:pubsub", task_data)

if __name__ == '__main__':    
    for i in range(3):
        send_task(i)

执行 我启动了两个worker 然后client发送了3次任务, 输出如下:

worker1:
{u'age': 16, u'num': 0, u'name': u'Jack'}
{u'age': 16, u'num': 1, u'name': u'Jack'}
{u'age': 16, u'num': 2, u'name': u'Jack'}

worker2:
{u'age': 16, u'num': 0, u'name': u'Jack'}
{u'age': 16, u'num': 1, u'name': u'Jack'}
{u'age': 16, u'num': 2, u'name': u'Jack'}

尾巴

有的时候,发送邮件之类的需求,其实并不需要去等待处理的结果如何,异步任务往往是最佳的选择。当你不想上celery之类的框架,或者你的事情特别简单的话,可以尝试这种方式去做这样一个简单的worker。

关于部署,推荐使用supervisord之类的工具,启动多个或者管理状态都是极好的。

关于稳定性,线上的推送/邮件/短信,都是基于这个在跑着,大半年了没出过状况,但只是我的场景实践,仅供参考。

如果你还需要知道执行的结果和监控任务执行的进度的话,想必celery是极好的。

更多干货内容,欢迎关注公众号:知了python

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值