分布式事务锁的实现-consul

Session的介绍

consul的session代表了具有非常规具体语义的contract(就是一种契约,或者说规则,不是咱们常规理解的会话)。 当构建session时,可以提供节点名称,健康检查列表,行为,TTL和lock-delay 。 新建的session中提供了一个可以用来识别它的命名ID。 该ID可与KV存储一起使用以获取锁定:相互排斥的咨询机制。

 

基于Consul的分布式锁主要利用Key/Value存储API中的acquire和release操作来实现。acquire和release操作是类似Check-And-Set的操作:

acquire操作只有当锁不存在持有者时才会返回true,并且set设置的Value值,同时执行操作的session会持有对该Key的锁,否则就返回false
release操作则是使用指定的session来释放某个Key的锁,如果指定的session无效,那么会返回false,否则就会set设置Value值,并返回true

 注意:锁是有生命周期,它的生命周期是与session的生命周期一致 因此对于锁的持有者,它需要周期性的执行renew session,以确保session关联的锁不被释放。

分布式事务锁实现的流程

C#实现的代码示例:

注意先在nuget中安装包Consul,然后在编码。

using Consul;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsulClientTest
{
    class LockHelper
    {
        private ConsulClient client;
        private string sessionId;
        string lockKey = "mylock";
        public LockHelper()
        {
            client = new ConsulClient();
        }
        public async Task<bool> GetLock()
        {
            SessionEntry se = new SessionEntry()
            {
                LockDelay = new TimeSpan(0, 0, 0, 0, 0)//表示session删除后不要延迟,对应的KV要能够让别的字段立即使用。
            };
            sessionId = (await client.Session.Create(se)).Response;

            var p = new KVPair(lockKey)
            {
                Value = Encoding.UTF8.GetBytes("Hello MyLock.我的自定义:" + DateTime.Now.ToString()),
                Session = sessionId
            };
            await client.KV.Put(p);
            while (true)
            {
                var rs = (await client.KV.Acquire(p)).Response;
                if (rs)
                {
                    return true;
                }
                else
                {
                    continue;
                }
            }
        }
        /// <summary>
        /// 释放session
        /// </summary>
        /// <returns></returns>
        public async Task DelLock()
        {
            await client.Session.Destroy(sessionId);
        }
    }
}

 测试代码:

        static void Main(string[] args)
        {

            for (int i = 0; i < 10; i++)
            {
                Task t = new Task(async r => DoTask((string)r), i.ToString());
                t.Start();
            }
            Console.WriteLine("Hello World!");
            Console.ReadLine();

        }


        private async static void DoTask(string str)
        {
            Console.WriteLine("我是"+str+"号,准备获取Lock。");
            LockHelper lh = new LockHelper();
            var myLock = await lh.GetLock();
            if (myLock)
            {
                Console.WriteLine(str + "号得到了锁");
            }
            await lh.DelLock();
            Console.WriteLine("我是" + str + "号,已经释放Lock。");
        }

特点分析

还是没有解决“锁的拥有者”[长时间执行超时问题]或者[服务器宕机]造成无法解锁的问题。

 其他语言对consul分布式锁的实现:golang分布式事务锁的实现

Consul包实用示例:consuldotnet源码以及使用方法

 

添加评论

Loading