转自:http://blog.itpub.net/29254281/viewspace-1800617/

还是秒杀.
秒杀一般有几个场景
1.电商秒杀商品
2.抢红包
3.抢票

假设一个场景如下:
    某电商公司搞活动,一折秒杀,推出几种秒杀的商品,每种商品1000个,预计100w人抢购
要求:
    不能超卖.绝对不可以卖多了.
    数据库要扣减库存,并且记录订单明细.

难点分析
1.不能阻塞.
海量的请求就像血栓一样,遍走周身,一旦遇到瓶颈,就会堵塞整个血管.
所以一定要让海量的用户请求,尽快结束.

2.数据库单行更新
大量的 update 库存表 set 剩余数量=剩余数量-1 where 商品ID=?
这种单行更新,有行锁,会阻塞其他事务,占用宝贵的数据库处理能力.

针对这种场景,综合了很多资料
我觉得可以尝试几个关于秒杀的优化.

1.Web服务器集群层,卸载流量
    海量的用户秒杀请求,本质上是一个排序,先到先得.
    但是如此之多的请求,完全响应,难度又很大.
    所以在Web服务器集群,可以考虑卸载流量.
    比如每十个请求,随机抛弃九个,只放行一个请求到后续处理环节.
    把秒杀的排序模式,变为随机抽奖的模式.
    
2.Web服务器集群层,缩小锁范围.
    每次秒杀活动开始之前.先计算活动推出的商品数量,然后分配一个限额到每个Web服务器.
    比如一个活动推出秒杀商品
    电视,手机,衣服各1000件,那么每台服务器的限额就是125件.
    将这个限额写入ZooKeeper,Web服务器监听到限额的变化,就会重新初始化各自的商品剩余数量.

模拟示例:

  1. private static ConcurrentHashMap<String,Integer> map=new ConcurrentHashMap<String, Integer>();
  2. private void zooKeeperHandle(){
  3. //将ZooKeeper的变化,初始化到Web服务器全局容器
  4. map.put("电视机", 125);
  5. map.put("手机", 125);
  6. map.put("衣服", 125);
  7. }

假设用户请求秒杀电视机,它只是锁了该Web服务器电视机的数量。(该Web服务器手机和衣服还可以继续并发处理,当然其他的Web服务器也在同时处理电视机的秒杀请求)
    这样缩小了锁定的范围,增加了系统处理的吞吐量.

如果这个剩余数量大于零,则将用户ID放入电视机购买队列,然后告知用户秒杀成功
    如果这个剩余数量等于零,则告知用户秒杀失败.即便别的Web服务器还有电视机的剩余配额.

3.ZooKeeper层,ZooKeeper变更库存信息
    假设活动期间,需要修改库存信息。
    两种可能,
    第一种,该商品已经卖了500件,电商不想继续卖了.
    第二种,从仓库中又找到了一些积压库存..

两种情况,都直接修改ZooKeeper中相应商品的配额.
    Web服务器会监听变化,并重新初始化全局容器.

4.消息队列层,多消费者处理
    消费者主要是从队列获取购买请求,发送至数据库
    扣减数据库库存
    写订单明细记录

5.数据库层,使用存储过程代替JDBC调用
    由于使用了多消费者处理同一队列,增加吞吐量,避免队列堆积过大.
    但是多消费者,必然导致数据库出现单行更新问题.

单行更新问题就是多个线程,并发修改同一条记录,导致事务相互阻塞.浪费了数据库宝贵的处理能力.
    考查下图.
    假设消费者到数据库的网络是1毫秒
    那么相对于存储过程,使用JDBC的方式,每个事务将至少多持有行锁2毫秒.

所以进一步优化,可以考虑用存储过程代替JDBC

6.数据库层,库存单行更新,增加多个槽位.
    单行更新场景

    增加槽位的表结构

   
    使用槽位分散行锁
    每种商品的库存,由4个槽位组成.
    事务开始,首先找到剩余数量最多的那个商品槽位.
    然后扣减该槽位的库存.
    这样一个行锁,可以变为4个行锁,系统吞吐量增加了4倍.
    (其实如果update的影响行数为0,表示该槽位已经没有库存.可以重复执行这个过程,再另选一个槽位)

  1. //开始事务
  2. select 商品,剩余数量,@槽位:=Slot from 库存表
  3. where
  4. 商品='电视机' and 剩余数量>0 and
  5. 剩余数量=(select max(剩余数量) from 库存表 where 商品='电视机')
  6. limit 1;
  7. update 库存表 set 剩余数量=剩余数量-1 where 剩余数量>0 and 商品='电视机' and Slot=@槽位;
 //如果update的影响行数不为0,写订单明细表
commit;

7.数据库层,冷热商品分开.
    某些热点商品,可以单独放置在一个数据库处理
    比如苹果手机新品,特卖打折 10w部
    这种注定会热的商品,应该使用单独的数据库处理
    避免和普通商品竞争,堵塞本次活动其他商品的处理.

参考:
http://blog.itpub.net/29254281/viewspace-1783043/
    
