标签:Console Distributed Redis connection WriteLine lock var public taskInfo
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace RedisDemo
{
class Program
{
static void Main(string[] args)
{
TestRedisLockWithFencingToken();
Console.ReadKey();
}
public static List<int> SLEEP_OF_SECONDS = new List<int> { 20, 0, 0, 10, 10 };
public static void TestRedisLockWithFencingToken()
{
var tasks = new List<Task>();
var mockService = new MockService();
Enumerable.Range(1, 3).ToList().ForEach(it =>
{
var task = Task.Run(() =>
{
var taskId = $"task_{it}";
var lockHelper = new RedisLockHelper();
var lockKey = "article:1";
try
{
Console.WriteLine($"-> {taskId} begin acquire redis lock.");
var result = lockHelper.GetLock(lockKey, TimeSpan.FromSeconds(10));
if (result.Success)
{
var taskInfo = new TaskInfo { TaskId = taskId, FencingToken = result.FencingToken ?? 0 };
Console.WriteLine($"-> {taskId} acquire lock success {taskInfo}.");
var sleepOfSeconds = SLEEP_OF_SECONDS[it - 1];
Thread.Sleep(sleepOfSeconds * 1000);
mockService.Save(taskInfo);
Console.WriteLine($"{taskInfo} Done");
}
}
catch (Exception ex)
{
Console.WriteLine($"{taskId} {ex.Message}");
}
finally
{
lockHelper.ReleaseLock("article:1");
}
});
tasks.Add(task);
});
try
{
Task.WaitAll(tasks.ToArray());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
}
}
public class TaskInfo
{
public long FencingToken { get; set; }
public string TaskId { get; set; }
public override string ToString()
{
return $"TaskId: {TaskId} - FencingToken: {FencingToken}";
}
}
public class MockService
{
private IConnectionMultiplexer connection;
private String fencingTokenKey = "redis_fencingToken";
public MockService()
{
this.Initialize();
}
private void Initialize()
{
connection = ConnectionMultiplexer.Connect("localhost");
}
public void Close()
{
if (connection != null)
{
connection.Close();
}
}
public void Save(TaskInfo taskInfo)
{
Console.WriteLine($"MockService#Save: {taskInfo}");
var fencingToken = taskInfo.FencingToken;
var serverFencingToken = connection.GetDatabase().StringGet(fencingTokenKey);
Console.WriteLine($"MockService#Save: {taskInfo} - Server Fencing Token {serverFencingToken}");
if (serverFencingToken.HasValue)
{
if (fencingToken == (long)serverFencingToken)
{
Console.WriteLine($"MockService#Save: {taskInfo} Save Success.");
}
else
{
Console.WriteLine($"MockService#Save: {taskInfo} Save Failure, Fencingtoken not equal server token.");
}
}
else
{
Console.WriteLine($"{taskInfo} Save error");
}
}
}
public class RedisLockResult
{
public bool Success { get; set; }
public long? FencingToken { get; set; }
}
public class RedisLockHelper : IDisposable
{
private IConnectionMultiplexer connection;
private String value;
private String fencingTokenKey = "redis_fencingToken";
public RedisLockHelper()
{
value = Guid.NewGuid().ToString();
this.Initialize();
}
public RedisLockResult GetLock(String key, TimeSpan expiry)
{
var db = connection.GetDatabase();
var lockSuccess = db.StringSet(key, value, expiry, When.NotExists, CommandFlags.None);
var start = DateTime.Now;
while (!lockSuccess)
{
Thread.Sleep(50);
lockSuccess = db.StringSet(key, value, expiry, When.NotExists, CommandFlags.None);
start = start.AddMilliseconds(50);
if (DateTime.Now.Subtract(start).TotalSeconds > 20)
{
throw new InvalidOperationException($"can not acquire distributed lock");
}
}
var result = new RedisLockResult()
{
Success = lockSuccess
};
if (lockSuccess)
{
var fencingToken = db.StringIncrement(fencingTokenKey, 1, CommandFlags.None);
result.FencingToken = fencingToken;
}
return result;
}
public void ReleaseLock(RedisKey key)
{
var lua = @"if redis.call('get', @key) == @value then
return redis.call('del', @key)
else
return 0
end";
var db = connection.GetDatabase();
var prepare = LuaScript.Prepare(lua);
var result = db.ScriptEvaluate(prepare, new { key = key, value = value });
}
private void Initialize()
{
connection = ConnectionMultiplexer.Connect("localhost");
}
public void Dispose()
{
if (connection != null)
{
connection.Dispose();
}
}
}
}
标签:Console,Distributed,Redis,connection,WriteLine,lock,var,public,taskInfo 来源: https://www.cnblogs.com/byxxw/p/11344463.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。