14 秒杀系统 | 交易性能优化 | 库存行锁优化(一)扣减库存 Redis 化

SQL 分析

  • MySQL 加行锁的前提是:item_id 这一列上必须有索引;
  • 如果 item_id 这一列上没有索引,那么只能加表锁;

    
    
  1. <update id= "decreaseStock">
  2. update item_stock
  3. set stock = stock - #{amount}
  4. where item_id = #{itemId} and stock >= #{amount}
  5. </update>
  • 给 item_id 加唯一索引
alter table item_stock add unique index item_id_index(item_id);

    
    
  • 表结构

    
    
  1. CREATE TABLE `item_stock` (
  2. `id` int NOT NULL AUTO_INCREMENT,
  3. `stock` int NOT NULL DEFAULT '0',
  4. `item_id` int NOT NULL DEFAULT '0',
  5. PRIMARY KEY (`id`),
  6. UNIQUE KEY `item_id_index` (`item_id`)
  7. ) ENGINE =InnoDB AUTO_INCREMENT = 3 DEFAULT CHARSET =utf8 COLLATE =utf8_unicode_ci;

扣减库存 Redis 化

  • 活动发布时,同步库存到 Redis 中:

    
    
  1. @Override
  2. public void publishPromo (Integer promoId) {
  3. PromoDO promoDO = promoDOMapper.selectByPrimaryKey(promoId);
  4. if (promoDO.getItemId() == null || promoDO.getItemId().intValue() == 0) {
  5. return;
  6. }
  7. ItemModel itemModel = itemService.getItemById(promoDO.getItemId());
  8. redisTemplate.opsForValue().set( "promo_item_stock_" + itemModel.getId(), itemModel.getStock());
  9. }
  • 下单交易减 Redis 中的库存;

    
    
  1. @Override
  2. @Transactional
  3. public boolean decreaseStock( Integer itemId, Integer amount) {
  4. // int affectedRows = itemStockDOMapper.decreaseStock(itemId, amount);
  5. long result = redisTemplate. opsForValue(). increment( "promo_item_stock_" + itemId, amount * - 1);
  6. if (result >= 0) {
  7. return true;
  8. } else {
  9. return false;
  10. }
  11. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值