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

A distributed lock ensures that a critical section of code is executed by only one process at a time across multiple service instances. Silky provides Redis-based distributed locks via the Silky.DistributedLock.Redis package, built on top of RedLock.net.

Installation

<PackageReference Include="Silky.DistributedLock.Redis" Version="3.9.2" />

Setup

Module

[DependsOn(
    typeof(RedisDistributedLockModule),
    typeof(DotNettyTcpModule)
)]
public class OrderHostModule : SilkyModule { }

Configuration

{
  "redisLock": {
    "endpoints": [
      { "host": "127.0.0.1", "port": 6379 }
    ],
    "password": "",
    "database": 0,
    "expiry": "00:00:30"
  }
}

Using IDistributedLock

Inject IDistributedLock and use it to protect critical sections:

public class OrderAppService : IOrderAppService, IScopedDependency
{
    private readonly IDistributedLock _distributedLock;
    private readonly IOrderRepository _orderRepo;

    public OrderAppService(
        IDistributedLock distributedLock,
        IOrderRepository orderRepo)
    {
        _distributedLock = distributedLock;
        _orderRepo = orderRepo;
    }

    public async Task<CreateOrderOutput> CreateOrderAsync(CreateOrderInput input)
    {
        // Lock key is per-user to prevent double-submission
        var lockKey = $"create-order:{input.UserId}";

        await using (var handle = await _distributedLock.TryAcquireAsync(lockKey, TimeSpan.FromSeconds(10)))
        {
            if (handle == null)
            {
                throw new BusinessException("Another order creation is in progress. Please try again later.");
            }

            // Critical section — only one instance executes this at a time
            var order = new Order { UserId = input.UserId, /* ... */ };
            await _orderRepo.InsertAsync(order);
            return new CreateOrderOutput { OrderId = order.Id };
        }
    }
}

Async Lock with Timeout

// Wait up to 5 seconds to acquire the lock; expires after 30 seconds
await using var handle = await _distributedLock.TryAcquireAsync(
    resource: "inventory:update",
    expiry: TimeSpan.FromSeconds(30),
    wait: TimeSpan.FromSeconds(5),
    retry: TimeSpan.FromMilliseconds(200));

if (handle == null)
{
    // Could not acquire within the wait period
    throw new TimeoutException("Could not acquire distributed lock");
}

Parameters

ParameterDescriptionDefault
resourceUnique lock key(required)
expiryLock TTL — auto-released after this time30s
waitMax time to wait for the lock10s
retryRetry interval while waiting200ms

Multi-Node (RedLock Algorithm)

For high availability, configure multiple Redis endpoints. The lock is acquired using the RedLock algorithm — requiring a majority of nodes to agree:

{
  "redisLock": {
    "endpoints": [
      { "host": "redis-1", "port": 6379 },
      { "host": "redis-2", "port": 6379 },
      { "host": "redis-3", "port": 6379 }
    ]
  }
}
Edit this page
Prev
Caching