dubbo系列(四) 凑一下热闹 使用dubbo redis mybatis mysql 实现商品秒杀功能
jmeter实现并发抢购
使用我的pc tomcat使用默认设置, 商品为5000个,未优化测试结果最高qps1400
开了两个dubbo服务
秒杀前准备数据
创建list存到redis里, 如果一个商品有5000件,list的大小为5000
redis数据
这里用到了redis批量插入数据,具体实现看看上面的代码吧, 用到了setnx实现锁功能,使用到redis 数据格式有string,list,map三种
抢购逻辑实现
待优化的内容
Object value = redisTemplate.opsForList().leftPop(goodQueueCache.getCacheKey()); if (value != null) { //这里待优化 }
优化的代码如下
public class SaveMiaoShaOrderRunner implements Runnable { private Logger logger = LoggerFactory.getLogger(SaveMiaoShaOrderRunner.class); private ConcurrentLinkedQueue<MiaoshaOrder> miaoshaOrdersQueue; private MiaoshaService miaoshaService; public SaveMiaoShaOrderRunner(ConcurrentLinkedQueue<MiaoshaOrder> miaoshaOrdersQueue, MiaoshaService miaoshaService) { this.miaoshaOrdersQueue = miaoshaOrdersQueue; this.miaoshaService = miaoshaService; } @Override public void run() { logger.info("开始保存订单..."); List<MiaoshaOrder> miaoshaOrders = new ArrayList<>(); int size = 0; MiaoshaOrder order; for (int i = 0; i < 1000; i++) { //获取并移除此队列的头,如果此队列为空,则返回 null。 order = miaoshaOrdersQueue.poll(); if (order == null) { break; } else { miaoshaOrders.add(order); size++; } } if (size > 0) { miaoshaService.batchSave(miaoshaOrders); miaoshaOrders.clear(); } } }
MiaoshaServiceImpl增加以下代码
@PostConstruct public void initSaveDbThread() { MyExecutors.SINGLE_SCHEDULED_EXECUTOR_SERVICE.scheduleWithFixedDelay(// new SaveMiaoShaOrderRunner(miaoshaOrdersQueue, this),2, 2, TimeUnit.SECONDS); }
优化后使用我的pc tomcat使用默认设置, 商品为40,000个,测试结果qps最高到1700
看一下数据库,没有超卖
库存数没有更新,这个是没有实现了,不是bug哦, 可以新开一个线程每几秒统计一下redis list的大小,然后更新到数据库中