Mejores esfuerzos para notificar a las soluciones de transacciones distribuidas

Una solución es posible para notificar al programa de transacción distribuida, a continuación es un ejemplo de una recarga:

 

proceso interactivo:
1, cuenta del sistema llamada al sistema de recarga de interfaz
2, recargar el sistema para completar la notificación del resultado de recarga proceso de pago iniciada con el sistema de cuentas

Si la notificación no, el sistema de recarga por la política de notificación repetida
3, el sistema recibe una cuenta de recarga modificaciones dan como resultado la notificación del estado de recarga.
4, sistema de cuenta no recibe la notificación del sistema llamará automáticamente a la interfaz de recarga para la recarga de los resultados.
Por el ejemplo anterior que mejor resumen para informar a los objetivos del programa:
objetivo: para iniciar una fiesta de notificación de los resultados del negocio de procesamiento a través de ciertos mecanismos mejores esfuerzos para notificar al destinatario.
Específicamente incluye:
1, un determinado mensaje se repite mecanismo de notificación.
Dado que la parte receptora no puede recibir notificación de la notificación, en este momento no debe haber algún mecanismo para mensaje de notificación duplicado.
2, el mensaje de corrección de pruebas mecanismos.
Si usted no hizo los mayores esfuerzos para informar al destinatario, o el destinatario de prensa posterior al consumidor para el consumidor de nuevo, esta vez por el mensaje de consulta al destinatario parte notificada de forma activa
la información para satisfacer la demanda.
Mejores esfuerzos para notificar y consistencia de la información fiable ¿Cuál es la diferencia?
1, resolver escenarios diferentes pensaron
a las fuentes de consistencia fiable, iniciaron notificar a las partes tienen que asegurarse de que el mensaje enviado, y envía el mensaje a la atención del receptor, la fiabilidad de los mensajes clave para iniciar una notificación por parte del
partido para ser garantizada.
Mejores esfuerzos para notificar, informar a la parte lanzó sus mejores esfuerzos para notificar el resultado del proceso de negocio para recibir las partes de notificación, pero no puede recibir el mensaje, entonces tienen que tomar
para cerrar la iniciativa de llamar a notificar a las partes para iniciar una interfaz de grupo de procesamiento de consulta de notificación de los resultados del negocio, notificación fehaciente la clave de recibir la notificación de la fiesta.
2, dos escenarios de negocio diferentes
fuente confiable de preocupación es la consistencia de la transacción consistente con el proceso de negociación, de forma asíncrona para completar la transacción.
Mejor para informar preocupa que después de los Asuntos de notificación de transacciones, resultados comerciales fiables que sale aviso.
3, las diferentes soluciones técnicas direcciones
mensaje fiable enviado desde la consistencia a resolver por el mensaje recibido consistencia, es decir, el mensaje es enviado y recibido.
Mejores esfuerzos no pueden garantizar que el mensaje haya recibido la notificación de la emisión a la consistencia, los mecanismos de confiabilidad solamente los mensajes recibidos. mecanismo fiable, la eliminación de la mayor
interés para el destinatario una notificación, cuando un mensaje no puede ser recibida por el receptor, el mensaje de consulta receptor-iniciado (el resultado del procesamiento).

Soluciones
mediante la comprensión de la mejor manera de informar, utilizando el mecanismo de MQ ACK puede lograrse mejor a aviso.
Escenario 1:

 

 

 

Esta realización es el uso de MQ mecanismo de notificación de acuse de recibo para enviar una notificación a la parte receptora por el MQ, proceso es el siguiente:
1. La parte que inicia la notificación para notificar MQ.
Utilice mensaje común mecanismo de notificación enviará MQ.
Nota: Si el mensaje no se envía la notificación por la iniciativa parte receptora para iniciar una notificación solicitando resultados de ejecución de consultas de negocios partido. (Habla Detrás)
2, para recibir notificaciones MQ monitor de fiesta.
3, la parte receptora recibe el mensaje de notificación, un acuse de recibo de transacción de respuesta de finalización.
4, recibir notificaciones si el partido no respondió a repetidas acuse de recibo del aviso de MQ.
MQ seguirá 1min, 5min, 10 min, 30 min, 1 h, 2 h, 5 h, 10h intervalo manera, el intervalo de notificación ensanchado gradualmente (si MQ emplea
rocketMq, puede estar dispuesto en el corredor) hasta que la ventana de tiempo alcanza superior solicitud de notificación.
5, antes de recibir un mensaje de notificación a la consistencia de la corrección de pruebas por la interfaz de mensaje de corrección de pruebas.
Esquema 2:
Esta realización también utiliza el mecanismo de MQ ack, diferente de la forma de realización 1 es la aplicación para recibir una notificación envía una notificación, como se muestra a continuación:

