La cola retrasada de Rabbitmq desbloquea automáticamente el inventario

1. El servicio de inventario desbloquea automáticamente el inventario.

Insertar descripción de la imagen aquí

La coherencia final se utiliza para resolver transacciones distribuidas ¿
Qué debo hacer si el servicio de pedidos se revierte de forma anormal y el servicio de ware no puede revertirse?

Aunque el uso de transacciones globales de seata puede permitir que otros servicios se reviertan al mismo tiempo cuando se produce una excepción en el servicio de pedidos y se revierte , el método de bloqueo se utiliza cuando el tráfico es grande, lo cual es ineficiente y
no es adecuado para grandes situaciones de concurrencia. Puede usar el sondeo de tareas programadas para verificar el estado del pedido, pero el método de sondeo consume más recursos y memoria, así que elija la solución de coherencia final, use el enrutamiento de mensajes fallidos de la cola de retardo mq y luego cree una solución correctiva. siempre que aparezca el servicio de pedidos La falla se puede juzgar a través del tiempo mq, siempre que pueda garantizar que el inventario eventualmente se pueda desbloquear

La cola de retraso desbloquea automáticamente la lógica empresarial del inventario.
Cuando el servicio de artículos completa el bloqueo del inventario, envía un mensaje a mq y lo guarda en la cola de mensajes no entregados. Este mensaje registra cuánto inventario está bloqueado para esos productos. Cuando el La cola alcanza el tiempo de supervivencia, el mensaje será entregado. Al interruptor de enrutamiento de mensajes no entregados, el interruptor de enrutamiento de mensajes no entregados enviará el mensaje a la cola final. Si el tiempo de pago del pedido es de 30 minutos, configuramos el tiempo de supervivencia en 40 minutos. Esto garantiza que los mensajes que monitoreamos deben exceder el tiempo de pago. tiempo, y luego permitir que el servicio de inventario de mercancías se suscriba y monitoree la cola final. Mientras haya noticias, verificaremos el servicio de pedido. Siempre que prueba que el servicio del pedido tiene una reversión anormal o el pedido ha excedido el tiempo de pago y no ha sido pagado, lo haremos Una operación para desbloquear y restaurar el inventario

1. El inventario se bloqueó correctamente, envíe un mensaje a mq

(1) Guarde la orden de trabajo (número de orden) y los detalles de la orden de trabajo (cuánto inventario está bloqueado para el producto)
(2) Envíe una copia de los datos anteriores a mq

@Transactional
    @Override
    public boolean orderStock(OrderStockRequest orderStockRequest) {
    
    
        //保存工作单
        WareOrderTaskEntity wareOrderTaskEntity = new WareOrderTaskEntity();
        wareOrderTaskEntity.setOrderSn(orderStockRequest.getOrderSn());
        wareOrderTaskService.save(wareOrderTaskEntity);

        List<OrderItemVo> itemVos = orderStockRequest.getItemVos();
        List<SkuStockfromWare> collect = itemVos.stream().map(item -> {
    
    
            SkuStockfromWare skuStockfromWare = new SkuStockfromWare();
            skuStockfromWare.setSkuId(item.getSkuId());
            skuStockfromWare.setNum(item.getCount());
            //查询该商品在那些仓库有库存
            List<Long> wareId = wareSkuDao.skuStockfromWare(item.getSkuId());
            skuStockfromWare.setWareId(wareId);
            return skuStockfromWare;
        }).collect(Collectors.toList());

        //根据skuId遍历
        for (SkuStockfromWare skuStockfromWare : collect) {
    
    
            //判断是否锁定成功
            boolean flag = false;

            //判断该商品是否有仓库存在库存
            List<Long> wareIdList = skuStockfromWare.getWareId();
            if (wareIdList.size() < 0 || wareIdList == null){
    
    
                throw new NoWareStockException(skuStockfromWare.getSkuId());
            }
            for (Long wareId : wareIdList) {
    
    
                Long count = wareSkuDao.LockedStockFromWare(skuStockfromWare.getSkuId(),wareId,skuStockfromWare.getNum());
                if (count.equals(1L)){
    
    
                    //锁定成功
                    flag = true;

                    //保存工作单详情
                    WareOrderTaskDetailEntity wareOrderTaskDetailEntity = new WareOrderTaskDetailEntity();
                    wareOrderTaskDetailEntity.setSkuId(skuStockfromWare.getSkuId());
                    wareOrderTaskDetailEntity.setSkuNum(skuStockfromWare.getNum());
                    wareOrderTaskDetailEntity.setTaskId(wareOrderTaskEntity.getId());
                    wareOrderTaskDetailEntity.setWareId(wareId);
                    wareOrderTaskDetailEntity.setLockStatus(1);
                    wareOrderTaskDetailService.save(wareOrderTaskDetailEntity);
                    //TODO 库存锁定成功->发消息给交换机
                    StockLocked stockLocked = new StockLocked();
                    stockLocked.setTaskId(wareOrderTaskEntity.getId());
                    WareOrderTaskDetailTo wareOrderTaskDetailTo = new WareOrderTaskDetailTo();
                    BeanUtils.copyProperties(wareOrderTaskDetailEntity,wareOrderTaskDetailTo);
                    stockLocked.setDetailTo(wareOrderTaskDetailTo);
                    //convertAndSend(String exchange, String routingKey, Object object)
                    rabbitTemplate.convertAndSend("stock-event-exchange","stock.locked",);

                    //该商品锁定库存成功就执行下一个商品
                    break;
                }

            }

            //如果没有一个仓库扣成功,代表此skuId的库存不足
            if (!flag){
    
    
                throw new SkuNoStockException(skuStockfromWare.getSkuId());
            }

        }
        return true;
    }

