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
453 lines
17 KiB
C#
453 lines
17 KiB
C#
/*
|
||
* 由SharpDevelop创建。
|
||
* 用户: Administrator
|
||
* 日期: 2018-09-14
|
||
* 时间: 15:16
|
||
*
|
||
* 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
|
||
*/
|
||
|
||
using System;
|
||
using StackExchange.Redis;
|
||
using System.Collections.Generic;
|
||
using MrWu.Debug;
|
||
using System.Linq;
|
||
using GameData;
|
||
using Server.Config;
|
||
|
||
namespace Server.DB.Redis
|
||
{
|
||
/// <summary>
|
||
/// 数据库类型
|
||
/// </summary>
|
||
public enum DbStyle
|
||
{
|
||
/// <summary>
|
||
/// 主库
|
||
/// </summary>
|
||
main,
|
||
|
||
/// <summary>
|
||
/// 比赛
|
||
/// </summary>
|
||
bisai
|
||
}
|
||
|
||
/// <summary>
|
||
/// redis数据库管理
|
||
/// </summary>
|
||
public class redisManager
|
||
{
|
||
/* redis 命令大全
|
||
* del key 删除键
|
||
* dump key 序列化key 返回序列化的值
|
||
* exists key 检查key是否存在
|
||
* exipire key seconds 设置过期的时间
|
||
* pexipire key milliseconds 设置过期时间毫秒
|
||
* keys keyspattem 查找给定格式的key
|
||
* move key db 将key移动到给定数据库db中
|
||
* persist key 移除key的过期时间
|
||
* pttl key 返回剩余过期时间以毫秒计
|
||
* ttl key 返回剩余的过期时间以秒计
|
||
* randomkey 随机返回一个key
|
||
* rename key newkey 修改key的名称
|
||
* renamenx key newkey 仅当newkey不存在时,将key改名为newkey
|
||
* type key 返回key所存储的值类型
|
||
*
|
||
* 字符串类型的命令
|
||
* set key value 设置key 字符串值
|
||
* get key 获取key的字符串值
|
||
* getrange key start end 获取key的字符串一段值
|
||
* getset key value 从新设置key的值 并返回原来的值
|
||
* getbit key offset ------
|
||
* strlen key 返回key存储的字符串长度
|
||
* mset key1 value1 key2 value2 设置一个或多个字符串的值
|
||
* msetnx key1 value1 key2 value2 设置一个活多个字符串的值不如果存在key则不设置
|
||
* setex key seconds value 将值value关联到key,并将key的过期时间设为seconds秒
|
||
* psetex key millseconds value 将value关联到key,并将key的过期时间设为milliseconds毫秒
|
||
* incr key 将key中存储的数字值增一 只能value是整数才能使用 并返回存储后的值
|
||
* incrby key increment 将key中存储的数字值增加increment 并返回存储后的值
|
||
* incrbyfloat key increment 将key中存储的数字值增加increment的浮点值 并返回存储后的值 存在误差
|
||
* decr key 将key中存储的数字减一 只有value是数字型的时候才能使用 并返回存储后的值
|
||
* decrby key decrement 将key中存储的数字值减少decrement 并返回存储后的值
|
||
* append key value 如果key已经存在并且是一个字符串 append 命令将指定的value追加到key原来的值的末尾 并返回追加后的字符串长度
|
||
*
|
||
* hash类型的命令
|
||
* hmset key hashkey1 value1 hashkey2 vlaue2 将新的hash字段插入到hash表中
|
||
* hget key hashkey 获取hash中的key
|
||
* hdel key hashkey1 hashkey2 删除一个或多个hash字段
|
||
* hexists key filed 查询哈希表中是否存在filed
|
||
* hgetall key 获取在哈希表中指定的key的所有字段和值
|
||
* hincrby key field increment 为哈希表中key 的值增加1
|
||
* hincrbyfloat key field increment 为哈希表中key 的值浮点值增量
|
||
* hkeys key 获取所有的哈希表中key值
|
||
* hlen key 获取哈希表中字段的数量
|
||
* hmget key field1 field2 获取给定字段的值
|
||
* hset key field vlaue 如果hash表中存在key则 修改key的值 如果不存在则添加
|
||
* hsernx key filed value 只有在hash表中不存在field字段时才设置值
|
||
* hvals key 获取hash表中的所有值
|
||
*
|
||
* List 列表类型命令
|
||
* lpush key value1 value2 将值插入到key列表中的头部
|
||
* blpop key key1 timeout 优先取key中的值如果key中有值返回第一个值 如果key中没有值取key1中的值 如果key1也没有值 则会等待timeout后超时
|
||
* brpop key key1 timeout 获取最后一个值
|
||
* brpoplpush source destination timeout 从source 中取出一个值并插入到destination 中 如果没有值知道timeout才停止
|
||
* lindex key index 通过索引获取表中的元素
|
||
* linsert key before value
|
||
* lpop key 移出并获取列表中的第一个元素
|
||
* lpush key value1 value2 将值插入到已存在key列表中的头部
|
||
* lpushx key value 将一个值插入到已存在key表中的头部
|
||
* lrange key start end 获取列表中指定范围的内的元素
|
||
* lrem key count value count>0表示从头向尾搜索,移除value相等的元素 数量为count count<0表示从尾巴向头搜索,移除value相等的元素 数量为count的绝对值 count = 0 时移除列表中所有的value相等的元素
|
||
* lset key index value 设置列表index上的值
|
||
* ltrim key satrt stop 指定列表保留的元素区间,不在区间内的元素将会被删除
|
||
* rpop key 移除并获取列表中的最后一个元素\
|
||
* rpoplpush source destination 移除source中的最后一个元素并将该元素添加到destination表中
|
||
* rpush key value1 value2 将值插入到列表的尾部
|
||
* rpushx key value 向已存在的表中添加值
|
||
*
|
||
* Set 集合命令
|
||
* sadd key menber1 menber2 向集合中添加一个或多个成员
|
||
* scard key 获取集合中的成员数量
|
||
* sdiff key key1 返回所有集合的差集
|
||
* sdiffstore destination key key1 返回给定所有集合的差集 并存储到destination 中
|
||
* sinter key key1 缩回所有集合的交集
|
||
* sindterstore destination key key1 返回所有集合的交集 并存储到destination中
|
||
* sismember key member 判断member元素是否是集合key的成员
|
||
* smemers key 返回集合中的所有成员
|
||
* smove source destination member 将member元素从source集合移动到destination集合中
|
||
* spop key 移除并返回集合中的一个随机元素
|
||
* srandmember key count 返回集合中的一个或多个随机元素
|
||
* serm key member member1 移除集合中的一个或多个成员
|
||
* sunion key key1 返回所有给定集合的并集
|
||
* sunionstore destination key1 key2 返回所有给定集合的并集并存储在destination集合中
|
||
* 迭代集合中的元素xxxx
|
||
*
|
||
* 有序集合
|
||
* zadd key score member1 socre1 member2 向有序集合添加一个或多个成员,或者更新已存在的成员的分数
|
||
* zcard key 获取有序集合的成员数量
|
||
* zcount key min max 计算在有序集合中指定区间分数的成员数
|
||
* zincrby key increment member 有序集合中对指定成员的分数加增量increment
|
||
* ---zinterstore destination numkeys key key1
|
||
* --zlexcount key min max 在有序集合中计算指定字典区间内成员数量
|
||
*
|
||
*
|
||
*
|
||
*
|
||
*
|
||
* */
|
||
|
||
|
||
/**
|
||
* 通配符 * 表示任意一个或多个字符
|
||
* ? 表示任意字符
|
||
* [abc] 表示方括号中任意一个字母
|
||
*
|
||
* */
|
||
private redisManager()
|
||
{
|
||
}
|
||
|
||
/// <summary>
|
||
/// 主redis 数据库连接
|
||
/// </summary>
|
||
private static RedisConnectionHelp mainDBConnection;
|
||
|
||
/// <summary>
|
||
/// 比赛redis 数据库连接
|
||
/// </summary>
|
||
private static RedisConnectionHelp bisaiDBConnection;
|
||
|
||
private static volatile bool isStart = false;
|
||
|
||
/// <summary>
|
||
/// redis操作数据库代理_逻辑数据库处理
|
||
/// </summary>
|
||
public static IDatabaseProxy db
|
||
{
|
||
get
|
||
{
|
||
if (isStart)
|
||
{
|
||
return new IDatabaseProxy(mainDBConnection.Instance.GetDatabase());
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// redis 操作数据库代理_逻辑数据库处理
|
||
/// </summary>
|
||
/// <param name="idx"></param>
|
||
/// <returns></returns>
|
||
public static IDatabaseProxy Getdb(int idx)
|
||
{
|
||
if (isStart)
|
||
return new IDatabaseProxy(mainDBConnection.Instance.GetDatabase(idx));
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取比赛数据库处理
|
||
/// </summary>
|
||
/// <param name="idx"></param>
|
||
/// <returns></returns>
|
||
public static IDatabaseProxy GetBiSaidb(int idx = -1)
|
||
{
|
||
if (isStart)
|
||
return new IDatabaseProxy(bisaiDBConnection.Instance.GetDatabase(idx));
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取数据库操作
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public static IDatabase GetDataBase(DbStyle sty = DbStyle.main, int idx = -1)
|
||
{
|
||
ConnectionMultiplexer cm = null;
|
||
switch (sty)
|
||
{
|
||
case DbStyle.main:
|
||
cm = mainDBConnection.Instance;
|
||
break;
|
||
case DbStyle.bisai:
|
||
cm = bisaiDBConnection.Instance;
|
||
break;
|
||
}
|
||
|
||
if (cm == null)
|
||
return null;
|
||
return cm.GetDatabase(idx);
|
||
}
|
||
|
||
public static List<RedisKey> Keys(string pattern, int dbidx, int pageSize = 1000, DbStyle sty = DbStyle.main)
|
||
{
|
||
if (!isStart) return null;
|
||
|
||
ConnectionMultiplexer cm = null;
|
||
switch (sty)
|
||
{
|
||
case DbStyle.main:
|
||
cm = mainDBConnection.Instance;
|
||
break;
|
||
case DbStyle.bisai:
|
||
cm = bisaiDBConnection.Instance;
|
||
break;
|
||
}
|
||
|
||
if (cm == null)
|
||
return null;
|
||
|
||
List<RedisKey> allkeys = new List<RedisKey>();
|
||
|
||
try
|
||
{
|
||
var points = cm.GetEndPoints();
|
||
if (points.Length < 1)
|
||
{
|
||
Debug.Error("redis 没有任何连接!");
|
||
return null;
|
||
}
|
||
|
||
IServer server = cm.GetServer(points[0]);
|
||
|
||
if (points.Length > 1)
|
||
{
|
||
ClusterConfiguration clusternodes = server.ClusterNodes();
|
||
foreach (var item in clusternodes.Nodes)
|
||
{
|
||
if (!item.IsSlave)
|
||
{
|
||
IServer temp = cm.GetServer(item.EndPoint);
|
||
IEnumerable<RedisKey> rks = temp.Keys(dbidx, pattern,pageSize);
|
||
foreach (RedisKey rk in rks)
|
||
{
|
||
allkeys.Add(rk);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
var rks = server.Keys(dbidx, pattern, pageSize);
|
||
|
||
foreach (var key in rks)
|
||
{
|
||
allkeys.Add(key);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.Error("查询错误asdsahdjk" + e.ToString());
|
||
return allkeys;
|
||
}
|
||
|
||
|
||
return allkeys;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 启动redis 服务器
|
||
/// </summary>
|
||
/// <param name="AllowAdmin">管理员模式</param>
|
||
public static void Start(bool AllowAdmin = false)
|
||
{
|
||
for (int i = 0; i < RedisConfigCategory.Instance.DataList.Count; i++)
|
||
{
|
||
var item = RedisConfigCategory.Instance.DataList[i];
|
||
switch (item.Name)
|
||
{
|
||
case "main":
|
||
mainDBConnection = new RedisConnectionHelp();
|
||
mainDBConnection.Start(item, AllowAdmin);
|
||
break;
|
||
case "bisai":
|
||
bisaiDBConnection = new RedisConnectionHelp();
|
||
bisaiDBConnection.Start(item, AllowAdmin);
|
||
break;
|
||
}
|
||
}
|
||
|
||
isStart = true;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// ConnectionMultiplexer对象管理帮助类__单例换多例
|
||
/// </summary>
|
||
public class RedisConnectionHelp
|
||
{
|
||
private readonly object Locker = new object();
|
||
private ConnectionMultiplexer _instance;
|
||
|
||
/// <summary>
|
||
/// 单例获取
|
||
/// </summary>
|
||
public ConnectionMultiplexer Instance
|
||
{
|
||
get
|
||
{
|
||
if (_instance == null)
|
||
{
|
||
lock (Locker)
|
||
{
|
||
if (_instance == null || !_instance.IsConnected)
|
||
{
|
||
//Debug.Error("获取新的实例!!!!");
|
||
_instance = GetManager();
|
||
}
|
||
}
|
||
}
|
||
|
||
return _instance;
|
||
}
|
||
}
|
||
|
||
RedisConfig redisConfig;
|
||
bool AllowAdmin;
|
||
|
||
/// <summary>
|
||
/// 启动redis
|
||
/// </summary>
|
||
/// <param name="redisConfig_"></param>
|
||
/// <param name="AllowAdmin_"></param>
|
||
public void Start(RedisConfig redisConfig_, bool AllowAdmin_ = false)
|
||
{
|
||
redisConfig = redisConfig_;
|
||
AllowAdmin = AllowAdmin_;
|
||
}
|
||
|
||
private ConnectionMultiplexer GetManager(string connectionString = null)
|
||
{
|
||
ConfigurationOptions options = new ConfigurationOptions();
|
||
|
||
options.ConnectTimeout = redisConfig.ConnectTimeOut;
|
||
options.AllowAdmin = AllowAdmin;
|
||
options.AbortOnConnectFail = false; //true 表示连接失败将不会创建链接实例
|
||
options.ConnectRetry = 5; //失败尝试重新链接的次数
|
||
|
||
options.EndPoints.Add(redisConfig.Host, redisConfig.Port);
|
||
|
||
ConnectionMultiplexer cml = ConnectionMultiplexer.Connect(options);
|
||
|
||
//redisPool.TimeoutMilliseconds = 3000;
|
||
|
||
cml.ConnectionFailed += MuxerConnectionFailed;
|
||
cml.ConnectionRestored += MuxerConnectionRestored;
|
||
cml.ErrorMessage += MuxerErrorMessage;
|
||
cml.ConfigurationChanged += MuxerConfigurationChanged;
|
||
cml.HashSlotMoved += MuxerHashSlotMoved;
|
||
cml.InternalError += MuxerInternalError;
|
||
|
||
return cml;
|
||
}
|
||
|
||
#region 事件
|
||
|
||
/// <summary>
|
||
/// 配置更改时
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void MuxerConfigurationChanged(object sender, EndPointEventArgs e)
|
||
{
|
||
Debug.Fatal("Configuration changed: " + e.EndPoint);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发生错误时
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void MuxerErrorMessage(object sender, RedisErrorEventArgs e)
|
||
{
|
||
Debug.Fatal("ErrorMessage: " + e.Message);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重新建立连接之前的错误
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e)
|
||
{
|
||
Debug.Fatal("ConnectionRestored: " + e.EndPoint);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 连接失败 , 如果重新连接成功你将不会收到这个通知
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e)
|
||
{
|
||
Debug.Fatal("重新连接:Endpoint failed: " + e.EndPoint + ", " + e.FailureType +
|
||
(e.Exception == null ? "" : (", " + e.Exception.Message)));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更改集群
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e)
|
||
{
|
||
Debug.Fatal("HashSlotMoved:NewEndPoint" + e.NewEndPoint + ", OldEndPoint" + e.OldEndPoint);
|
||
}
|
||
|
||
/// <summary>
|
||
/// redis类库错误
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void MuxerInternalError(object sender, InternalErrorEventArgs e)
|
||
{
|
||
Debug.Fatal("InternalError:Message" + e.Exception.Message);
|
||
}
|
||
|
||
#endregion 事件
|
||
}
|
||
} |