proceso interactivo es el siguiente:
1, el partido iniciará una notificación notificación a MQ.
mensaje de la transacción usando el mismo esquema para garantizar los asuntos locales fiable de mensajes atomicidad y el mensaje finalmente se dará cuenta de primera emitida MQ.
2, la notificación escucha MQ, MQ mensaje recibido.
Partido 1 recibe la notificación MQ esquema de monitorización directa, MQ oyente en el Esquema 2 de la notificación.

Si no hay respuesta al procedimiento de notificación ack las notificaciones MQ repetida.
3, el programa llama a una notificación a través de Internet recibir notificaciones protocolo de interfaz de Program Interface (por ejemplo, http, servicio web), la notificación de finalización.
Notificación interfaz de llamada a procedimiento para recibir notificaciones de la notificación de éxito que indica que el programa tiene éxito, es decir, un mensaje de éxito MQ consumo, MQ no entregará mensaje de notificación notifica al programa de
información.
4, antes de recibir un mensaje de notificación a la consistencia de la corrección de pruebas por la interfaz de mensaje de corrección de pruebas.
Difiere del Esquema 1 y el Esquema 2:
1, el esquema 1 recibe la parte notificada e interfaces MQ, es decir, sistema de notificación MQ oyente recibe, la aplicación principal y notificación entre este programa de aplicación interna.
Después de 2, Esquema 2 por el oyente las interfaces MQ MQ con el programa de notificación, la notificación programa recibido por el mensaje MQ llamadas a procedimientos de notificación recibidas a través de la interfaz de Internet protocolo de
fiesta notificación. Este esquema de notificación aplica principalmente entre la aplicación externa, el resultado de pago tales como el pago Po, la notificación micro mensaje.

RocketMQ máximo esfuerzo para notificar el tipo de transacción
descripción del negocio
ejemplos de realización posible para notificación de transacciones distribuidas RocketMq middleware, proceso de recarga de simulación.
Este caso tiene dos sistemas de cuentas y servicios del sistema de micro-recarga, que representan la base de datos del sistema de base de datos es BANK1, incluyendo la cuenta de Joe Smith. sistema de recarga de
base de datos de uso bank1_pay base de datos para registrar los registros de cuentas de prepago.
Los procesos de negocio como se muestra a continuación:

 

proceso de interacción es la siguiente:
1, una petición de usuario para sistema de recarga de recarga.
2, el sistema de recarga recarga completa se recargará resultados de MQ.
3, el sistema de monitorización de la cuenta MQ, recargue la notificación del resultado de la recepción, si no se recibe el mensaje, el MQ envía una notificación en repetidas ocasiones. Los resultados recibidos notificación cuenta del sistema de recarga
del sistema para aumentar la cantidad de recarga.
4, la cuenta del sistema investigación también puede tomar la iniciativa para recargar el sistema para recargar el resultado de una interfaz de consulta, aumentar la cantidad.

pago alcanzar las siguientes funciones:
1, recargue la interfaz
2, para completar la notificación de recarga
3, la interfaz de consulta resultado de recarga
2) Dao

@Mapper 
@Component 
pública  interfaz AccountPayDao { 
    @Insert ( "valores de inserción en account_pay (id, account_no, pay_amount, resultado) (# {id}, {# AccountNo}, {# payAmount}, {#} resultado)" )
     int insertAccountPay (@Param ( "id") String Id, @Param ( "AccountNo") de cadena AccountNo, @Param ( "payAmount") doble pay_amount, @Param ( "número" ) resultado String); 

    @Select ( "SELECT ID, account_no AccountNo, pay_amount payAmount, resultado de account_pay donde id = # {txNo}" ) 
    AccountPay findByIdTxNo (@Param ( "txNo" ) de cadena txNo); 



}

3) Servicio

@Service 
@ SLF4J 
pública  clase AccountPayServiceImpl los implementos AccountPayService { 

    @Autowired 
    AccountPayDao accountPayDao; 

    @Autowired 
    RocketMQTemplate rocketMQTemplate; 

    // inserción de registro superior 
    @ Override
     pública AccountPay insertAccountPay (AccountPay accountPay) {
         int Éxito = accountPayDao.insertAccountPay (accountPay.getId (), accountPay. getAccountNo (), accountPay.getPayAmount (), el "éxito" );
         SI (éxito> 0 ) {
             // enviar una notificación, un mensaje de notificación se envía utilizando común 
            accountPay.setResult ( "éxito" );
            rocketMQTemplate.convertAndSend ( "topic_notifymsg" , accountPay);
             retorno accountPay; 
        } 
        retorno  nula ; 
    } 

    // para la recarga registrada partido de notificación de recepción llama a este método para consultar el resultado recarga 
    @ Override
     pública AccountPay getAccountPay (String TXNO) { 
        AccountPay accountPay = accountPayDao. findByIdTxNo (TXNO);
         retorno accountPay; 
    } 
}

