Flask+Redis+mq實現高並發


Flask單機測試,實現redis+MQ秒殺業務,防止超限

簡單描述

搶購,秒殺是商場業務很常見的應用場景,主要需求解決:

1.高並發

2.如何解決庫存的正確減少("超賣"的問題)

redis 命令說明exists >setnx> incrby

# (1) 設置一些參數
    # 限制商品庫存總數
    amount_limit = 1000
    # 設置redis中的緩存key name
    keyname = 'limit'
    # incrby 每次自動增加的數量我們設置為1
    incr_amount = 1
    # (2)判斷redis中是否有我們的key name 也就是庫存商品的建
    通過r.exists()
  

  # 測試我們設置庫存量初始值為0
  # setnx >>>可以防止並發時多次設置key 
  r.setnx(keyname, 0)  # 初始值0
  # 判斷自增加數和庫存數
  incr_num = r.incrby(keyname, incr_amount)

 測試代碼

from flask import Flask
import logging
from logging import handlers
import redis

# 添加日志

rf_handler = handlers.TimedRotatingFileHandler(
    'redis.log', when='midnight', interval=1,
    backupCount=7)
rf_handler.setFormatter(
    logging.Formatter(
        "%(asctime)s %(filename)s line:%(lineno)d [%(levelname)s] %(message)s")
)

logging.getLogger().setLevel(logging.INFO)
logging.getLogger().addHandler(rf_handler)

app = Flask(__name__)

# 鏈接我們的redis connect redis
pool = redis.ConnectionPool(host='localhost', port=6379,
                            decode_responses=True)
r = redis.Redis(connection_pool=pool)


# 操作方法 進行商品庫存的讀取
# redis.get(store_shop)
# 為了簡單的演練 我們自己自定義參數

def limit_handler():
    """
    :return True:允許 ;False:拒絕

    """
    # (1) 設置一些參數
    # 限制商品庫存總數
    amount_limit = 1000
    # 設置redis中的緩存key name
    keyname = 'limit'
    # incrby 每次自動增加的數量我們設置為1
    incr_amount = 1
    # (2)判斷redis中是否有我們的key name 也就是庫存商品的建

    if not r.exists(keyname):
        """
        # 測試我們設置庫存量初始值為0
        # setnx >>>可以防止並發時多次設置key  

        """
        r.setnx(keyname, 0)  # 初始值0

        # 數據插入redis 后進行判斷是否大於限制數
    # 判斷自增加數和庫存數
    incr_num = r.incrby(keyname, incr_amount)

    if incr_num <= amount_limit:


        """
        再次將商品的信息進行緩存到redis中:user_id order_id price
        創建商品訂單號
        def post(self, request, *args, **kwargs):
        # 1)獲取前台信息:商品、價格、支付方式
        request_data = request.data
        subject = request_data.get('subject')
        total_amount = request_data.get('total_amount')
        pay_type = request_data.get('pay_type')
        if not (subject and total_amount and pay_type):
            return APIResponse(2, '數據有誤')
        # 2)生成訂單(訂單號,訂單表的訂單記錄)
        out_trade_no = str(time.time())
         try:
            user_obj = models.Order.objects.create(subject=subject, total_amount=total_amount, pay_type=pay_type,
                                        out_trade_no=out_trade_no, user=user)
            print(user_obj,'order999')
         except:
            return APIResponse(1, '訂單生成失敗')
        # 3)生成支付鏈接,並返回
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=out_trade_no,
            total_amount=total_amount,
            subject=subject,
            return_url=settings.RETURN_URL,
            notify_url=settings.NOTIFY_URL
        )
        order_url = pay_url + order_string
        return APIResponse(order_url=order_url)
        """
        # out_trade_no
        # 條件有限
        import time
        out_trade_no = str(time.time())
        return True  # 正常是生成訂單 >>>保存商品信息>>>調用alipay進行頁面的跳轉》》》MQ寫入隊列 進行數據的寫入
    return False


@app.route('/home')
def Login():
    return 'ok'


@app.route('/kill')
def hot():

    if limit_handler():

        logging.info("successful")
        return '提交訂單成功'
    else:
        logging.info("failed")

        return "商品已售完"


if __name__ == '__main__':
    app.run(debug=True)

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM