关闭

使用 Redis 构建先进先出队列解决秒杀问题

时间: 2019-07-25阅读: 2339标签: redis

本文摘录自即将出版的《Redis使用手册》, 详情请见: RedisGuide.com 。

先进先出队列(first in first out queue)是一种非常常见的数据结构, 一般都会包含入队(enqueue)和出队(dequeue)这两个操作, 其中入队操作会将一个元素放入到队列中, 而出队操作则会从队列中移除最先被入队的元素。

先进先出队列的应用非常广泛, 它见诸于各式各样的应用程序当中。 举个例子, 很多电商网站都会在节日时推出一些秒杀活动, 这些活动会放出数量有限的商品供用户抢购, 秒杀系统的一个特点就是在短时间内会有大量用户同时进行相同的购买操作, 如果使用事务或者锁去实现秒杀程序, 那么就会因为锁和事务的重试特性而导致性能低下, 并且由于重试的存在, 成功购买商品的用户可能并不是最早执行购买操作的用户, 因此这种秒杀系统实际上是不公平的。

解决上述问题的其中一个方法就是把用户的购买操作都放入到先进先出队列里面, 然后以队列方式处理用户的购买操作, 这样程序就可以在不使用锁或者事务的情况下实现秒杀系统, 并且得益于先进先出队列的特性, 这种秒杀系统可以按照用户执行购买操作的顺序来判断哪些用户可以成功执行购买操作, 因此它是公平的。

使用列表实现的先进先出队列:/list/fifo_queue.py

class FIFOqueue:

    def __init__(self, client, key):
        self.client = client
        self.key = key

    def enqueue(self, item):
        """
        将给定元素放入队列,然后返回队列当前包含的元素数量作为结果。
        """
        return self.client.rpush(self.key, item)

    def dequeue(self):
        """
        移除并返回队列目前入队时间最长的元素。
        """
        return self.client.lpop(self.key)

作为例子, 我们可以通过执行以下代码, 载入并创建一个先进先出队列:

>>> from redis import Redis
>>> from fifo_queue import FIFOqueue
>>> client = Redis(decode_responses=True)
>>> q = FIFOqueue(client, "buy-request")

然后通过执行以下代码, 将三个用户的购买请求依次放入到队列里面:

>>> q.enqueue("peter-buy-milk")
1
>>> q.enqueue("john-buy-rice")
2
>>> q.enqueue("david-buy-keyboard")
3

最后, 按照先进先出顺序, 依次从队列中弹出相应的购买请求:

>>> q.dequeue()
'peter-buy-milk'
>>> q.dequeue()
'john-buy-rice'
>>> q.dequeue()
'david-buy-keyboard'

可以看到, 队列弹出元素的顺序跟元素入队时的顺序是完全相同的: 最先是 "peter-buy-milk" 元素, 接着是 "john-buy-rice" 元素, 最后是 "david-buy-keyboard" 元素。


站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/4944

关闭

Redis中设置了过期时间的Key,那么你还要知道些什么?

熟悉Redis的同学应该知道,Redis的每个Key都可以设置一个过期时间,当达到过期时间的时候,这个key就会被自动删除。这就是Redis的过期策略。在为key设置过期时间需要注意的事项

PHP使用redis防止大并发下二次写入

php调用redis进去读写操作,大并发下会出现:读取key1,没有内容则写入内容,但是大并发下会出现同时多个php进程写入的情况,这个时候需要加一个锁,即获取锁的php进程有权限写。

Redis的主从复制

Redis配置成主从模式,主库(Master)只负责写数据,从库(Slave)只负责读数据。一个主库可以拥有多个从库,但一个从库只能隶属于一个主库。

Redis的基本数据结构及基本命令详解

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)

docker搭建redis集群

从docker库获取ruby镜像;创建虚拟网卡;查看网卡信息;查看redis-net虚拟网卡网关ip;创建需要挂载的目录以及文件;在/docker/redis目录下创建一个sh脚本文件;执行脚本创建挂载目录以及配置文件

node怎么用redis怎么做消息队列?

MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。

Redis使用10个小技巧

Redis 在当前的技术社区里是非常热门的。从来自 Antirez 一个小小的个人项目到成为内存数据存储行业的标准,Redis已经走过了很长的一段路。随之而来的一系列最佳实践,使得大多数人可以正确地使用 Redis

Redis常用命令

连接操作命令,持久化,远程服务控制,对value操作的命令,String,List,Set,Hash,Redis 发布订阅命令,Redis 事务命令,查看keys个数,清空数据库

我眼中的 Redis

本来对这个Redis没什么兴趣的,不就是一个缓存的数据库而已吗?直到上次配置spring-redis的时候,发现这个东西没有用户名。配置如上所示,只有主机、端口和密码

Redis在Php项目中的实际应用场景

Redis在Php项目中的实际应用场景:商品维度计数、用户维度计数、存储社交关系、用作缓存代替memcached、反spam系统、用户Timeline/Feeds、最新列表&排行榜、消息通知、将Redis用作消息队列

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!