You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
427 lines
13 KiB
427 lines
13 KiB
/*
|
|
作用: redis操作类
|
|
时间: 2023.06.09
|
|
作者: evangeyu
|
|
说明:
|
|
导出所有redis相关操作
|
|
|
|
使用约束:
|
|
1. 不允许大key,key命名包含唯一id: 数据库功能:类型:唯一id1 : 唯一id2:.... = 数据 如:AccountInfo:string:accountType:accountType = "xxx"
|
|
2. key禁止包含特殊字符,如空格、换行、单双引号以及其他转义字符
|
|
3. 如果是String类型,单个value大小控制10k以内
|
|
4. hash、list、set、zset类型,元素个数一般不超过5000
|
|
*/
|
|
|
|
|
|
using System;
|
|
using StackExchange.Redis;
|
|
using Newtonsoft.Json;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Sog
|
|
{
|
|
public class RedisDB
|
|
{
|
|
private string m_dbName;
|
|
private string m_ip;
|
|
private static ConfigurationOptions m_connectConfig = null;
|
|
private static ConnectionMultiplexer m_redisConn = null;
|
|
private IDatabase m_redisDB
|
|
{
|
|
get
|
|
{
|
|
return m_redisConn.GetDatabase();
|
|
}
|
|
}
|
|
|
|
public RedisDB(string dbname, string ip, string password)
|
|
{
|
|
m_ip = ip;
|
|
m_dbName = dbname;
|
|
|
|
m_connectConfig = ConfigurationOptions.Parse(string.Format("{0},password={1}", ip, password));
|
|
m_connectConfig.CommandMap = CommandMap.Create(new HashSet<string> { "SUBSCRIBE" }, false); // 禁用订阅功能
|
|
|
|
try
|
|
{
|
|
m_redisConn = ConnectionMultiplexer.Connect(m_connectConfig);
|
|
RegisterEvent();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
TraceLog.Error("connect redis ip {0} error!", m_ip);
|
|
TraceLog.Exception(ex);
|
|
|
|
TraceLog.Error("Inner exception:");
|
|
TraceLog.Exception(ex.InnerException);
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (m_redisConn != null)
|
|
{
|
|
m_redisConn.Close(true);
|
|
m_redisConn.Dispose();
|
|
m_redisConn = null;
|
|
}
|
|
}
|
|
|
|
public TimeSpan Ping()
|
|
{
|
|
return m_redisDB.Ping();
|
|
}
|
|
|
|
public string CreateKey(string name, params string[] ids)
|
|
{
|
|
if (ids == null)
|
|
{
|
|
return string.Format("{0}:{1}", m_dbName, name);;
|
|
}
|
|
|
|
return string.Format("{0}:{1}:{2}", m_dbName, name, string.Join(":", ids));
|
|
}
|
|
|
|
|
|
//----------------------------------------- 序列化
|
|
|
|
public static string ConvertToStr<T>(T value)
|
|
{
|
|
return value is string ? value.ToString() : JsonConvert.SerializeObject(value);
|
|
}
|
|
|
|
public static T ConvertToObj<T>(string value)
|
|
{
|
|
if (string.IsNullOrEmpty(value))
|
|
{
|
|
return default(T);
|
|
}
|
|
else
|
|
{
|
|
return JsonConvert.DeserializeObject<T>(value);
|
|
}
|
|
}
|
|
|
|
private static List<T> ConvetList<T>(RedisValue[] values)
|
|
{
|
|
List<T> result = new List<T>();
|
|
foreach (var item in values)
|
|
{
|
|
var model = ConvertToObj<T>(item);
|
|
if (model != null)
|
|
result.Add(model);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
//----------------------------------------- String
|
|
|
|
public bool StringSet<T>(string redisKey, T obj)
|
|
{
|
|
return m_redisDB.StringSet(redisKey, ConvertToStr(obj));
|
|
}
|
|
|
|
public T StringGet<T>(string redisKey)
|
|
{
|
|
return ConvertToObj<T>(m_redisDB.StringGet(redisKey));
|
|
}
|
|
|
|
public long StringIncrement(string redisKey)
|
|
{
|
|
return m_redisDB.StringIncrement(redisKey);
|
|
}
|
|
|
|
public async Task<bool> StringSetAsync<T>(string redisKey, T obj)
|
|
{
|
|
return await m_redisDB.StringSetAsync(redisKey, ConvertToStr(obj));
|
|
}
|
|
public async Task<T> StringGetAsync<T>(string redisKey)
|
|
{
|
|
return ConvertToObj<T>(await m_redisDB.StringGetAsync(redisKey));
|
|
}
|
|
|
|
//----------------------------------------- Hash
|
|
|
|
public void HashSetPart(string redisKey, IEnumerable<HashEntry> hashFields)
|
|
{
|
|
m_redisDB.HashSet(redisKey, hashFields.ToArray());
|
|
}
|
|
|
|
public RedisValue[] HashGetPart(string redisKey, RedisValue[] hashField)
|
|
{
|
|
return m_redisDB.HashGet(redisKey, hashField);
|
|
}
|
|
|
|
public bool HashSet<T>(string redisKey, string hashField, T value)
|
|
{
|
|
return m_redisDB.HashSet(redisKey, hashField, ConvertToStr(value));
|
|
}
|
|
|
|
public T HashGet<T>(string redisKey, string hashField)
|
|
{
|
|
return ConvertToObj<T>(m_redisDB.HashGet(redisKey, hashField));
|
|
}
|
|
|
|
public HashEntry[] HashGetAll(string redisKey)
|
|
{
|
|
return m_redisDB.HashGetAll(redisKey);
|
|
}
|
|
|
|
public async Task<T> HashGetAsync<T>(string redisKey, string hashField)
|
|
{
|
|
return ConvertToObj<T>(await m_redisDB.HashGetAsync(redisKey, hashField));
|
|
}
|
|
public async Task<bool> HashSetAsync<T>(string redisKey, string hashField, T value)
|
|
{
|
|
return await m_redisDB.HashSetAsync(redisKey, hashField, ConvertToStr(value));
|
|
}
|
|
|
|
|
|
//----------------------------------------- List
|
|
|
|
public string ListLeftPop(string redisKey)
|
|
{
|
|
return m_redisDB.ListLeftPop(redisKey);
|
|
}
|
|
|
|
public string ListRightPop(string redisKey)
|
|
{
|
|
return m_redisDB.ListRightPop(redisKey);
|
|
}
|
|
|
|
public long ListRemove(string redisKey, string redisValue, long count = 0)
|
|
{
|
|
return m_redisDB.ListRemove(redisKey, redisValue, count);
|
|
}
|
|
|
|
public void ListTrim(string redisKey, long start, long stop)
|
|
{
|
|
m_redisDB.ListTrim(redisKey, start, stop);
|
|
}
|
|
|
|
public void ListMaxLen(string redisKey, long maxLen)
|
|
{
|
|
ListTrim(redisKey, 0, maxLen > 0 ? (maxLen - 1) : -1);
|
|
}
|
|
|
|
public long ListRightPush(string redisKey, string redisValue)
|
|
{
|
|
return m_redisDB.ListRightPush(redisKey, redisValue);
|
|
}
|
|
|
|
public long ListLeftPush(string redisKey, string redisValue)
|
|
{
|
|
return m_redisDB.ListLeftPush(redisKey, redisValue);
|
|
}
|
|
|
|
public long ListLength(string redisKey)
|
|
{
|
|
return m_redisDB.ListLength(redisKey);
|
|
}
|
|
|
|
public IEnumerable<RedisValue> ListRange(string redisKey, int startRow=0, int endRow=-1)
|
|
{
|
|
return m_redisDB.ListRange(redisKey, startRow, endRow);
|
|
}
|
|
|
|
public long ListRightPush<T>(string redisKey, T value)
|
|
{
|
|
return m_redisDB.ListRightPush(redisKey, ConvertToStr(value));
|
|
}
|
|
|
|
public long ListLeftPush<T>(string redisKey, T value)
|
|
{
|
|
return m_redisDB.ListLeftPush(redisKey, ConvertToStr(value));
|
|
}
|
|
|
|
public List<T> ListRange<T>(string redisKey, int startRow=0, int endRow=-1)
|
|
{
|
|
return ConvetList<T>(ListRange(redisKey, startRow, endRow).ToArray());
|
|
}
|
|
|
|
|
|
//----------------------------------------- Set
|
|
|
|
public bool SetAdd(string redisKey, string member)
|
|
{
|
|
return m_redisDB.SetAdd(redisKey, member);
|
|
}
|
|
|
|
public long SetAdd(string redisKey, RedisValue[] members)
|
|
{
|
|
return m_redisDB.SetAdd(redisKey, members);
|
|
}
|
|
|
|
public long SetLength(string redisKey)
|
|
{
|
|
return m_redisDB.SetLength(redisKey);
|
|
}
|
|
|
|
public bool SetRemove(string redisKey, string memebr)
|
|
{
|
|
return m_redisDB.SetRemove(redisKey, memebr);
|
|
}
|
|
|
|
public bool SetAdd<T>(string redisKey, T member)
|
|
{
|
|
return m_redisDB.SetAdd(redisKey, ConvertToStr(member));
|
|
}
|
|
|
|
public RedisValue[] SetMembers(string redisKey)
|
|
{
|
|
return m_redisDB.SetMembers(redisKey);
|
|
}
|
|
|
|
|
|
//----------------------------------------- SortedSet
|
|
|
|
public bool ZSetAdd(string redisKey, string member, double score)
|
|
{
|
|
return m_redisDB.SortedSetAdd(redisKey, member, score);
|
|
}
|
|
|
|
public IEnumerable<RedisValue> ZSetRangeByRank(string redisKey)
|
|
{
|
|
return m_redisDB.SortedSetRangeByRank(redisKey);
|
|
}
|
|
|
|
public long ZSetLength(string redisKey)
|
|
{
|
|
return m_redisDB.SortedSetLength(redisKey);
|
|
}
|
|
|
|
public bool ZSetRemove(string redisKey, string memebr)
|
|
{
|
|
return m_redisDB.SortedSetRemove(redisKey, memebr);
|
|
}
|
|
|
|
public bool ZSetAdd<T>(string redisKey, T member, double score)
|
|
{
|
|
return m_redisDB.SortedSetAdd(redisKey, ConvertToStr(member), score);
|
|
}
|
|
|
|
public IEnumerable<SortedSetEntry> ZSetScan(string redisKey, string pattern, int pageSize = 250, long cursor = 0, int pageOffset = 0)
|
|
{
|
|
return m_redisDB.SortedSetScan(redisKey, pattern, pageSize, cursor, pageOffset);
|
|
}
|
|
|
|
|
|
//----------------------------------------- 操作key
|
|
|
|
public bool KeyDelete(string redisKey)
|
|
{
|
|
return m_redisDB.KeyDelete(redisKey);
|
|
}
|
|
|
|
public long KeyDelete(IEnumerable<string> redisKeys)
|
|
{
|
|
var keys = redisKeys.Select(x => (RedisKey)x);
|
|
return m_redisDB.KeyDelete(keys.ToArray());
|
|
}
|
|
|
|
public bool KeyExists(string redisKey)
|
|
{
|
|
return m_redisDB.KeyExists(redisKey);
|
|
}
|
|
|
|
public bool KeyRename(string redisKey, string redisNewKey)
|
|
{
|
|
return m_redisDB.KeyRename(redisKey, redisNewKey);
|
|
}
|
|
|
|
public bool KeyExpire(string redisKey, TimeSpan? expiry)
|
|
{
|
|
return m_redisDB.KeyExpire(redisKey, expiry);
|
|
}
|
|
|
|
|
|
//----------------------------------------- keys scan
|
|
|
|
// 注意:这个底层可能使用了keys 和 scan两种命令
|
|
// pattern : 支持通配符 (*:任意字符;?:单个任意字符;[ab]:指定范围内的字符)
|
|
public IEnumerable<RedisKey> Keys(RedisValue _pattern = default)
|
|
{
|
|
var server = m_redisConn.GetServer(m_ip);
|
|
return server.Keys(pattern: _pattern);
|
|
}
|
|
|
|
// pattern : 支持通配符 (*:任意字符;?:单个任意字符;[ab]:指定范围内的字符)
|
|
public long Scan(ref IEnumerable<RedisKey> result, string _pattern, long cursor = 0, int count = 100)
|
|
{
|
|
var redisResults = (RedisResult[])m_redisDB.Execute("scan", cursor, "MATCH", _pattern, "COUNT", count);
|
|
result = (RedisKey[])redisResults[1];
|
|
return (long)redisResults[0];
|
|
}
|
|
|
|
//----------------------------------------- pipleline 批处理
|
|
|
|
public IBatch CreateBatch()
|
|
{
|
|
return m_redisDB.CreateBatch();
|
|
}
|
|
|
|
|
|
//----------------------------------------- redis相关事件
|
|
|
|
private static void RegisterEvent()
|
|
{
|
|
m_redisConn.ConfigurationChangedBroadcast += OnConfigurationChangedBroadcast;
|
|
m_redisConn.HashSlotMoved += OnHashSlotMoved;
|
|
m_redisConn.ConfigurationChanged += OnConfigurationChanged;
|
|
m_redisConn.ConnectionRestored += OnConnectionRestored;
|
|
m_redisConn.ConnectionFailed += OnConnectionFailed;
|
|
|
|
m_redisConn.ErrorMessage += OnErrorMessage;
|
|
m_redisConn.InternalError += OnInternalError;
|
|
}
|
|
|
|
// 重新配置广播-主从同步更改
|
|
private static void OnConfigurationChangedBroadcast(object sender, EndPointEventArgs e)
|
|
{
|
|
TraceLog.Trace($"{nameof(OnConfigurationChangedBroadcast)}: {e.EndPoint}");
|
|
}
|
|
|
|
|
|
// 更改集群
|
|
private static void OnHashSlotMoved(object sender, HashSlotMovedEventArgs e)
|
|
{
|
|
TraceLog.Error(
|
|
$"{nameof(OnHashSlotMoved)}: {nameof(e.OldEndPoint)}-{e.OldEndPoint} To {nameof(e.NewEndPoint)}-{e.NewEndPoint}, ");
|
|
}
|
|
|
|
// 更改配置
|
|
private static void OnConfigurationChanged(object sender, EndPointEventArgs e)
|
|
{
|
|
TraceLog.Error($"{nameof(OnConfigurationChanged)}: {e.EndPoint}");
|
|
}
|
|
|
|
// 连接失败
|
|
private static void OnConnectionFailed(object sender, ConnectionFailedEventArgs e)
|
|
{
|
|
TraceLog.Error($"{nameof(OnConnectionFailed)}: {e.Exception}");
|
|
}
|
|
|
|
// 重新连接
|
|
private static void OnConnectionRestored(object sender, ConnectionFailedEventArgs e)
|
|
{
|
|
TraceLog.Error($"{nameof(OnConnectionRestored)}: {e.Exception}");
|
|
}
|
|
|
|
// 发生错误
|
|
private static void OnErrorMessage(object sender, RedisErrorEventArgs e)
|
|
{
|
|
TraceLog.Error($"{nameof(OnErrorMessage)}: {e.Message}");
|
|
}
|
|
// 内部错误
|
|
private static void OnInternalError(object sender, InternalErrorEventArgs e)
|
|
{
|
|
TraceLog.Error($"{nameof(OnInternalError)}: {e.Exception}");
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|