GitHub - chanjarster/artemis-disruptor-miaosha: 没有redis也能够支撑

标签: | 发表时间:2018-09-08 10:18 | 作者:
出处:https://github.com

artemis-disruptor-miaosha

没有redis也能够支撑 "小米在印度把亚马逊搞挂了"事件的秒杀解决方案。

小米在印度打破了多项记录:

  1. 4分钟内卖出了超过250,000台。 ---OPS:1042次抢购/S
  2. 成为最快的手机抢购活动。
  3. 抢购前我们收到了100万“到货提醒”。
  4. 亚马逊每分钟收到超过500万个点击。
  5. 亚马逊在这个期间每秒收到1500个订单(这是印度电商公司所有销售中最高的)。 ---OPS:1500次下单请求/S

性能表现

先说一下性能表现吧,因为大家对这个比较感兴趣。

硬件环境(Tomcat、Artemis、Jmeter、Oracle,backend都在这台电脑上):

  • MacBook Pro (Retina, 15-inch, Mid 2014)
  • 2.2 GHz Intel Core i7
  • 16 GB 1600 MHz DDR3
  • 512G SSD

软件环境:

  • java version "1.8.0_131"
  • Artemis 1.5.4
  • Oracle XE 11g (Docker)
  • Tomcat 8.5.14 (1个)

相关配置见 如何准备环境

测试Jmeter脚本见 如何Benchmark

  • 300线程,循环1000次,共30w请求

一共Benchmark了两次,因为JIT的关系,第二次的性能表现更好。

第一次结果

  • QPS:300000 in 00:01:57 = 2569.8/s Avg: 108 Min: 0 Max: 41102 Err: 164 (0.05%)
  • TPS:299836订单 / 121秒 = 2477条/s

PS. 数据库表现从后端程序的日志中分析的。

第二次结果

不重启Tomcat和Artemis,把数据库的数据恢复后,重启了后端程序

  • QPS:300000 in 00:00:35 = 8527.8/s Avg: 20 Min: 0 Max: 4515 Err: 2 (0.00%)
  • TPS:246873订单 / 46 秒 = 5366条 / s

数据库记录数偏少是因为Artemis队列满了,把消息丢掉了。

架构说明

从部署拓扑上看,架构分为4个部分:

  1. webapp,可集群部署,运行在Tomcat中
  2. ActiveMQ Artemis,负责webapp和backend之间的通信
  3. backend,只能单个部署,独立运行,内部使用 Disruptor
  4. Oracle数据库

ActiveMQ Artemis

ActiveMQ Artemis是JBoss把HornetQ捐赠到Apache基金会后改名的项目,目前是ActiveMQ下的子项目。

HornetQ是当年大名鼎鼎的高性能消息中间件,因此 ActiveMQ Artemis也具备相当的性能表现。

本项目利用它做webapp和backend之间的消息通信。

Disruptor

Disruptor是LMAX公司开源的高性能内存队列。 Disruptor能够让开发人员只需写单线程代码,就能够获得非常强悍的性能表现,同时避免了写并发编程的难度和坑。 其本质思想在于多线程未必比单线程跑的快。

backend利用它把从 ActiveMQ Artemis获得请求串行化,判断商品库存是否充足,更新剩余库存,最后异步写入数据库。

使用内存、避免IO

本项目对于库存是否充足的判断既不在数据库层面,也没有利用redis,更不涉及任何IO。

backend程序在启动时将数据库中的库存数据加载到内存中,库存充足判断、更新剩余库存的动作都是在内存中进行的,配合 Disruptor绕过了并发编程的内存可见性、同步、锁等问题,性能非常强。

也许有人会说,在实际项目中把商品信息都放到内存中不现实,怕会发生OOM,其实这个要看具体情况。

