Flask - 抢购、秒杀系统

本文分析了秒杀系统中的超卖和超抢问题,提出基于Redis的解决方案。通过Redis队列保证并发下的线程安全,结合Jmeter进行并发测试,确保系统的稳定性和性能。同时,介绍了如何利用Redis的原子性操作防止数据不一致,实现用户限购功能。
摘要由CSDN通过智能技术生成

目录

一、秒杀系统需求分析

1-1 超卖问题

1-2 超抢问题

二、基于 Redis 队列实现抢购

2-0 思路总结

2-1 初始版本

2-2 添加抢购量需求

三、Jmeter 并发测试工具

3-1 Jmeter 汉化

3-2 随机参数(函数)

3-3 响应编码问题(Unicode 转换)

四、基于 Redis 的计数器实现秒杀

4-0 Redis 的线程安全

4-1思路总结


 

一、秒杀系统需求分析

1-1 超卖问题

10个物品被20个用户抢到。

查询出对应商品的库存,看是否大于0,然后执行生成订单等操作,但是在判断库存是否大于0处,如果在高并发下就会有问题,导致库存量出现负数(线程安全)

解决思路:解决线程安全。

思路一、由于Redis 是单进程单线程,Redis 的所有基础命令都是原子性的,所以在单命令下线程安全。

php 实现参考

1-2 超抢问题

对于同一个物品,单用户能抢到多个。

解决思路:判断用户是否抢到,需要记录抢购用户

二、基于 Redis 队列实现抢购

使用redis队列,因为pop操作是原子的,即使有很多用户同时到达,也是依次执行。

mysql事务在高并发下性能下降很厉害,文件锁的方式也是

并发思路:celery 异步任务(优化高并发场景) + redis 队列

2-0 思路总结

  • key - value []
  • 假设:商品A限购5个,初始化list在redis内
    • 抢购商品A - [1,1,1,1,1]
  • 开始抢购则进行pop操作,每来一个用户先判断list的长度是否非0,若非0,pop一个,并将用户名写入另一个list
    • 抢购商品A - [1,1,1,1]
    • 商品A已抢用户 - [用户1,]
  • 若list(抢购商品A )已经pop空,则将返回用户失败信息。

2-1 初始版本

# ---------用于生成抢购库存列表-----------------
li = [1 for i in range(50)]
print(li)
re = conn.lpush('goods_a', *li)
print(re)

 

# API 接口,CBV
class Seckill(Resource):
    def post(self):
        # 获取form表单内的username,唯一参数
        username = request.form['username']
        # redis 内list存储数据为byte类型
        username = bytes(username, encoding='utf-8')

        # 获得当前redis内已购用户信息
        users_list = redis_store0.lrange('a_users', 0, -1)
        if username in users_list:
            return '您已经抢到了,请勿重复请求。'

        # 判断库存
        goods_count = redis_store0.llen('goods_a')
        if goods_count:
            res = redis_store0.lpop('goods_a')
            if res:
                redis_store0.lpush('a_users', username)
                return &
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值