2. Supervise la cola y desbloquee el inventario.

(1) Determinar si la orden de trabajo existe. Si
no existe, significa que la operación de bloqueo de inventario se ha revertido y no se realizará ningún procesamiento.
(2) Consultar si la orden existe.
Si la orden no existe, significa que la operación de realización del pedido se ha revertido.
Si existe, consulte el pedido. Si el estado es 4-cerrado. Si es 4-cerrado, se realiza la operación de desbloqueo de inventario y no se muestran otros estados del pedido. procesado. (
3) Antes de desbloquear, determine si el estado de la orden de trabajo es 1-bloqueado, lo que demuestra que solo se ha realizado la operación de bloqueo de inventario. (4) Desbloquee el
inventario y modifique el estado de los detalles de la orden de trabajo a desbloqueado.

/**
 * 解锁库存
 */
@RabbitListener(queues = {
    
    "stock.release.stock.queue"})
@Service
public class UnLockStockListener {
    
    

    @Autowired
    WareSkuService wareSkuService;

    @RabbitHandler
    public void UnLockStock(StockLockedTo lockedTo, Channel channel, Message message) throws IOException {
    
    
        try {
    
    
            wareSkuService.unlockStock(lockedTo);
            //签收
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
    
    
            //拒签,让消息重新归队,等待服务器重启进行下一次解锁
            channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);
        }

    }

}

Operación de desbloqueo


    /**
     * 解锁库存
     *
     * (1).判断工作单是否存在
     *      不存在代表已回滚,不做处理
     *      (2).查询订单是否存在
     *          如果订单不存在,表示已回滚
     *             (3).执行解锁库存操作
     *          如果存在,查询订单状态是否为 4-已关闭
     *                如果是 4-已关闭,执行解锁库存操作,订单其他状态不做处理
     */
    @Override
    public void unlockStock(StockLockedTo lockedTo) {
    
    

        WareOrderTaskEntity taskEntity = wareOrderTaskService.getById(lockedTo.getTaskId());
        //已回滚不做处理
        if (taskEntity != null){
    
    
            //查询订单是否存在
            R<OrderVo> r = orderFeignService.orderStatus(taskEntity.getOrderSn());
            if (r.getCode() == 0){
    
    
                OrderVo orderVo = r.getData(new TypeReference<OrderVo>() {
    
    
                });
                if (orderVo == null || orderVo.getStatus() == 4){
    
    
                    WareOrderTaskDetailTo detailTo = lockedTo.getDetailTo();
                    //判断工作单的状态是否为 1-已锁定,证明只做了锁定库存操作
                    if (detailTo.getLockStatus() == 1){
    
    
                        //恢复库存
                        unlock(detailTo.getId(),detailTo.getSkuNum(),detailTo.getSkuId(),detailTo.getWareId());
                    }
                }
            }else {
    
    
                throw new OrderFeignException();
            }

        }
    }

    /**
     * 解锁库存
     * UPDATE `wms_ware_sku` SET stock_locked = stock_locked - ?
     * WHERE sku_id = ? AND ware_id = ?
     */
    private void unlock(Long id,Integer skuNum, Long skuId, Long wareId) {
    
    
        wareSkuDao.unlock(skuNum,skuId,wareId);
        //修改状态为 已解锁
        WareOrderTaskDetailEntity wareOrderTaskDetailEntity = new WareOrderTaskDetailEntity();
        wareOrderTaskDetailEntity.setId(id);
        wareOrderTaskDetailEntity.setLockStatus(2);
    }

2. El servicio de pedidos cierra el pedido y también realiza la operación de desbloqueo de inventario.

Insertar descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/weixin_44847885/article/details/131713153
Recomendado
Clasificación