• flask+redis实现抢购(秒杀)功能


    今天面试了 一家非常高大上的公司,问了我关于redis的实用性问题,但是答的不是很好,所以下午通过再次学习 redis,实现相关实用性功能的一种。

    对于抢购功能,难点在于 抢购时 由于高并发请求,导致一个用户抢购多件商品,库存量小于订单量的情况。

    如下通过redis的hash和list类型实现相关功能。

    思路:

    hash:主要用来存储用户抢购成功的信息,因其自身的特性,如果hash的key,val重复,会返回0,从而判断一个用户只能抢购一个商品。

    list:主要用来存放商品,在每个请求进来时,从list中pop一个商品,这样做到针对redis(货物)做到单线程(无论并发多少个请求)。

    整体思路:利用hash的不可重复特性和list, 在请求进来时从list中pop一个商品,然后添加到hash中,如果添加失败,就再次push一个商品到list中。

    from flask import Flask, request
    from flask.views import MethodView
    
    app = Flask(__name__)
    REDIS_CONF = {
        'host': '127.0.0.1',
        'port': 6379,
        'db': 1
    }
    app.config.update({'REDIS_CONF': REDIS_CONF})
    
    from redis import StrictRedis
    import random
    
    REDIS = StrictRedis(**REDIS_CONF)
    
    
    class GetGoods(MethodView):
        def post(self):
            uid = random.randint(1, 10)
            if REDIS.lpop('goods_list'):
                if REDIS.hset('user_list', uid, 1):
                    print(f'Success,{uid}')
                    return f'Success,{uid}'
                else:
                    # 不可重复抢(每人限领一个)
                    print(f'push ,{uid}')
                    REDIS.lpush('goods_list', 1)
                    return f'create a user {uid}'
            else:
                # 已抢完
                print('Finsh!')
                return 'Finsh!'
    
        def get(self):
            user_list = REDIS.hgetall('user_list')
            user_list_len = REDIS.hlen('user_list')
            goods_list = REDIS.llen('goods_list')
            result_dict = {"user_list": user_list, "user_list_len": user_list_len, 'goods_list': goods_list}
            print(result_dict)
            return 'success!'
    
    
    class SendGoods(MethodView):
        def post(self):
            count = request.form.get('count')
            if REDIS.exists('goods_list'):
                print('delet exists goods')
                REDIS.delete('goods_list')
    
            for item in range(int(count)):
                REDIS.lpush('goods_list', 1)
            REDIS.delete('user_list')
            goods_list = REDIS.lrange('goods_list', 0, count)
            return f'send goods success! {goods_list}'
    
    
    # 用户抢购接口
    app.add_url_rule('/goods', view_func=GetGoods.as_view('goods'), methods=['POST'])
    # 商家查看商品抢购结果
    app.add_url_rule('/goods', view_func=GetGoods.as_view('get_goods'), methods=['GET'])
    # 商家发布商品
    app.add_url_rule('/send/goods', view_func=SendGoods.as_view('send_goods'), methods=['POST'])
    
    app.run(host='127.0.0.1', port=8000, threaded=10, debug=True)

    通过postman测试:

    先执行  商家发布商品 接口,发送100个商品。

    然后并发压力测试  商家查看商品抢购结果 接口。

    然后执行 商家查看商品抢购结果 接口得到如下结果:

    发布100个商品,只有10个人抢购1000此,结果做到了每人一个商品,剩下90个商品。

  • 相关阅读:
    JQuery[07]Dom操作
    系统钩子[02] 安装全局鼠标钩子
    [Java动态代理] 设计模式之代理模式
    对话框编程之模态对话框 [03]
    对话框编程之属性对话框 [05]
    [Java反射机制] 通过反射机制创建类的实例并调用其方法
    JQuery[06] 过滤器、相对选择器
    JQuery[04] 节点遍历
    JQuery[13] Ajax的简单应用
    JQuery[09] CSS样式操作/节点操作
  • 原文地址:https://www.cnblogs.com/rgcLOVEyaya/p/RGC_LOVE_YAYA_836days.html
Copyright © 2020-2023  润新知