4) Controller

@RestController
 pública  clase AccountPayController { 

    @Autowired 
    AccountPayService accountPayService; 

    // 充值 
    @GetMapping (value = "/ paydo" )
     pública paga AccountPay (AccountPay accountPay) {
         // 生成事务编号 
        cadena txNo = UUID.randomUUID toString () ().; 
        accountPay.setId (txNo); 
        retorno accountPayService.insertAccountPay (accountPay); 
    } 

    // 查询充值结果 
    @GetMapping (value = "/ payresult / {} txNo" )
     pública payresult AccountPay (@PathVariable ( "txNo" ) Cadena txNo) {
         retornoaccountPayService.getAccountPay (txNo); 
    } 
}

BANK1 lograr las siguientes funciones:
1, la escucha MQ, recibiendo resultado de recarga, la cantidad de modificación de acuerdo con la cuenta para completar el resultado de recarga.
2, la iniciativa para el sistema de recarga, la cantidad completa cuenta de recarga modificado de acuerdo con los resultados.
1) Dao

@Mapper 
@Component 
pública  interfaz AccountInfoDao {
     // modificar la cantidad de cuentas 
    @Update ( "SET actualización ACCOUNT_INFO la account_balance la account_balance = {IMPORTE} + # = # {AccountNo el DONDE account_no}" )
     int updateAccountBalance (@Param () Cadena AccountNo "AccountNo", @ PARAM ( "CANTIDAD" ) CANTIDAD doble); 


   // consulta idempotente registrado para el control idempotente 
    @Select ( "SELECT COUNT (1) a partir de de_duplication DONDE tx_no = {#} TXNO" )
     int isExistTx (String TXNO); 

    / / registro de la transacción complemento, para el control de idempotent 
    @Insert ( "valores de_duplication INSERT INTO ({#} TXNO, ahora ());" )
     int addTx (String TXNO); 

}

2) AccountInfoService

@Service 
@ SLF4J 
pública  clase AccountInfoServiceImpl implementos AccountInfoService { 

    @Autowired 
    AccountInfoDao accountInfoDao; 

    @Autowired 
    PayClient payClient; 

    // 更新账户金额
    @ Override 
    @Transactional 
    pública  vacío updateAccountBalance (AccountChangeEvent accountChange) {
         // 幂等校验
        si (accountInfoDao.isExistTx (accountChange.getTxNo ())> 0 ) {
             retorno ; 
        } 
        Int i =accountInfoDao.updateAccountBalance (accountChange.getAccountNo (), accountChange.getAmount ());
         // registro de la transacción de inserción, para controlar idempotente 
        accountInfoDao.addTx (accountChange.getTxNo ()); 
    } 

    // llamada remota para la recarga de los resultados 
    @Override
     públicas queryPayResult AccountPay (String tx_no) { 

        // llamar a distancia 
        AccountPay payresult = payClient.payresult (tx_no);
         IF ( "éxito" .equals (payresult.getResult ())) {
             // Actualizar cuenta la cantidad 
            AccountChangeEvent accountChangeEvent = nueva nueva AccountChangeEvent (); 
            accountChangeEvent.setAccountNo (payresult.getAccountNo ()); //Cuenta 
            accountChangeEvent.setAmount (payresult.getPayAmount ()); // cantidad 
            accountChangeEvent.setTxNo (payresult.getId ()); // número de transacción de recarga 
            updateAccountBalance (accountChangeEvent); 
        } 
        retorno payresult; 
    } 
}
@FeignClient (valor = "DTX-notifymsg-Demo-Pay", fallback PayFallback. Clase )
 pública  interfaz PayClient { 

    // recarga Interfaz de Consulta resultado del sistema de llamada de recarga a distancia de 
    @GetMapping (value = "/ pago / payresult / {} txNo " )
     pública payresult AccountPay (@PathVariable (" TXNO " ) cadena TXNO); 
}

3) MQ monitor de

