为啥线程数不同,秒杀结果不同,好想知道这个具体原理啊.麻烦老师解答一下.具体看以下代码和截图

为啥线程数不同,秒杀结果不同,好想知道这个具体原理啊.麻烦老师解答一下.具体看以下代码和截图

import redis
import random
from concurrent.futures import ThreadPoolExecutor

# 模拟抢购
pool = redis.ConnectionPool(host='localhost', port=6379, password=123, db=0, max_connections=20)
con = redis.Redis(connection_pool=pool)
con_buy = redis.Redis(connection_pool=pool)
# Python 线程池
executor = ThreadPoolExecutor(200)


def get_user_id():
    """ 创建user id 的集合"""
    s = set()
    while True:
        if len(s) == 1000:
            break
        num = random.randint(100000, 999999)
        s.add(num)
    return s


def buy():
    """ 模拟购买场景 """
    try:
        pipline = con_buy.pipeline()
        if con_buy.exists('kill_flag') == 1:
            pipline.watch('kill_flag', 'kill_user')
            total = int(pipline.get('kill_total').decode('utf-8'))
            # print(total)
            num = int(pipline.get('kill_num').decode('utf-8'))
            # print(num)
            if num < total:
                pipline.multi()
                pipline.incr('kill_num')
                s = get_user_id()
                user_id = s.pop()
                pipline.rpush('kill_user', user_id)
                pipline.execute()
                print('第{0}个秒杀成功,总共有{1},还有{2}个'.format(num+1, total, total-num-1))
    # except Exception as e:
    #     print(e)
    finally:
        pipline.reset()


def main():
    try:
        con.delete('kill_total', 'kill_num', 'kill_flag', 'kill_user')
        con.set('kill_total', 50)
        con.set('kill_num', 0)
        con.set('kill_flag', 1)
        con.expire('kill_flag', 600)
        for i in range(1000):
            executor.submit(buy)
        print("秒杀结束")

    except Exception as e:
        print(e)
    # finally:
    #     # del con
    #     del con_buy


if __name__ == '__main__':
    main()

http://img1.sycdn.imooc.com//climg/5da32e0c09faae1413430672.jpg

http://img1.sycdn.imooc.com//climg/5da32e7309cd613713530684.jpg

http://img1.sycdn.imooc.com//climg/5da32ea1093e88c113660703.jpg


http://img1.sycdn.imooc.com//climg/5da32f4109815c8b13520657.jpg

http://img1.sycdn.imooc.com//climg/5da32f0d091ee0a613470665.jpg


我之前用200个线程总是抢不完, 换了线程总数,终于可以了,然后就测试了一下,发现,不同的线程数,结果截然不同.这是为啥呢??麻烦老师解答一下.以上的代码只是在线程数那里做了修改,其它地方都没改变.我的数据库也是和这个打印效果完全一样..

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

3回答
好帮手慕美 2019-10-14 12:01:37

同学,你好。

1、当线程中的事务修改了watch的数据后,本事务因为未能正常execute,所以事务中关于修改秒杀商品数量的操作不会被提交执行,因此不会造成秒杀商品数量的减少。

2、若每个线程执行的事务能够正常提交,即不会发生上述的情况。同学可以更换数据库多测试几次。

如果我的回答解决了您的疑惑,请采纳!祝学习愉快~~~~

  • 提问者 3三哥 #1
    好的,谢谢老师.我等会儿测试一下,您意思是数据库不一样,效果还不一样啊?
    2019-10-14 15:19:48
  • 好帮手慕美 回复 提问者 3三哥 #2
    同学,你好。不是说数据库不一样效果就不一样,多执行几次或更换数据库可能就不会发生上述的情况 ,即能够正常秒杀。祝学习愉快~~~~
    2019-10-14 16:40:46
  • 提问者 3三哥 回复 好帮手慕美 #3
    我已经更换数据库了,从db=0改了好几个,还是这样.还有就是我想知道为啥有这种区别出现.为啥会部分事务不能正常提交.
    2019-10-14 16:57:58
提问者 3三哥 2019-10-13 22:15:03

实测,1--20都可以成功抢完 ,然后貌似21到 292之间总会有剩余,293以上,好像都可以抢完.

提问者 3三哥 2019-10-13 22:11:56

太神奇了..我都惊讶了.

问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师