采用先更新数据库,再删除缓存方式(推荐) | 如果是热点key比较多情况下,用先更新数据库,再更新缓存方式
- 分布式锁对当前更新数据加锁,保证并发数据一致性
- 修改订单状态
- 此订单加入延时队列中,补偿删除对应缓存中数据
- 删除缓存
@Transactional(rollbackFor = Exception.class)
public B2cOrderDto updateOrderStatusByCode(String orderCode, OrderStatusEnum orderStatusEnum) {
Assert.notNull(orderCode, "订单编号为空");
log.info("修改订单 订单编号:{}", orderCode);
B2cOrderEntity save = null;
InterProcessMutex lock = null;
try {
lock = zookeeperLock.tryLock("updateOrderStatus" + orderCode, 3000, 3000);
if (lock == null) {
throw new BusinessException("当前订单正在修改中,请稍后操作!");
}
//修改订单状态
B2cOrderEntity orderEntity = orderRepository.findByOrderCode(orderCode);
orderEntity.setOrderStatus(orderStatusEnum.getCode());
orderEntity.setModifyTime(new Date());
save = orderRepository.save(orderEntity);
//删除缓存
Boolean delete = redisTemplate.delete("order:" + orderCode);
//如果删除缓存失败,加入延时队列,利用重试机制进行补偿删除
if (!delete) {
amqpTemplate.convertAndSend(RabbitContents.DELETE_ORDERCACHE_EXCHANGE, "", orderCode);
log.info("exchange is {}, data is {}", RabbitContents.DELETE_ORDERCACHE_EXCHANGE, orderCode);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (lock != null) {
try {
zookeeperLock.unlock(lock);
} catch (Exception e) {
log.error("解锁失败", e);
}
}
}
return entityToDto(save);
}