Micro-services (and more libraries across servers) distributed transaction component design thinking (Wang Xiaolong, 2019-12-10)

Transaction:

First, it may exist unpredictable number of transactions;

Second, the need to coordinate all relevant transactions concurrently;

Third, the transaction may be distributed on different servers;

Fourth, through a combination of local affairs, the implementation of a distributed transaction; (combined Redis publish-subscribe mechanism, combined with an interface to the Senate, Redis to do cross-server publishing subscribe, achieved by passing the message on the overall services end up either committed or rolled back collective control)

---------------------------------------------------

First, the transaction subscribe messaging conventions:

  Services are divided into initiator, related parties;

  The transaction originator, responsible for creating a distributed transaction (while generating a unique transaction ID), and automatically monitor the current subscription message distributed transaction theme: DistributedTransaction_StatusReport_TransactionID

  The theme of the message is divided into two parameters, one is RequestID, one TransactionStatus, that the implementation of state of the target service.

  When call other services within the distributed transaction, the transaction ID is transmitted over the same time, while producing a RequestID each different service request;

  (Micro API service requests the service base class to be reserved transaction ID field is distributed transaction, defaults to null or empty, the transaction needs to be executed in the form of pass or specific interface implemented only distributed transaction, for the transaction to add the interface ID specific parameters)

      Other services at the time of execution, judge there is a transaction ID, transaction-based scheduling situation, but does not commit, before you commit to do WaitOne and will wait for a timeout operation;

      Redis wait before the start of the subscription, the subscription message associated with the transaction ID, the message is: DistributedTransaction_StatusCommit_TransactionID

      When listening to the news, do Set operations, exit the timeout, and complete the transaction operations;

  Redis messages have three results:

    Message timeout: Rollback

    Message submission: Submit

    Message Rollback: Rollback

    [Service regardless of rollback or commit, need to unsubscribe message on the above matters;]

   Distributed Transaction creator, responsible for recording the results of each service call, there is a discovery stage of a service call fails, an error, is not complete, immediate notification is sent to the front of the rollback other services, follow-up services are no longer continue to call;

    Creator in all of the services, after their own affairs are executed, after confirming there is no problem, push messages distributed to various machines, Circular submit.

  ----------------------------------------------

  So far distributed transaction is completed. To solve a number of problems between micro service when you call the service, each local affairs coordination.

Second, the design:

  DistributedTransaction.Create () // generates a distributed transaction ID, or consider the wording Using transaction range, the distribution of other services call, and checks the scheduling result for each service,

  DistributedTransaction.SessionID // Save the above call Create to create a transaction ID

  DistributedTransaction.Commit () // implementation of distributed transaction commits, the fact is the news release submitted to the Redis, to subscribers of all equipment, send subscribe message;

  DistributedTransaction.Rollback () // rollback to perform distributed transactions. Also released a rollback message to Redis.

  DistributedTransaction.AddServiceTransaction ({ServiceRequestID, TransactionStatus}) // add a related party transaction, there are a few records for local services involved in the transaction, and the other's state record (waiting, committed, rolled back), also expressed the need is associated with each service requested by a request ID, or rolls back up service if submitted, the creator may send messages to indicate the status.

  DistributedTransaction.HasRollbacks () // used to determine whether a service transaction is rolled back

  DistributedTransaction.HasCommits () // used to determine whether a transaction occurs submitted;

  DistributedTransaction.WaitComplate()

  // used to determine whether all of the submission is successful only when all states have been submitted, as if they all commit, rollback if there is submitted, the transaction in question, regarded as false, if there is to wait, have to submit, then wait for the final completion (also need to have a timeout mechanism).

  // This method will wait for the final result, and the final result of the transaction and return the description information, but failed part, only recording request ID, can be extended to complete the association ID of the local request and services;


Third, the question:

  1, transaction tracking, no tracking mechanism described above, if, assuming that there are three different services involved in the transaction, of which three were executed, the transaction is to be committed or rolled back state before submitting news release,

    A crash in which a service (assuming power failure), can not receive the message, the other two service message is successfully received, then the other two commit service, service A because when the machine is not submitted;

    In theory, since the data before and after the transaction is not involved in the business, does not track the specific impact of the table, the impact, therefore, can not perform manual rollback;

    But could theoretically increase rolled back or committed, service nodes and other mechanisms to ensure that the increase in distributed transaction initiator, clear whether completed or partially completed submission.

    However, if the assumption that the transaction initiated hair crash? The machine has not been submitted to the transaction, but the transaction other three services have been submitted? In theory, it should be submitted performing local affairs after the machine recovery.

  2, timeout problems

    Redis waiting to receive services from the directive committed or rolled back, waiting for the stage, in order to achieve automatic rollback, and therefore will monitor timeout, timeout should be relatively short period of time, but the follow-up due to uncertainty

    Transaction creator as well as the number of service calls required, and can not determine the duration of each service execution estimation, a short time may lead to abnormal rollback.

    If possible, you should consider a number of parallel execution service, ensure that the same consolidation time, the waiting time is the most time-consuming service execution time; control any transaction should be completed within the shortest possible time.

  2.1, the timeout triggered rollback

    Due to the above design does not wait for a timeout after automatic rollback services, to notify the creator or service associated batch execution rollback Further, if the notification is sent by the service rollback occurs.

Fourth, to solve the problem:

    The above mechanism, can be resolved in a non-distributed anomalies, synchronous execution of service transactions or micro-sync rollback assumptions: there is no sudden crash the server, Redis case of crash.

 

----------------------------------------------------

Here come some EF / LINQ2SQL cross-database transaction codes, achieve a similar principle and the principle of the above, but there is no cross-server scenario, all local affairs: not encapsulated, only experimental code, how need to use in a production environment, it is recommended do write a class package for centralized control, no difference in control, do not distinguish between the number of databases require cross-database, automatically have been completed (uncommitted) transaction rollback centralized error.

 var dc = new DataContexts(0);
        dc.Ztb_shopdict.Connection.Open();
        var transaction1 = dc.Ztb_shopdict.Connection.BeginTransaction();
        dc.Ztb_shopinfo.Connection.Open();
        var tran2 = dc.Ztb_shopinfo.Connection.BeginTransaction();

        // if the transaction is successful tag
        bool TransactionStatus = true;
        try
        {
            dc.Ztb_shopdict.Transaction = transaction1;
            dc.Ztb_shopdict.Dict_SystemPara.InsertOnSubmit(new API.Domain.ztb_shopdict.Dict_SystemPara() { ShopID = 0, ParaKey = "a", ParaValue = "v" });
            dc.Ztb_shopdict.SubmitChanges();
            try
            {
                dc.Ztb_shopinfo.Transaction = tran2;
                dc.Ztb_shopinfo.Activity_Item.InsertOnSubmit(new API.Domain.ztb_shopinfo.Activity_Item() { Activity_Info_ID = 0, Activity_Price = 0, addActivity_Price = 0, enable = true, firstActivity_Price = 0, levelId = 0, ServiceID = 0, ShopID = 0 });
                dc.Ztb_shopinfo.SubmitChanges();
            }
            catch (Exception ex)
            {
                tran2.Rollback();
                // throw an error at the same time, causing a rollback
                throw ex;
            }
        }
        catch (Exception ex)
        {
            TransactionStatus = false;
            transaction1.Rollback();
            Response.Write(ex.ToString());
        }

        if (TransactionStatus)
        {
            // All transactions are successful, submitted together
                transaction1.Commit();
                tran2.Commit();
        }

  

 

Guess you like

Origin www.cnblogs.com/soleds/p/12015257.html