在本项目中商品在内存中相关类是 Item.java,在利用 jol-cli( 点此下载)查看其memory-layout后发现,其大小为24byte:

    me.chanjar.jms.server.memdb.Item object internals:
 OFFSET  SIZE  TYPE DESCRIPTION                    VALUE
      0    12       (object header)                N/A
     12     4   int Item.amount                    N/A
     16     4  Long Item.id                        N/A
     20     4       (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

Long占用的内存也为24b:

    java.lang.Long object internals:
 OFFSET  SIZE  TYPE DESCRIPTION                    VALUE
      0    12       (object header)                N/A
     12     4       (alignment/padding gap)        N/A
     16     8  long Long.value                     N/A
Instance size: 24 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total

假设你有100W商品需要秒杀,那么其占用内存 = 1,000,000 * (24b + 4b + 24b) = 52,000,000b = 49m。仅仅只占49m。

优化项

架构上的优化点

  1. 下单请求异步处理,请求返回的本次请求的ID,客户端拿这个ID到另行发起请求查询结果
  2. 在秒杀期间,商品库存信息在内存中,库存判断及库存扣减都在内存中进行,之后异步到数据库
  3. 利用Disruptor将并发请求串行化,同时避免了多线程编程复杂度
  4. 抛弃数据库事务,采用最终一致性

和JMS相关的优化点

  1. 重用JMS Connection、Session、MessageProducer、MessageConsumer,而不是每次都创建这些对象(Spring的JmsTemplate就是这么干的)
  2. 将JMS Session设定为transacted=false, AUTO_ACKNOWLEDGE
  3. 发送JMS消息时DeliveryMode=NON_PERSISTENT
  4. 关闭Artemis的重发、消息持久机制

和JDBC相关的优化点

  1. 使用JDBC Batch Update,减少和数据库网络IO的次数
  2. 优化更新商品库存的DB操作,在高并发情况下,将针对同一个商品的更新库存操作合并成一条update,而不是多个update(借助于Disruptor)

和Tomcat相关的优化点

  1. 调大maxThreads参数

流程说明

本项目只提供了两个接口:

  1. 下单接口。用于下单。
  2. 查询下单结果的接口。用于查询下单是否成功。

聪明的读者肯定已经想到了,整个秒杀过程是异步的。

下单流程

下单流程

查询下单结果的流程

查询下单结果流程

How-tos

相关 [github chanjarster artemis] 推荐:

GitHub - chanjarster/artemis-disruptor-miaosha: 没有redis也能够支撑

- -
"小米在印度把亚马逊搞挂了"事件的秒杀解决方案. 小米在印度打破了多项记录:. 4分钟内卖出了超过250,000台. ---OPS:1042次抢购/S. 抢购前我们收到了100万“到货提醒”. 亚马逊每分钟收到超过500万个点击. 亚马逊在这个期间每秒收到1500个订单(这是印度电商公司所有销售中最高的).

Apache Artemis 1.2.0 发布,嵌入式消息服务

- - 开源中国社区最新新闻
Apache Artemis 1.2.0 发布了. 该版本修复了不少BUG,可喜的是带来了OSGI的支持. 改善了一下Jounal文件的创建和重用处理流程,. 改善了TCP压力回馈流量控制(TCP Back Pressure delivery flow control). 更具体的 Changelog 请看这里:  ReleaseNote.

Home · JohnLangford/vowpal_wabbit Wiki · GitHub

- -
There are two ways to have a fast learning algorithm: (a) start with a slow algorithm and speed it up, or (b) build an intrinsically fast learning algorithm.

git和github简介(上)

- linyehui - 没做完,没准备好
在此贴上本人在Web标准化交流会6月25日北京站的主题分享. 在线PPT:http://jinjiang.github.com/slides/learning-git/. PPT源码:https://github.com/Jinjiang/slides/tree/gh-pages/learning-git.

Github使用指南(转)

- - CSDN博客推荐文章
来自:https://github.com/neuola/neuola-legacy/wiki/github%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97. 如果你只是想了解 github 的使用,请跳到 Github 简介一节. 作为程序员大军之一,想必大家有这样的经历吧.

github 上的好东西

- - 收集分享互联网资源
基于HTML5的专业级图像处理开源引擎.

Windows 下 使用TortoiseGit GitHub

- - CSDN博客研发管理推荐文章
TortoiseGit依赖msysgit,首先下载: http://code.google.com/p/msysgit/downloads/detail?name=msysGit-fullinstall-1.8.1.2-preview20130201.exe&can=2&q=. 再下载TortoiseGit: http://code.google.com/p/tortoisegit/wiki/Download?tm=2.

一个 GitHub Trending 小工具

- - IT瘾-dev
Github Trending基本上是我每天都会浏览的网页,上面会及时发布一些GIthub上比较有潜力的项目,或者说每日Star数增量排行榜. 不过由于Github Trending经常会实时更新,即使你访问得再勤,难免还是会错过一些你感兴趣的项目,为此不少人都想出了自己的解决办法,例如. josephyzhou,他的 github-trending项目得到了众多人的青睐,我仔细阅读了他的源码 (Go),发现实现也较为简单, 就用Python 重写了一下,发现代码少了好多,详见 我的 github-trending.

blong/clickhouse .md at master · xingxing9688/blong · GitHub

- -
https://clickhouse.yandex/tutorial.html快速搭建集群参考. https://clickhouse.yandex/reference_en.html官网文档. https://habrahabr.ru/company/smi2/blog/317682/关于集群配置参考.

Github 用户数突破一百万

- pipitu - Solidot
51开源社区 写道 "Gibhub用户数已突破一百万,Github官方博客发布了庆祝图片. 目前已有1,004,771用户,在Github托管了超过2,836,210 个git库. Git是一个分布式的版本控制系统,最初由Linus Torvalds编写,用作Linux内核代码的管理. 推出后,Git在其它项目中也取得了很大成功,尤其是在Ruby社区中.