feat: initial commit - HJHA game server full source
6 major server modules (PdkFriendServer/GlobalSever/ServerCore/GameModule/GameNetModule) + game logic (GameFix/GameDAL/ServerData) + network layer (NetWorkMessage) + data layer (ObjectModel) + utilities (MrWu/Core/Config/CloudAPI/dll) + adapters (zyxAdapter/base) .NET 8.0 C# solution, 16 projects, 958 source files
This commit is contained in:
314
GameDAL/db/redis/DistributedLock.cs
Normal file
314
GameDAL/db/redis/DistributedLock.cs
Normal file
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* 由SharpDevelop创建。
|
||||
* 用户: Administrator
|
||||
* 日期: 2018-10-24
|
||||
* 时间: 9:56
|
||||
*
|
||||
* 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
|
||||
*/
|
||||
using System;
|
||||
using System.Threading;
|
||||
using MrWu.Debug;
|
||||
using Server.DB.Redis;
|
||||
using StackExchange.Redis;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Server.DB.Redis
|
||||
{
|
||||
/// <summary>
|
||||
/// 分布式锁
|
||||
/// </summary>
|
||||
public class DistributedLock{
|
||||
|
||||
/// <summary>
|
||||
/// 最大等待数量
|
||||
/// </summary>
|
||||
private readonly int maxWaitCnt;
|
||||
|
||||
/// <summary>
|
||||
/// 锁的钥匙
|
||||
/// </summary>
|
||||
private readonly string[] lockKey;
|
||||
|
||||
/// <summary>
|
||||
/// 下一个锁的位置
|
||||
/// </summary>
|
||||
private int nextid = -1;
|
||||
|
||||
/// <summary>
|
||||
/// 读写锁
|
||||
/// </summary>
|
||||
private readonly ReaderWriterLockSlim rwls = new ReaderWriterLockSlim();
|
||||
|
||||
private volatile IDatabaseProxy m_db;
|
||||
|
||||
/// <summary>
|
||||
/// 操作线程锁数据库
|
||||
/// </summary>
|
||||
private IDatabaseProxy db{
|
||||
get{
|
||||
if(m_db == null)
|
||||
m_db = redisManager.db;
|
||||
return m_db;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建分布式锁
|
||||
/// </summary>
|
||||
/// <param name="waitMaxCnt">最大等待数量</param>
|
||||
public DistributedLock(int waitMaxCnt){
|
||||
maxWaitCnt = waitMaxCnt;
|
||||
lockKey = new string[maxWaitCnt];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加锁
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
private int AddKey(string key){
|
||||
while(true){
|
||||
rwls.EnterWriteLock();
|
||||
try{
|
||||
nextid++;
|
||||
if(nextid >= maxWaitCnt)
|
||||
nextid = 0;
|
||||
if(lockKey[nextid] == null){
|
||||
lockKey[nextid] = key;
|
||||
return nextid;
|
||||
}
|
||||
}finally{
|
||||
rwls.ExitWriteLock();
|
||||
}
|
||||
//SpinWait sw = new SpinWait();
|
||||
//sw.SpinOnce();
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除锁
|
||||
/// </summary>
|
||||
/// <param name="idx"></param>
|
||||
/// <returns></returns>
|
||||
private void RemoveKey(int idx){
|
||||
rwls.EnterWriteLock();
|
||||
try{
|
||||
lockKey[idx] = null;
|
||||
}finally{
|
||||
rwls.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取钥匙
|
||||
/// </summary>
|
||||
/// <param name="idx"></param>
|
||||
/// <returns></returns>
|
||||
private string GetKey(int idx){
|
||||
rwls.EnterReadLock();
|
||||
try{
|
||||
return lockKey[idx];
|
||||
}finally{
|
||||
rwls.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 为锁续航
|
||||
/// </summary>
|
||||
/// <param name="state"></param>
|
||||
private void AddLockLife(object state){
|
||||
Task.Factory.StartNew(()=>{
|
||||
int idx = (int)state;
|
||||
string key = GetKey(idx);
|
||||
|
||||
while(true){
|
||||
Thread.Sleep(1000);
|
||||
if(key == GetKey(idx) && key != null){
|
||||
string strtimeOut = db.StringGet(key);
|
||||
if(strtimeOut != null){
|
||||
int timeOut;
|
||||
if(int.TryParse(strtimeOut,out timeOut))
|
||||
db.KeyExpire(key,new TimeSpan(0,0,timeOut));
|
||||
else
|
||||
Debug.Error("不可能的错误存储的值不是数字anckjnsakjbdnja,"+strtimeOut + "," + key);
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}else
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试运行
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <param name="action">事件</param>
|
||||
/// <param name="timeOut">key超时时间</param>
|
||||
/// <param name="tryTimeOut">尝试超时时间</param>
|
||||
/// <returns>是否运行</returns>
|
||||
public bool TryLockRun(string key,Action action,int timeOut,int tryTimeOut = 0){
|
||||
if(key == null){
|
||||
Debug.Error("key不能为null");
|
||||
return false;
|
||||
}
|
||||
key = key+".lock";
|
||||
TimeSpan tm = new TimeSpan(0,0,timeOut);
|
||||
DateTime lastTime = DateTime.Now;
|
||||
//SpinWait sw = new SpinWait();
|
||||
while(!db.StringSet(key,timeOut,tm,When.NotExists)){
|
||||
if((DateTime.Now - lastTime).TotalMilliseconds >= tryTimeOut)
|
||||
return false;
|
||||
//sw.SpinOnce();
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
|
||||
//Debug.Log("运算开始:" + key + "," + DateTime.Now.Millisecond.ToString());
|
||||
Exception ex = null;
|
||||
int idx = AddKey(key);
|
||||
try{
|
||||
AddLockLife(idx);
|
||||
if(action != null)
|
||||
action();
|
||||
}catch(Exception e){
|
||||
Debug.Error("处理出错:" + e.ToString());
|
||||
ex = e;
|
||||
}finally{
|
||||
RemoveKey(idx);
|
||||
//Debug.Log("运算结束:" + key + "," + DateTime.Now.Millisecond.ToString());
|
||||
db.KeyDelete(key);
|
||||
if(ex != null)
|
||||
throw ex;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试运行
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <param name="func">事件</param>
|
||||
/// <param name="timeOut">timeOut</param>
|
||||
/// <param name="result">返回结果</param>
|
||||
/// <param name="tryTimeOut">尝试超时时间</param>
|
||||
/// <returns>是否运行</returns>
|
||||
public bool TryLockRun<T>(string key,Func<T> func,int timeOut,out T result,int tryTimeOut = 0){
|
||||
result = default(T);
|
||||
if(key == null){
|
||||
Debug.Error("key不能为null");
|
||||
return false;
|
||||
}
|
||||
|
||||
key = key + ".lock";
|
||||
TimeSpan tm = new TimeSpan(0,0,timeOut);
|
||||
DateTime lastTime = DateTime.Now;
|
||||
//SpinWait sw = new SpinWait();
|
||||
while(!db.StringSet(key,timeOut,tm,When.NotExists)){
|
||||
if((DateTime.Now - lastTime).TotalMilliseconds >= tryTimeOut)
|
||||
return false;
|
||||
//sw.SpinOnce();
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
|
||||
Exception ex = null;
|
||||
int idx = AddKey(key);
|
||||
try{
|
||||
AddLockLife(idx);
|
||||
if(func != null)
|
||||
result = func();
|
||||
}catch(Exception e){
|
||||
ex = e;
|
||||
Debug.Error("处理出错:" + e.ToString());
|
||||
}finally{
|
||||
RemoveKey(idx);
|
||||
Debug.Log("运算结束:" + key + "," + DateTime.Now.Millisecond.ToString());
|
||||
db.KeyDelete(key);
|
||||
if(ex != null)
|
||||
throw ex;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加锁运行
|
||||
/// </summary>
|
||||
public void LockRun(string key,Action action,int timeOut = 3){
|
||||
if(key == null){
|
||||
Debug.Error("key不能为null");
|
||||
return;
|
||||
}
|
||||
key = key+".lock";
|
||||
TimeSpan tm = new TimeSpan(0,0,timeOut);
|
||||
//SpinWait sw = new SpinWait();
|
||||
while(!db.StringSet(key,timeOut,tm,When.NotExists)){
|
||||
//sw.SpinOnce();
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
|
||||
Exception ex = null;
|
||||
|
||||
int idx = AddKey(key);
|
||||
try{
|
||||
AddLockLife(idx);
|
||||
|
||||
if(action != null)
|
||||
action();
|
||||
|
||||
}catch(Exception e){
|
||||
ex = e;
|
||||
}finally{
|
||||
RemoveKey(idx);
|
||||
db.KeyDelete(key);
|
||||
if(ex != null)
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加锁运行
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="func"></param>
|
||||
/// <param name="timeOut">超时时间</param>
|
||||
/// <returns></returns>
|
||||
public T LockRun<T>(string key,Func<T> func,int timeOut = 3){
|
||||
T result = default(T);
|
||||
if(key == null){
|
||||
Debug.Error("key不能为null");
|
||||
return result;
|
||||
}
|
||||
|
||||
key = key + ".lock";
|
||||
TimeSpan tm = new TimeSpan(0,0,timeOut);
|
||||
//SpinWait sw = new SpinWait();
|
||||
|
||||
while(!db.StringSet(key,timeOut,tm,When.NotExists)){
|
||||
//sw.SpinOnce();
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
|
||||
Exception ex = null;
|
||||
int idx = AddKey(key);
|
||||
try{
|
||||
AddLockLife(idx);
|
||||
|
||||
if(func != null)
|
||||
result = func();
|
||||
|
||||
}catch(Exception e){
|
||||
ex = new Exception("lockRun error :" , e);
|
||||
}finally{
|
||||
RemoveKey(idx);
|
||||
db.KeyDelete(key);
|
||||
if(ex != null)
|
||||
throw ex;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user