Silky Microservice FrameworkSilky Microservice Framework
Home
Docs
Config
Source
github
gitee
  • 简体中文
  • English
Home
Docs
Config
Source
github
gitee
  • 简体中文
  • English
  • Introduction

    • Silky Framework Overview
  • Getting Started

    • Glossary
    • Quick Start
    • Project Template
    • Microservice Architecture
    • Sample Projects
  • Host & Module

    • Host Types
    • Gateway Configuration
    • Module System
    • Plugin System
  • Gateway & HTTP

    • Swagger / OpenAPI
    • MiniProfiler
    • CORS
    • Audit Logging
  • Service & RPC

    • App Services & Service Entries
    • RPC Communication
    • WebSocket
    • Service Registry
    • Service Governance
  • Data & Cache

    • EFCore Data Access
    • Caching
    • Distributed Lock
  • Security & Auth

    • Identity & Authentication
    • Distributed Transactions
  • Infrastructure

    • Dependency Injection
    • Object Mapping
    • Validation
    • Link Tracking (SkyAPM)
    • Logging (Serilog)
    • Health Checks
    • Message Bus (MassTransit)
    • Unit & Integration Testing

Overview

In microservice applications, completing a business operation may span multiple services and multiple databases. Distributed transactions ensure that operations across multiple resource servers either all succeed or all fail, maintaining data consistency.

Theoretical Background

CAP Theorem

Distributed systems cannot simultaneously satisfy all three of:

  1. Consistency (C): All nodes see the same data at the same time
  2. Availability (A): Every request receives a response within a bounded time
  3. Partition Tolerance (P): The system continues to operate despite network partitions

Since partition tolerance is mandatory in distributed systems, architects must choose between consistency and availability based on business requirements.

BASE Theory

BASE is an alternative to ACID for large-scale distributed systems:

  • Basically Available: The system remains available despite partial failures
  • Soft State: Data may be in an intermediate state temporarily
  • Eventual Consistency: Data will converge to a consistent state eventually

distributed transactions

TCC Transaction

Silky implements the TCC (Try-Confirm-Cancel) distributed transaction pattern.

PhaseDescription
TryReserve resources; perform preliminary checks and reservations (no actual commit)
ConfirmCommit the transaction; execute the actual business operation using reserved resources
CancelRoll back; release reserved resources if Try or Confirm fails

Enable TCC Support

PM> Install-Package Silky.Transaction.Tcc -Version 3.9.2
PM> Install-Package Silky.Transaction.Repository.Redis -Version 3.9.2  # Redis journal

Configure

transaction:
  retryMax: 10              # max retry attempts for compensation
  recoverDelayTime: 60      # delay before recovery attempt (s)
  
redis:
  configuration: "127.0.0.1:6379"

Annotate the Coordinator

Mark the initiating method with [Transaction]:

[ServiceRoute]
public interface IOrderAppService
{
    [Transaction]
    Task<CreateOrderOutput> CreateOrderAsync(CreateOrderInput input);
}

Implement Try / Confirm / Cancel

Mark participant methods with [TccTransaction], specifying the confirm and cancel method names:

[ServiceRoute]
public interface IInventoryAppService
{
    // Try: reserve stock
    [TccTransaction(ConfirmMethod = "ConfirmDeductStock", CancelMethod = "CancelDeductStock")]
    Task<bool> TryDeductStockAsync(DeductStockInput input);

    // Confirm: actually deduct stock
    Task<bool> ConfirmDeductStockAsync(DeductStockInput input);

    // Cancel: release the reserved stock
    Task<bool> CancelDeductStockAsync(DeductStockInput input);
}

Orchestrate the Transaction

In the coordinator's implementation, call participant Try methods. The framework automatically calls Confirm on all participants on success, or Cancel on all on failure:

public class OrderAppService : IOrderAppService, IScopedDependency
{
    private readonly IInventoryAppService _inventoryService;
    private readonly IAccountAppService _accountService;

    public OrderAppService(
        IInventoryAppService inventoryService,
        IAccountAppService accountService)
    {
        _inventoryService = inventoryService;
        _accountService = accountService;
    }

    [Transaction]
    public async Task<CreateOrderOutput> CreateOrderAsync(CreateOrderInput input)
    {
        // Step 1: Try deduct stock
        await _inventoryService.TryDeductStockAsync(new DeductStockInput
        {
            ProductId = input.ProductId,
            Quantity = input.Quantity
        });

        // Step 2: Try deduct account balance
        await _accountService.TryDeductBalanceAsync(new DeductBalanceInput
        {
            UserId = input.UserId,
            Amount = input.TotalAmount
        });

        // If any Try fails, the framework automatically calls Cancel on all participants
        return new CreateOrderOutput { OrderId = Guid.NewGuid().ToString() };
    }
}

Transaction Journal

Silky persists transaction state in Redis, enabling automatic recovery of interrupted transactions:

  • Try phase records the participant list and input parameters
  • Confirm/Cancel phase updates transaction state
  • A background recovery task retries failed compensations up to transaction:retryMax times

Limitations

  • Only the TCC pattern is built-in; Saga and AT modes are not currently supported
  • All participant service interfaces must be Silky service entries (annotated with [ServiceRoute])
  • Confirm and Cancel methods must be idempotent — they may be called more than once during recovery
Edit this page
Prev
Identity & Authentication