首页 > Windows开发 > 详细

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

时间:2018-05-07 12:22:29      阅读:6699      评论:0      收藏:0      [点我收藏+]

标签:com   sca   sco   ria   namespace   serialize   表示   标识   怎么   

之前有写过一篇介绍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;
            }
        }
    }
}

 

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

标签:com   sca   sco   ria   namespace   serialize   表示   标识   怎么   

原文:https://www.cnblogs.com/axel10/p/9001800.html

(0)
(0)
   
举报
评论 一句话评论(0
© 2014 bubuko.com 版权所有 鲁ICP备09046678号-4
打开技术之扣,分享程序人生!
             

鲁公网安备 37021202000002号