• Redis 实现安全队列


    原创 2015-12-24 杜亦舒 性能与架构 Redis 实现安全队列

    Redis的列表数据结构可以让我们方便的实现消息队列


    例如用 LPUSH(BLPUSH)把消息入队,用 RPOP(BRPOP)获取消息


    绝大部分的情况下,这些操作都是没问题的,但并不能保证绝对安全


    当 LPOP 返回一个元素给客户端的时候,会从 list 中把该元素移除,这意味着该元素就只存在于客户端的上下文中,如果客户端在处理这个返回元素的过程崩溃了,那么这个元素就永远丢失了


    如何解决?


    redis 有一个 RPOPLPUSH (或者其阻塞版本的 BRPOPLPUSH)命令


    命令格式


    RPOPLPUSH source destination 


    原子性地返回并移除 source 列表的最后一个元素, 并把该元素放入 destination 列表的头部


    用这个命令可以保证队列的安全问题:


    使用 RPOPLPUSH 获取消息时,RPOPLPUSH 会把消息返给客户端,同时把该消息放入一个备份消息列表,并且这个过程是原子的,可以保证消息的安全,当客户端成功的处理了消息后,就可以把此消息从备份列表中移除了


    命令的阻塞与非阻塞区别


    redis的命令中,很多都提供了阻塞与非阻塞两个方式


    例如 LPUSH 为非阻塞,BLPUSH 为阻塞方式


    他们的区别是什么?


    唯一的区别是当列表中没有元素时,BRPOP命令会一直阻塞住连接,直到有新元素加入,而RPOP会直接返回nil


    实际应用的区别


    需要从队列获取任务


    如果用非阻塞的方式,代码会是这样


    # 无限循环读取任务队列中的内容 

    loop 

    $task = RPOR queue 

    if $task 

    # 如果有任务则执行 

    execute($task) 

    else 

    # 如果没有就等待1秒

    wait 1 second 


    当队列中没有任务时,每秒都会调用一次RPOP命令查看是否有新任务,可能会白白浪费很多系统资源,如果在有新任务加入队列时就通知消费者就好了,这个需求就可以使用阻塞式命令来实现


    loop 

    # 如果队列中没有任务,BRPOP命令会一直阻塞

    # 0 表示一直等待,永不过期 

    $task = BRPOP queue, 0 

    # 有返回值就继续执行 

    execute($task[1])

  • 相关阅读:
    第五周进度条
    《掌握需求过程》阅读笔记01
    第三周进度条
    问题账户需求分析
    2016年秋季阅读个人计划
    梦断代码阅读笔记03
    软件工程概论课程总结
    Python爬取上交所一年大盘数据
    Python爬取6271家死亡公司数据,看十年创业公司消亡史
    python:王思聪究竟上了多少次热搜?
  • 原文地址:https://www.cnblogs.com/xmanblue/p/6497403.html
Copyright © 2020-2023  润新知