@Component 
@ SLF4J 
@RocketMQMessageListener (tema = "topic_notifymsg", consumerGroup = "consumer_group_notifymsg_bank1" )
 pública  clase NotifyMsgListener implementos RocketMQListener <AccountPay> { 

    @Autowired 
    AccountInfoService accountInfoService; 

    // 接收消息
    @ Override
     pública  vacío onMessage (AccountPay accountPay) { 
        log.info ( "接收到消息: {}" , JSON.toJSONString (accountPay));
        si ( "éxito" .equals (accountPay.getResult ())) {
             // 更新账户金额
            AccountChangeEvent accountChangeEvent = nuevo AccountChangeEvent (); 
            accountChangeEvent.setAccountNo (accountPay.getAccountNo ()); 
            accountChangeEvent.setAmount (accountPay.getPayAmount ()); 
            accountChangeEvent.setTxNo (accountPay.getId ()); 
            accountInfoService.updateAccountBalance (accountChangeEvent); 
        } 
        Log.info ( "处理消息完成: {}" , JSON.toJSONString (accountPay)); 
    } 
}

 

 4) Controller

@RestController 
@ SLF4J 
pública  clase AccountInfoController { 

    @Autowired 
    privada accountInfoService AccountInfoService; 

    // 主动查询充值结果 
    @GetMapping (valor = "/ payresult / {txNo}" )
     pública resultado AccountPay (@PathVariable ( "txNo" ) de cadena txNo) { 
        AccountPay accountPay = accountInfoService.queryPayResult (txNo);
        volver accountPay; 
    } 
}

Los escenarios de prueba

12/03/2020 18: 54: 21.442 DEBUG 8108 --- [io-9901-exec-10] ctmdAccountPayDao.insertAccountPay: ==> Preparación: (, account_no identificación, pay_amount, resultado) valores inserto en account_pay (?,? ,?,? ) 
 03/12/2020 18: 54: 21.442 DEBUG 8108 --- [io-9901-exec-10] ctmdAccountPayDao.insertAccountPay: ==> Parámetros: 4db8776f-fc55-4190-b014-7caa21b77ec0 (String) , 1 (String), 2000,0 (doble), el éxito (String)
 03/12/2020 18: 54: 21.455 DEBUG 8108 --- [io-9901-exec-10] ctmdAccountPayDao.insertAccountPay: <== Actualizaciones: 1
12/03/2020 18: 54: 21.464 INFO 20.964 --- [MessageThread_3] c.topcheer.eq.message.NotifyMsgListener:接收到消息: { "AccountNo": "1", "id": "4db8776f-fc55- 4190-b014-7caa21b77ec0" , "payAmount": 2000.0, "número": "éxito" }
 03/12/2020 18: 54: 21,466 DEBUG 20964 --- [MessageThread_3] cteq.dao.AccountInfoDao.isExistTx: ==> Preparación: select count (1) desde donde de_duplication tx_no =? 
12/03/2020 18: 54: 21.466 DEBUG 20.964 --- [MessageThread_3] cteq.dao.AccountInfoDao.isExistTx: ==> Parámetros: 4db8776f-fc55-4190-b014- 7caa21b77ec0 (String)
 03/12/2020 18: 54: 21.467 DEBUG 20.964 --- [MessageThread_3] cteq.dao.AccountInfoDao.isExistTx: <== total: 1 
03/12/2020 18: 54: 21.468 DEBUG 20964 --- [MessageThread_3] ctedAupdateAccountBalance: ==> Preparación: 
12/03/2020 18: 54: 21.468 DEBUG 20.964 --- [MessageThread_3] ctedAupdateAccountBalance: ==> Parámetros: 2000,0 (doble), 1 (String)
 03/12/2020 18: 54: 21.470 DEBUG 20.964 --- [ MessageThread_3] ctedAupdateAccountBalance: <== actualizaciones: 1 
03/12/2020 18: 54: 21.470 DEBUG 20.964 --- [MessageThread_3] c.topcheer.eq.dao.AccountInfoDao.addTx: ==> Preparación: inserción en valores de_duplication ( ? , ahora ()); 
12/03/2020 18: 54: 21.470 DEBUG 20.964 --- [MessageThread_3] c.topcheer.eq.dao.AccountInfoDao.addTx: ==> Parámetros: 4db8776f-fc55-4190-b014-7caa21b77ec0 (String)
 03/12/2020 18: 54: 21.473 DEBUG 20.964 --- [MessageThread_3] c.topcheer.eq.dao.AccountInfoDao.addTx: <== actualizaciones: 1 
03/12/2020 18: 54: 21.486 INFO 20.964 --- [MessageThread_3] c.topcheer.eq.message.NotifyMsgListener:处理消息完成: { "AccountNo": "1", "id": "4db8776f-fc55-4190-b014-7caa21b77ec0", "payAmount" : 2000.0, "número": "éxito"}
Publicados 407 artículos originales · ganado elogios 2 · Vistas 6790

Supongo que te gusta

Origin blog.csdn.net/qq_29860591/article/details/104833043
Recomendado
Clasificación