http://jiagou.baijia.baidu.com/article/108134?qq-pf-to=pcqq.group

http://www.infoq.com/cn/presentations/seckill-solution-based-sql

转载于:https://www.cnblogs.com/yanwei-wang/p/5957137.html

实现秒杀的几个想法(续)相关推荐

  1. 脑科学布局-陈天桥(转)

    作者:闲吟客 来源:知乎 从下面的资料看陈天桥布局脑科学已经很长时间了,而且盛大也在做相关布局.另外据说他曾经和国内学校商量捐款,让对方给他一个报告,对方一直拖着显得很不在乎,让陈觉得他们钱多不需要捐 ...

  2. 一个想法(续三):一份IT技术联盟创业计划书,开启众筹创业征程

    写在创业计划书之前的话: 昨天在闪存里我@了dudu,说:我要借钱,不久dudu回了我:傍个富婆. 当然,dudu以为我是玩笑,其实,我的确是开玩笑的,哈. 不过我正在执行一个创业计划,如果启动,我会 ...

  3. JSD-2204-(业务逻辑开发)-续秒杀业务-消息队列-Day14

    1.续秒杀业务准备 1.1设置定时任务 1.1.1将库存和随机码保存到Redis 利用Quartz将库存和随机码保存到Redis 1.创建Job接口实现类 2.创建配置类,配置JobDetail和Tr ...

  4. 一个想法(续五):IT联盟创业计划:现阶段进度公示、疑问解答及进行中的计划...

    前言: 首先今天是元宵节,先祝大伙元宵节快,单纯的快乐! 然后看看开展中的计划: IT联盟创业计划众筹发起:一个想法(续三):一份IT技术联盟创业计划书,开启众筹创业征程 IT联盟创业计划众筹进度:一 ...

  5. 秒杀多线程第十篇 生产者消费者问题 (续)

    使用java 和semaphore实现的 ,多个生产者和多个消费者的问题. 1.使用Semaphore,Semaphore的大小设定为BUFFER_LENGTH.也就是同时最多有这么多线程来操作缓冲区 ...

  6. 一个想法(续四):IT技术联盟创业众筹进度公示

    为了将整个创业过程更加的公开公正透明化,特开此篇用于展示众筹进度. 首轮众筹进度如下:(本活动截止于2017-3-6) 本文原创发表于博客园,作者为路过秋天,原文链接:http://www.cnblo ...

  7. python 抓包秒杀_Python 爬虫,推荐一款简单的抓包工具(续)

    2. Jmeter 配置 2-1创建线程组 打开 Jmeter 软件之后,保存为一个 jmx 文件 选中默认的测试计划,右键,添加一个一个线程(用户),选择线程组,这样会创建一个线程组 2-2为线程组 ...

  8. Redis03-优惠券秒杀

    一.分布式Id:订单id 在分布式架构下,传统生成Id的方式已经不再适用,应该生成全局唯一的 分布式Id需要满足的五个特性:全局性.唯一性.安全性.可用性.高性能 @Component public ...

  9. 借助Redis锁,完美解决高并发秒杀问题

    欢迎关注方志朋的博客,回复"666"获面试宝典 场景:一家网上商城做商品限量秒杀. 1 单机环境下的锁 将商品的数量存到Redis中.每个用户抢购前都需要到Redis中查询商品数量 ...

最新文章

  1. 隐马尔科夫模型原理解析
  2. activiti 设置可选处理人_新品速递|高端系列!慧明DF系列线性相位处理专业音箱处理器...
  3. 如何优雅的处理Restful
  4. java 数据源调用_实战分享: Spring boot 调用之间实现动态数据源
  5. 【Hbase】HBase 更改表名
  6. 服务器磁盘读取暴涨_8分钟了解服务器硬件知识
  7. AutoCAD 2022 for Mac v2022.2.1中文版
  8. Junit框架使用--JUnit常用断言及注解
  9. Tomcat8的下载、安装、配置
  10. 服务器pbs傻瓜操作
  11. IP Forwarding打开
  12. 北大教授:学术会议,已沦为表演
  13. 三伏天不能吃冷饮?7月这些蜚语你中招没
  14. python实现 pdf转png格式
  15. 成功解决 KeyError: Unable to open object (object x doesnt exist)和no file found ./SGN/asd.phl
  16. 中文转UTF-8 和UTF-8转中文
  17. 巴西龟购买指南(避免掉坑)
  18. java局域网通信_java局域网通信
  19. Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localizati论文精读及资源整理
  20. (1146, Table 'django.django_session' doesn't exist)

热门文章

  1. mysql金额数字转成中文_数字转换成汉字金额(转)
  2. python中的接口
  3. 蚂蚁金服大规模分布式事务实践和开源历程
  4. JVM性能调优实践:G1 垃圾收集器介绍篇
  5. Top-K问题与多路归并排序
  6. scala学习笔记-集合操作(15)
  7. XGBoost 与 Spark 在广告排序中的应用
  8. Java获取泛型T的类型 T.class
  9. spring boot与spring mvc的区别是什么?
  10. 微博预计要火一阵的SleepSort之Shell及C实现