为什么我的程序秒杀数据怎么运行都只有6个人

为什么我的程序秒杀数据怎么运行都只有6个人

我尝试切换了线程数量和逻辑库,都是只有6个http://img1.sycdn.imooc.com//climg/5f69de0209a79b4615621895.jpg

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

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

2回答
好帮手慕小猿 2020-09-24 11:46:51

同学你好,
1、若注释con.delete(),数据库中的kill_user因是列表类型所以累加的

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

2、因不确定同学修改后的代码是否正确,如下是老师的代码,同学可以对比一下,user_id会出现少于50的情况,因是线程,哪个线程先执行完成也不确定,以下代码老师这边运行也是少于50的,另一位老师是50的

import redis
import random
from redis_db import pool
from concurrent.futures import ThreadPoolExecutor

# 用户id
s = set()
while True:
   if len(s) == 1000:
       break
   num = random.randint(10000, 100000)
   s.add(num)

con = redis.Redis(
   connection_pool=pool
)
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)
except Exception as e:
   print(e)
# finally:
#     del con

executor = ThreadPoolExecutor(200)


def buy():
   connection = redis.Redis(
       connection_pool=pool
   )
   pipline = connection.pipeline()
   try:

       # 如果抢购有效
      # if connection.exists("kill_flag") == 1:
           # 监视成功抢购数,成功抢购的ID

           pipline.watch("kill_num", "kill_user")
           # 商品总数
           total = int(pipline.get("kill_total").decode("utf-8"))

           print(total,"!!!!!!!!!")
           # 成功抢购数
           num = int(pipline.get("kill_num").decode("utf-8"))
           if num < total  :
               pipline.multi()
               pipline.incr("kill_num")
               user_id = s.pop()
               pipline.rpush("kill_user", user_id)
               pipline.execute()
   except Exception as e:
       print(e)
   finally:
       if "pipline" in dir():
           pipline.reset()
       del connection


for i in range(0, 1000):
   executor.submit(buy)

print("秒杀已经结束")

  • 提问者 反冲斗士 #1
    为什么因为不确定哪个线程先执行完所以就没有50呢,我是这样理解的:最后for循环1000次,是调用线程池里的线程1000次去执行buy函数,来模拟1000个人同时参与秒杀的活动,这活动设置了过期时间:600秒,但是这个进程从开始到结束也才10秒不到,不是应该在600秒内把秒杀名额全部都弄完吗。。。。(不过中途我复制了老师的代码在另一台电脑上新装了redis数据库,没有改配置文件,创建完连接池之后直接运行,能正常显示50个名额,可能是我代码哪里有问题,我回去再看看)
    2020-09-24 14:24:14
  • 好帮手慕小猿 回复 提问者 反冲斗士 #2
    同学可以这样理解 1、当其他事务修改了watch的数据后,本事务因为未能正常execute,所以事务中关于修改秒杀商品数量的操作不会被提交执行,因此不会造成秒杀商品数量的改变。 2、线程池的任务是并发执行的,当并发往数据库里写数据时,会出现数据存储不成功的情况。 祝学习愉快~
    2020-09-24 19:22:33
  • 提问者 反冲斗士 回复 好帮手慕小猿 #3
    我重新看了一下代码,那是不是这个秒杀,假设50个名额都抢到,因为我们用的是pop()弹出集合末尾最后一个,是不是就意味这个50个用户的id永远是随机生成的集合的最后50个
    2020-09-24 22:45:42
好帮手慕小猿 2020-09-23 09:31:17

同学你好,
1、运行代码,代码报错,同学没有创建pipeline,就直接调用
http://img1.sycdn.imooc.com//climg/5f6aa2af09930b2003790135.jpg
2、逻辑不对,先判段元祖中是否有1000个元素,如果有1000个元素就停止循环,同学的逻辑是先添加元素,然后再判断,应该调整顺序
http://img1.sycdn.imooc.com//climg/5f6aa46d0956a3cc05760189.jpg
如果我的回答解决了你的疑惑,请采纳,祝学习愉快~

  • 提问者 反冲斗士 #1
    已修改,pipeline其实已创建好,可能截图问题没显示出来,我按这两点都改了,但是还是一样,而且如果我把con.delete('kill_total', 'kill_num', 'kill_flag', 'kill_user')这一行代码删掉,每一次重新运行,user_id的名单都会多6个(加上这行代码,每次固定只有6个id),而且一直往后运行会超过50,设置的判断语句没效果
    2020-09-23 22:51:33
问题已解决,确定采纳
还有疑问,暂不采纳

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

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

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

在线咨询

领取优惠

免费试听

领取大纲

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