c# redis 利用锁(StackExchange.Redis LockTake)来保证数据在高并发情况下的正确性

2018/05/07 11:35
阅读数 1.3K

之前有写过一篇介绍c#操作redis的文章 http://www.cnblogs.com/axel10/p/8459434.html ,这篇文章中的案例使用了StringIncrement来实现了高并发情况下key值的稳定增加,但如果要用锁的方式而不是StringIncrement方法,那该怎么做呢?

 

LockTake涉及到三个参数:key,token和TimeSpan,分别表示redis数据库中该锁的名称、锁的持有者标识和有效时间。下面将用一个多线程增加key值的案例来演示LockTake/LockRelease的用法。

 

using StackExchange.Redis;
using StackExchange.Redis.Extensions.Core;
using StackExchange.Redis.Extensions.Core.Configuration;
using StackExchange.Redis.Extensions.Newtonsoft;
using System;
using System.Threading;

namespace RedisTest
{
    class Program
    {
        static RedisValue Token = Environment.MachineName;
        static RedisKey Key = "lock";

        static void Ins()
        {
            Thread thread = new Thread(() =>
            {
                for (int i = 0; i < 100; i++)
                {

                    if (client.Database.LockTake(Key, Token, TimeSpan.MaxValue))   //key表示的是redis数据库中该锁的名称,不可重复。 Token用来标识谁拥有该锁并用来释放锁。TimeSpan表示该锁的有效时间。
                    {
                        try
                        {
                            int key = client.Get<int>("key");

                            client.Add("key", key + 10);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e);
                            throw;
                        }
                        finally
                        {
                            client.Database.LockRelease(Key, Token);
                        }
                    }
                    else
                    {
                        Console.WriteLine("locking");
                        while (!TryAgain(10))
                        {
                            Thread.Sleep(1);
                        }
                    }
                }
            });
            thread.Start();
        }

        private static StackExchangeRedisCacheClient client;


        static void Main(string[] args)
        {
            var redisConfiguration = new RedisConfiguration() //配置
            {
                Hosts = new RedisHost[]
                {
                    new RedisHost() {Host = "127.0.0.1", Port = 6379}
                }
            };


            client = new StackExchangeRedisCacheClient(new NewtonsoftSerializer(), redisConfiguration);
            client.Add("key", 0);

            for (int j = 0; j < 10; j++)
            {
                Ins();
            }

            Thread.Sleep(2000);

            int i = client.Get<int>("key");
            Console.WriteLine(i);
            Console.ReadKey();
        }

        static bool TryAgain(int value)
        {
            if (client.Database.LockTake(Key, Token, TimeSpan.MaxValue))
            {
                try
                {
                    int key = client.Get<int>("key");

                    client.Add("key", key + value);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
                finally
                {
                    client.Database.LockRelease(Key, Token);
                }

                return true;
            }
            else
            {
                return false;
            }
        }
    }
}

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部