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個商品。

 

發佈了92 篇原創文章 · 獲贊 2 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章