c# redis 利用鎖(StackExchange.Redis LockTake)來保證數據在高並發情況下的正確性


之前有寫過一篇介紹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;
            }
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM