zoukankan      html  css  js  c++  java
  • 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])

  • 相关阅读:
    POJ3258River Hopscotch(二分)
    POJ3273Monthly Expense(二分)
    POJ1002487-3279(map)
    HDU 3123 GCC
    POJ2031Building a Space Station
    POJ3096Surprising Strings(map)
    模板类
    POJ1265Area
    【ZZ】C 语言中的指针和内存泄漏 & 编写高效的C程序与C代码优化
    学习笔记之MySQL
  • 原文地址:https://www.cnblogs.com/xmanblue/p/6497403.html
Copyright © 2011-2022 走看看