Skip to content

Commit

Permalink
Merge pull request #87 from Senparc/Develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
JeffreySu authored Apr 17, 2019
2 parents 641efd1 + f53a194 commit 4697bc2
Show file tree
Hide file tree
Showing 27 changed files with 1,522 additions and 142 deletions.
142 changes: 125 additions & 17 deletions src/Senparc.CO2NET.Cache.Memcached/MamcachedCacheLock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

using System;
using System.Threading;
using System.Threading.Tasks;
using Enyim.Caching.Memcached;
using Senparc.CO2NET.Cache;
using Senparc.CO2NET.Trace;
Expand All @@ -27,11 +28,11 @@ namespace Senparc.CO2NET.Cache.Memcached
public class MemcachedCacheLock : BaseCacheLock
{
private MemcachedObjectCacheStrategy _mamcachedStrategy;
public MemcachedCacheLock(MemcachedObjectCacheStrategy strategy, string resourceName, string key, int retryCount, TimeSpan retryDelay)
protected MemcachedCacheLock(MemcachedObjectCacheStrategy strategy, string resourceName, string key, int? retryCount, TimeSpan? retryDelay)
: base(strategy, resourceName, key, retryCount, retryDelay)
{
_mamcachedStrategy = strategy;
LockNow();//立即等待并抢夺锁
//LockNow();//立即等待并抢夺锁
}

private static Random _rnd = new Random();
Expand All @@ -41,40 +42,55 @@ private string GetLockKey(string resourceName)
return string.Format("{0}:{1}", "Lock", resourceName);
}

private bool RetryLock(string resourceName, int retryCount, TimeSpan retryDelay, Func<bool> action)
#region 同步方法

/// <summary>
/// 创建 MemcachedCacheLock 实例,并立即尝试获得锁
/// </summary>
/// <param name="strategy">MemcachedObjectCacheStrategy</param>
/// <param name="resourceName"></param>
/// <param name="key"></param>
/// <param name="retryCount"></param>
/// <param name="retryDelay"></param>
/// <returns></returns>
public static ICacheLock CreateAndLock(IBaseCacheStrategy strategy, string resourceName, string key, int? retryCount = null, TimeSpan? retryDelay = null)
{
return new MemcachedCacheLock(strategy as MemcachedObjectCacheStrategy, resourceName, key, retryCount, retryDelay).Lock();
}


private ICacheLock RetryLock(string resourceName, int retryCount, TimeSpan retryDelay, Func<bool> action)
{
int currentRetry = 0;
int maxRetryDelay = (int)retryDelay.TotalMilliseconds;
while (currentRetry++ < retryCount)
{
if (action())
{
return true;//取得锁
base.LockSuccessful = true;
return this;//取得锁
}
Thread.Sleep(_rnd.Next(maxRetryDelay));
}
return false;
return this;
}

public override bool Lock(string resourceName)
public override ICacheLock Lock()
{
return Lock(resourceName, 9999, new TimeSpan(0, 0, 0, 0, 20));
}

public override bool Lock(string resourceName, int retryCount, TimeSpan retryDelay)
{
var key = _mamcachedStrategy.GetFinalKey(resourceName);
var successfull = RetryLock(key, retryCount, retryDelay, () =>
var key = _mamcachedStrategy.GetFinalKey(_resourceName);
var lockResult = RetryLock(key, _retryCount, _retryDelay, () =>
{
try
{
var ttl = base.GetTotalTtl(retryCount, retryDelay);
var ttl = base.GetTotalTtl(_retryCount, _retryDelay);
if (_mamcachedStrategy.Cache.Store(StoreMode.Add, key, new object(), TimeSpan.FromMilliseconds(ttl)))
{
base.LockSuccessful = true;
return true;//取得锁
}
else
{
base.LockSuccessful = false;
return false;//已被别人锁住,没有取得锁
}
Expand All @@ -95,13 +111,105 @@ public override bool Lock(string resourceName, int retryCount, TimeSpan retryDel
}
}
);
return successfull;
return lockResult;
}

public override void UnLock(string resourceName)
public override void UnLock()
{
var key = _mamcachedStrategy.GetFinalKey(resourceName);
var key = _mamcachedStrategy.GetFinalKey(_resourceName);
_mamcachedStrategy.Cache.Remove(key);
}

#endregion

#region 异步方法
#if !NET35 && !NET40

/// <summary>
/// 【异步方法】创建 MemcachedCacheLock 实例,并立即尝试获得锁
/// </summary>
/// <param name="strategy">MemcachedObjectCacheStrategy</param>
/// <param name="resourceName"></param>
/// <param name="key"></param>
/// <param name="retryCount"></param>
/// <param name="retryDelay"></param>
/// <returns></returns>
public static async Task<ICacheLock> CreateAndLockAsync(IBaseCacheStrategy strategy, string resourceName, string key, int? retryCount = null, TimeSpan? retryDelay = null)
{
return await new MemcachedCacheLock(strategy as MemcachedObjectCacheStrategy, resourceName, key, retryCount, retryDelay).LockAsync();
}

private async Task<ICacheLock> RetryLockAsync(string resourceName, int retryCount, TimeSpan retryDelay, Func<Task<bool>> action)
{
int currentRetry = 0;
int maxRetryDelay = (int)retryDelay.TotalMilliseconds;
while (currentRetry++ < retryCount)
{
if (await action())
{
base.LockSuccessful = true;
return this;//取得锁
}
Thread.Sleep(_rnd.Next(maxRetryDelay));
}
return this;
}

public override async Task<ICacheLock> LockAsync()
{
var key = _mamcachedStrategy.GetFinalKey(_resourceName);
var lockResult = await RetryLockAsync(key, _retryCount, _retryDelay, async () =>
{
try
{
var ttl = base.GetTotalTtl(_retryCount, _retryDelay);
#if NET45
var storeResult = await Task.Factory.StartNew(() => _mamcachedStrategy.Cache.Store(StoreMode.Add, key, new object(), TimeSpan.FromMilliseconds(ttl)));
if (storeResult)
#else
if (await _mamcachedStrategy.Cache.StoreAsync(StoreMode.Add, key, new object(), TimeSpan.FromMilliseconds(ttl)))
#endif
{
base.LockSuccessful = true;
return true;//取得锁
}
else
{
base.LockSuccessful = false;
return false;//已被别人锁住,没有取得锁
}
//if (_mamcachedStrategy._cache.Get(key) != null)
//{
// return false;//已被别人锁住,没有取得锁
//}
//else
//{
// _mamcachedStrategy._cache.Store(StoreMode.set, key, new object(), new TimeSpan(0, 0, 10));//创建锁
// return true;//取得锁
//}
}
catch (Exception ex)
{
SenparcTrace.Log("Memcached同步锁发生异常:" + ex.Message);
return false;
}
}
);
return lockResult;
}

public override async Task UnLockAsync()
{
var key = _mamcachedStrategy.GetFinalKey(_resourceName);
#if NET45
await Task.Factory.StartNew(() => _mamcachedStrategy.Cache.Remove(key));
#else
await _mamcachedStrategy.Cache.RemoveAsync(key);
#endif
}

#endif
#endregion
}
}
Loading

0 comments on commit 4697bc2

Please sign in to comment.