Revised the distributed locking document.

pull/11867/head
Halil İbrahim Kalkan 4 years ago
parent 533a59536f
commit 0a6d01454c

@ -1,77 +1,104 @@
# Distributed Locking
Distributed locking is very useful to manage many applications that trying to access the same resource.
Distributed locking is technique to manage many applications that trying to access the same resource.
The main purpose is to allow only one of many applications to access the same resource at the same time.
Otherwise accessing the same object from various applications may corrupt the value of resources.
On this occasion, distributed locking protects the correct value throughout the applications.
> To use in ABP, you should download the below NuGet package or can open any command apps and run the below command.
> ABP's current distributed locking implementation is based on the [DistributedLock](https://github.com/madelson/DistributedLock) library.
## Installation
You can open a command-line terminal and type the following command to install the [Volo.Abp.DistributedLocking](https://www.nuget.org/packages/Volo.Abp.DistributedLocking) package it into your project:
````powershell
abp add-package Volo.Abp.DistributedLocking
````
````csharp
using Volo.Abp.DistributedLocking;
namespace AbpDemo
{
public class MyService : ITransientDependency
{
private readonly IAbpDistributedLock _distributedLock;
public MyService(IAbpDistributedLock distributedLock)
{
_distributedLock = distributedLock;
}
public async Task MyMethodAsync()
{
await using (var handle = await _distributedLock.TryAcquireAsync("NameOfLock"))
{
if (handle != null)
{
//your code
}
}
}
}
}
````
This package provides the necessary API to use the distributed locking system, however, you should configure a provider before using it.
This provider contains a method named `TryAcquireAsync` and this method returns null if the lock could not be handled.
`name` is mandatory. It keeps the locked provider name. This name should be unique, otherwise, it will be seen as a different lock.
`timeout` is set as default. If it fells deadlock and doesn't work properly you can use define the time to kill it.
`cancellationToken` is set as default. It enables cooperative cancellation between threads, thread pool work items, or Task objects
### Configuring a provider
ABP depends on [DistributedLock.Core](https://www.nuget.org/packages/DistributedLock.Core) library which provides a distributed locking system for concurrency control in a distributed environment. There are [many distributed lock providers](https://github.com/madelson/DistributedLock#implementations) including Redis, SqlServer and ZooKeeper. You may use the one you want. ABP implements the Redis provider for you and you may customize the others yourselves.
The [DistributedLock](https://github.com/madelson/DistributedLock) library provides [various of implementations](https://github.com/madelson/DistributedLock#implementations) for the locking, like [Redis](https://github.com/madelson/DistributedLock/blob/master/docs/DistributedLock.Redis.md) and and [ZooKeeper](https://github.com/madelson/DistributedLock/blob/master/docs/DistributedLock.ZooKeeper.md).
Firstly, you should add [DistributedLock.Redis](https://www.nuget.org/packages/DistributedLock.Redis) NuGet package to your project, then add the following code into the ConfigureService method of your ABP module class.
For example, if you want to use the [Redis provider](https://github.com/madelson/DistributedLock/blob/master/docs/DistributedLock.Redis.md), you should add [DistributedLock.Redis](https://www.nuget.org/packages/DistributedLock.Redis) NuGet package to your project, then add the following code into the `ConfigureServices` method of your ABP [module](Module-Development-Basics.md) class:
````csharp
using Medallion.Threading;
using Medallion.Threading.Redis;
namespace AbpDemo
{
public class MyModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
//the other configurations
var configuration = context.Services.GetConfiguration();
context.Services.AddSingleton<IDistributedLockProvider>(sp =>
{
var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
return new RedisDistributedSynchronizationProvider(connection.GetDatabase());
var connection = ConnectionMultiplexer
.Connect(configuration["Redis:Configuration"]);
return new
RedisDistributedSynchronizationProvider(connection.GetDatabase());
});
}
}
}
````
Also, you should add your Redis configuration in appsetting.json.
You may change the structure of the JSON file but it must match with the above configuration code.
This code gets the Redis connection string from the [configuration](Configuration.md), so you can add the following lines to your `appsettings.json` file:
````json
"Redis": {
"Configuration": "127.0.0.1"
}
````
As mentioned above, this implementation is for Redis and for more detail you can visit [the GitHub site](https://github.com/madelson/DistributedLock#implementations).
## Usage
There are two ways to use the distributed locking API: ABP's `IAbpDistributedLock` abstraction and [DistributedLock](https://github.com/madelson/DistributedLock) library's API.
### Using the IAbpDistributedLock service
`IAbpDistributedLock` is a simple service provided by the ABP framework for simple usage of distributed locking.
**Example: Using `IAbpDistributedLock.TryAcquireAsync` method**
````csharp
using Volo.Abp.DistributedLocking;
namespace AbpDemo
{
public class MyService : ITransientDependency
{
private readonly IAbpDistributedLock _distributedLock;
public MyService(IAbpDistributedLock distributedLock)
{
_distributedLock = distributedLock;
}
public async Task MyMethodAsync()
{
await using (var handle =
await _distributedLock.TryAcquireAsync("MyLockName"))
{
if (handle != null)
{
// your code that access the shared resource
}
}
}
}
}
````
`TryAcquireAsync` may not acquire the lock. It returns `null` if the lock could not be acquired. In this case, you shouldn't access the resource. If the handle is not `null`, it means that you've obtained the lock and can safely access the resource.
`TryAcquireAsync` method gets the following parameters:
* `name` (`string`, required): Unique name of your lock. Different named locks are used to access different resources.
* `timeout` (`TimeSpan`): A timeout value to wait to obtain the lock. Default value is `TimeSpan.Zero`, which means it doesn't wait if the lock is already owned by another application.
* `cancellationToken`: A cancellation token that can be triggered later to cancel the operation.
### Using DistributedLock library's API
ABP's `IAbpDistributedLock` service is very limited and mainly designed to be internally used by the ABP Framework. For your own applications, you can use DistributedLock library's own API. See its [own documentation](https://github.com/madelson/DistributedLock) for details.
Loading…
Cancel
Save