Redis03-基础-C#客户端
零、文章目录
Redis03-基础-C#客户端
1、安装NuGet包
dotnet add package Newtonsoft.Json -v 13.0.3
dotnet add package StackExchange.Redis -v 2.8.24
2、操作帮助类实现
/***
主题:Redis帮助类
功能:1、设置连接字符串、选择数据库2、String操作①保存单个键值对②根据键获取到对应的值③同时保存多个键值对④存储一个对象⑤获取一个对象3、Hash操作①判断单个键值对是否存在Hash中②从Hash中移除单个键值对③从Hash中同时移除单个键对应的多个字段列表④在Hash中指定值⑤在Hash中同时添加单个键指定的多个字段列表⑥在Hash中获取单个键、字段对应的值⑦在Hash中同时获取单个键对应的指定字段⑧在Hash中获取单个键对应的所有字段⑨在Hash中获取单个键对应的所有值⑩在Hash中给单个键的单个字段添加一个对象值⑪在Hash中获取单个键单个字段对应的对象值4、List操作①移除并返回列表中该键对应的第一个元素②移除并返回列表中该键对应的最后一个元素③移除列表中指定键与该值相同的元素④在列表尾部插入值。如果键不存在,先创建再插入值⑤在列表头部插入值。如果键不存在,先创建再插入值⑥返回列表上该键的长度,如果不存在,返回 0⑦返回在该列表上键所对应的起止点元素⑧移除并返回存储在该键列表的第一个元素对象⑨移除并返回存储在该键列表的最后一个元素对象5、SortedSet操作①SortedSet新增②在有序集合中返回指定范围的元素,默认情况下从低到高③返回有序集合的元素个数④增量的得分排序的集合中的成员存储键值键按增量6、Key操作①删除指定Key②删除指定Key列表③检查Key是否存在④重命名Key⑤设置Key的时间7、发布订阅①订阅②发布
*/using Newtonsoft.Json;
using StackExchange.Redis;
using System.Text;namespace ConsoleMyRedis
{class RedisHelper{# region 1、设置连接字符串、选择数据库//连接字符串private readonly string _ConnectStr;//连接的Redis对象private static IConnectionMultiplexer _ConnMultiplexer;//锁private static readonly object _Locker = new object();//数据库private IDatabase _DB;/// <summary>/// 构造函数/// </summary>/// <param name="connStr">Redis的连接字符串</param>public RedisHelper(string connStr){if (!string.IsNullOrEmpty(connStr)){_ConnectStr = connStr;//获取到连接对象GetConnectRedisMultiplexer();//添加注册事件AddRegisterEvent();}}/// <summary>/// 选择数据库/// </summary>/// <param name="db">数据库编号(默认是编号0的数据库)</param>public void SelectDB(int db = 0){_DB = _ConnMultiplexer.GetDatabase(db);}/// <summary>/// 获取到连接状态/// </summary>public bool ConnetStatus{get{if (_ConnMultiplexer != null){return _ConnMultiplexer.IsConnected;}else{return false;}}}/// <summary>/// 给键添加前缀/// </summary>/// <param name="prefixName">前缀名称</param>/// <param name="keyName">键名称</param>/// <returns>返回添加前缀后的键</returns>public string AddPrefixOfKey(string prefixName, string keyName){string str = $"{prefixName}:{keyName}";return str;}//序列化类型public enum SerializeType{Binary, //二进制Json, //Json}#endregion# region 2、String操作#region 同步方式/// <summary>/// 保存单个键值对字符串(如果 key 已存在,则覆盖值)/// </summary>/// <param name="redisKey">键</param>/// <param name="redisValue">值</param>/// <param name="expiry">时间间隔</param>/// <returns>返回结果(true表示成功)</returns>public bool SetString(string redisKey, string redisValue, TimeSpan? expiry = null){if (ConnetStatus){return _DB.StringSet(redisKey, redisValue, expiry);}else{return false;}}/// <summary>/// 获取键对应值字符串/// </summary>/// <param name="redisKey">键</param>/// <param name="expiry">时间间隔</param>/// <returns>返回结果(true表示成功)</returns>public string GetString(string redisKey, TimeSpan? expiry = null){if (ConnetStatus){return _DB.StringGet(redisKey);}else{return null;}}/// <summary>/// 保存多个多个键值对字符串/// </summary>/// <param name="keyValuePairs">键值对容器</param>/// <returns>返回结果(true表示成功)</returns>public bool SetString(IEnumerable<KeyValuePair<string, string>> keyValuePairs){if (ConnetStatus){var pairs = keyValuePairs.Select(x => new KeyValuePair<RedisKey, RedisValue>(x.Key, x.Value));return _DB.StringSet(pairs.ToArray());}else{return false;}}/// <summary>/// 存储一个对象(该对象会被序列化保存)/// </summary>/// <param name="redisKey">键</param>/// <param name="redisValue">值(会被序列化)</param>/// <param name="expiry">时间间隔</param>/// <param name="serializeType">序列化类型(默认序列化为Json)</param>/// <returns>返回结果(true表示成功)</returns>public bool SetObjString<T>(string redisKey, T redisValue, TimeSpan? expiry = null,SerializeType serializeType = SerializeType.Json){if (ConnetStatus){switch (serializeType){case SerializeType.Binary:var binaryValue = Serialize(redisValue);return _DB.StringSet(redisKey, binaryValue, expiry);case SerializeType.Json:var jsonValue = SerializeJson(redisValue);return _DB.StringSet(redisKey, jsonValue, expiry);default:return false;}}else{return false;}}/// <summary>/// 获取一个对象(会进行反序列化)/// </summary>/// <param name="redisKey">键</param>/// <param name="expiry"></param>/// <param name="serializeType">序列化类型(默认序列化为Json)</param> /// <returns>返回结果(true表示成功)</returns>public T GetObjString<T>(string redisKey, TimeSpan? expiry = null,SerializeType serializeType = SerializeType.Json){if (ConnetStatus){switch (serializeType){case SerializeType.Binary:return Deserialize<T>(_DB.StringGet(redisKey));case SerializeType.Json:return DeserializeJson<T>(_DB.StringGet(redisKey));default:return default(T);}}else{return default(T);}}#endregion#region 异步方式/// <summary>/// 保存一个键值对字符串(异步方式)/// </summary>/// <param name="redisKey">键</param>/// <param name="redisValue">值</param>/// <param name="expiry">时间间隔</param>/// <returns>返回结果(true表示成功)</returns>public async Task<bool> SetStringOfAsync(string redisKey, string redisValue, TimeSpan? expiry = null){if (ConnetStatus){return await _DB.StringSetAsync(redisKey, redisValue, expiry);}else{return false;}}/// <summary>/// 获取单个值/// </summary>/// <param name="redisKey">键</param>/// <param name="redisValue">值</param>/// <param name="expiry">时间间隔</param>/// <returns>返回结果(true表示成功)</returns>public async Task<string> GetStringOfAsync(string redisKey, TimeSpan? expiry = null){if (ConnetStatus){return await _DB.StringGetAsync(redisKey);}else{return null;}}/// <summary>/// 保存一组字符串值/// </summary>/// <param name="keyValuePairs">键值对容器</param>/// <returns>返回结果(true表示成功)</returns>public async Task<bool> SetStringOfAsync(IEnumerable<KeyValuePair<string, string>> keyValuePairs){if (ConnetStatus){var pairs = keyValuePairs.Select(x => new KeyValuePair<RedisKey, RedisValue>(x.Key, x.Value));return await _DB.StringSetAsync(pairs.ToArray());}else{return false;}}/// <summary>/// 存储一个对象(该对象会被序列化保存)/// </summary>/// <param name="redisKey">键</param>/// <param name="redisValue">值</param>/// <param name="expiry">间隔时间</param>/// <param name="serializeType">序列化类型(默认序列化为Json)</param> /// <returns>返回结果(true表示成功)</returns>public async Task<bool> SetObjStringOfAsync<T>(string redisKey, T redisValue, TimeSpan? expiry = null,SerializeType serializeType = SerializeType.Json){if (ConnetStatus){switch (serializeType){case SerializeType.Binary:var binaryValue = Serialize(redisValue);return await _DB.StringSetAsync(redisKey, binaryValue, expiry);case SerializeType.Json:var jsonValue = SerializeJson(redisValue);return await _DB.StringSetAsync(redisKey, jsonValue, expiry);default:break;}return false;}else{return false;}}/// <summary>/// 获取一个对象(会进行反序列化)/// </summary>/// <param name="redisKey">键</param>/// <param name="expiry">间隔时间</param>/// <param name="serializeType">序列化类型(默认序列化为Json)</param> /// <returns>返回结果(true表示成功)</returns>public async Task<T> GetObjStringOfAsync<T>(string redisKey, TimeSpan? expiry = null,SerializeType serializeType = SerializeType.Json){if (ConnetStatus){switch (serializeType){case SerializeType.Binary:return Deserialize<T>(await _DB.StringGetAsync(redisKey));case SerializeType.Json:return DeserializeJson<T>(await _DB.StringGetAsync(redisKey));default:break;}return default(T);}else{return default(T);}}#endregion#endregion#region 3、Hash操作#region 同步方式/// <summary>/// 判断该字段是否存在hash中/// </summary>/// <param name="redisKey">键</param>/// <param name="hashField">字段</param>/// <returns>返回结果(true:表示成功)</returns>public bool ExistsHash(string redisKey, string hashField){if (ConnetStatus){return _DB.HashExists(redisKey, hashField);}else{return false;}}/// <summary>/// 从 hash 中移除指定字段/// </summary>/// <param name="redisKey">键</param>/// <param name="hashField">字段</param>/// <returns>返回结果(true:表示成功)</returns>public bool DeleteHash(string redisKey, string hashField){if (ConnetStatus){return _DB.HashDelete(redisKey, hashField);}else{return false;}}/// <summary>/// 从 hash 中移除指定字段/// </summary>/// <param name="redisKey">键</param>/// <param name="hashFields">字段</param>/// <returns>返回结果(-1:表示失败)</returns>public long DeleteHash(string redisKey, IEnumerable<string> hashFields){if (ConnetStatus){var fields = hashFields.Select(x => (RedisValue)x);return _DB.HashDelete(redisKey, fields.ToArray());}else{return -1;}}/// <summary>/// 在 hash 设定值/// </summary>/// <param name="redisKey">键</param>/// <param name="hashField">字段</param>/// <param name="value">值</param>/// <returns>返回结果(true:表示成功)</returns>public bool SetHash(string redisKey, string hashField, string value){if (ConnetStatus){return _DB.HashSet(redisKey, hashField, value);}else{return false;}}/// <summary>/// 在 hash 中设定值/// </summary>/// <param name="redisKey">键</param>/// <param name="hashFields">字段容器</param>public void SetHash(string redisKey, IEnumerable<KeyValuePair<string, string>> hashFields){if (ConnetStatus){var entries = hashFields.Select(x => new HashEntry(x.Key, x.Value));_DB.HashSet(redisKey, entries.ToArray());}}/// <summary>/// 在 hash 中获取值/// </summary>/// <param name="redisKey">键</param>/// <param name="hashField">字段</param>/// <returns>返回结果</returns>public string GetHash(string redisKey, string hashField){if (ConnetStatus){return _DB.HashGet(redisKey, hashField);}else{return null;}}/// <summary>/// 在hash获取值/// </summary>/// <param name="redisKey">键</param>/// <param name="hashFields">字段</param>/// <returns>返回结果</returns>public IEnumerable<string> GetHash(string redisKey, IEnumerable<string> hashFields){if (ConnetStatus){var fields = hashFields.Select(x => (RedisValue)x);return ConvertStrings(_DB.HashGet(redisKey, fields.ToArray()));}else{return null;}}/// <summary>/// 从 hash 返回所有的字段值/// </summary>/// <param name="redisKey">键</param>/// <returns>返回结果</returns>public IEnumerable<string> HashKeys(string redisKey){if (ConnetStatus){return ConvertStrings(_DB.HashKeys(redisKey));}else{return null;}}/// <summary>/// 根据键获取hash中的所有值/// </summary>/// <param name="redisKey">键</param>/// <returns>返回hash结果</returns>public IEnumerable<string> HashValues(string redisKey){if (ConnetStatus){return ConvertStrings(_DB.HashValues(redisKey));}else{return null;}}/// <summary>/// 在 hash 设定值(序列化)/// </summary>/// <param name="redisKey">键</param>/// <param name="hashField">字段</param>/// <param name="redisValue">值</param>/// <param name="serializeType">序列化的类型(默认是Json)</param>/// <returns>返回结果(true:表示成功)</returns>public bool SetObjHash<T>(string redisKey, string hashField, T redisValue,SerializeType serializeType = SerializeType.Json){if (ConnetStatus){switch (serializeType){case SerializeType.Binary:var binaryValue = Serialize(redisValue);return _DB.HashSet(redisKey, hashField, binaryValue);case SerializeType.Json:var jsonValue = SerializeJson(redisValue);return _DB.HashSet(redisKey, hashField, jsonValue);default:return false;}}else{return false;}}/// <summary>/// 在 hash 中获取值(反序列化)/// </summary>/// <param name="redisKey"></param>/// <param name="hashField"></param>/// <param name="serializeType">序列化的类型(默认是Json)</param>/// <returns></returns>public T GetObjHash<T>(string redisKey, string hashField,SerializeType serializeType = SerializeType.Json){if (ConnetStatus){switch (serializeType){case SerializeType.Binary:return Deserialize<T>(_DB.HashGet(redisKey, hashField));case SerializeType.Json:return DeserializeJson<T>(_DB.HashGet(redisKey, hashField));default:return default(T);}}else{return default(T);}}#endregion#region 异步方式/// <summary>/// 判断该字段是否存在hash中(异步方式)/// </summary>/// <param name="redisKey">键</param>/// <param name="hashField">字段</param>/// <returns>返回结果(true:表示存在)</returns>public async Task<bool> ExistsHashOfAsync(string redisKey, string hashField){if (ConnetStatus){return await _DB.HashExistsAsync(redisKey, hashField);}else{return false;}}/// <summary>/// 从hash中移除指定字段/// </summary>/// <param name="redisKey">键</param>/// <param name="hashField">字段</param>/// <returns>返回结果(true:表示成功)</returns>public async Task<bool> DeleteHashOfAsync(string redisKey, string hashField){if (ConnetStatus){return await _DB.HashDeleteAsync(redisKey, hashField);}else{return false;}}/// <summary>/// 从hash中移除指定字段/// </summary>/// <param name="redisKey">键</param>/// <param name="hashFields">字段</param>/// <returns>返回删除结果(-1 表示失败)</returns>public async Task<long> DeleteHashOfAsync(string redisKey, IEnumerable<string> hashFields){if (ConnetStatus){var fields = hashFields.Select(x => (RedisValue)x);return await _DB.HashDeleteAsync(redisKey, fields.ToArray());}else{return -1;}}/// <summary>/// 在 hash 设定值/// </summary>/// <param name="redisKey">键</param>/// <param name="hashField">字段</param>/// <param name="value">值</param>/// <returns>返回结果(true:表示成功)</returns>public async Task<bool> SetHashOfAsync(string redisKey, string hashField, string value){if (ConnetStatus){return await _DB.HashSetAsync(redisKey, hashField, value);}else{return false;}}/// <summary>/// 在 hash 中设定值/// </summary>/// <param name="redisKey"></param>/// <param name="hashFields"></param>public async Task SetHashOfAsync(string redisKey, IEnumerable<KeyValuePair<string, string>> hashFields){if (ConnetStatus){var entries = hashFields.Select(x => new HashEntry(x.Key, x.Value));await _DB.HashSetAsync(redisKey, entries.ToArray());}else{return;}}/// <summary>/// 在 hash 中获取值/// </summary>/// <param name="redisKey">键</param>/// <param name="hashField">字段</param>/// <returns>返回结果</returns>public async Task<string> GetHashOfAsync(string redisKey, string hashField){if (ConnetStatus){return await _DB.HashGetAsync(redisKey, hashField);}else{return null;}}/// <summary>/// 在 hash 中获取值/// </summary>/// <param name="redisKey">键</param>/// <param name="hashFields">字段</param>/// <param name="value">值</param>/// <returns>返回结果</returns>public async Task<IEnumerable<string>> GetHashOfAsync(string redisKey, IEnumerable<string> hashFields,string value){if (ConnetStatus){var fields = hashFields.Select(x => (RedisValue)x);return ConvertStrings(await _DB.HashGetAsync(redisKey, fields.ToArray()));}else{return null;}}/// <summary>/// 从 hash 返回所有的字段值/// </summary>/// <param name="redisKey">键</param>/// <returns>返回对应的hash字段值</returns>public async Task<IEnumerable<string>> HashKeysOfAsync(string redisKey){if (ConnetStatus){return ConvertStrings(await _DB.HashKeysAsync(redisKey));}else{return null;}}/// <summary>/// 返回 hash 中的所有值/// </summary>/// <param name="redisKey">键</param>/// <returns>返回hash中的所有值</returns>public async Task<IEnumerable<string>> HashValuesAsync(string redisKey){if (ConnetStatus){return ConvertStrings(await _DB.HashValuesAsync(redisKey));}else{return null;}}/// <summary>/// 在 hash 设定值(序列化)/// </summary>/// <param name="redisKey">键</param>/// <param name="hashField">字段</param>/// <param name="value">值</param>/// <param name="serializeType">序列化的类型(默认是Json)</param>/// <returns>返回结果(true:表示成功)</returns>public async Task<bool> SetObjHashAsync<T>(string redisKey, string hashField, T value,SerializeType serializeType = SerializeType.Json){if (ConnetStatus){switch (serializeType){case SerializeType.Binary:var binaryValue = Serialize(value);return await _DB.HashSetAsync(redisKey, hashField, binaryValue);case SerializeType.Json:var jsonValue = SerializeJson(value);return await _DB.HashSetAsync(redisKey, hashField, jsonValue);default:return false;}}else{return false;}}/// <summary>/// 在 hash 中获取值(反序列化)/// </summary>/// <param name="redisKey"></param>/// <param name="hashField"></param>/// <param name="serializeType">序列化的类型(默认是Json)</param>/// <returns></returns>public async Task<T> GetObjHashAsync<T>(string redisKey, string hashField,SerializeType serializeType = SerializeType.Json){if (ConnetStatus){switch (serializeType){case SerializeType.Binary:return Deserialize<T>(await _DB.HashGetAsync(redisKey, hashField));case SerializeType.Json:return DeserializeJson<T>(await _DB.HashGetAsync(redisKey, hashField));default:return default(T);}}else{return default(T);}}#endregion#endregion#region 4、List操作#region 同步方式/// <summary>/// 移除并返回存储在该键列表的第一个元素/// </summary>/// <param name="redisKey">键</param>/// <returns></returns>public string PopFirtKeyOfList(string redisKey){if (ConnetStatus){return _DB.ListLeftPop(redisKey);}else{return null;}}/// <summary>/// 移除并返回存储在该键列表的最后一个元素/// </summary>/// <param name="redisKey">键</param>/// <returns></returns>public string PopLastKeyOfList(string redisKey){if (ConnetStatus){return _DB.ListRightPop(redisKey);}else{return null;}}/// <summary>/// 移除列表指定键上与该值相同的元素/// </summary>/// <param name="redisKey">键</param>/// <param name="redisValue">值</param>/// <returns>返回结果(-1 表示失败)</returns>public long PopSameKeyOfList(string redisKey, string redisValue){if (ConnetStatus){return _DB.ListRemove(redisKey, redisValue);}else{return -1;}}/// <summary>/// 在列表尾部插入值。如果键不存在,先创建再插入值/// </summary>/// <param name="redisKey">键</param>/// <param name="redisValue">值</param>/// <returns>返回结果(-1 表示失败)</returns>public long PushKeyOfListLast(string redisKey, string redisValue){if (ConnetStatus){return _DB.ListRightPush(redisKey, redisValue);}else{return -1;}}/// <summary>/// 在列表头部插入值。如果键不存在,先创建再插入值/// </summary>/// <param name="redisKey">键</param>/// <param name="redisValue">值</param>/// <returns>返回结果(-1 表示失败)</returns>public long PushKeyOfListFirst(string redisKey, string redisValue){if (ConnetStatus){return _DB.ListLeftPush(redisKey, redisValue);}else{return -1;}}/// <summary>/// 返回列表上该键的长度,如果不存在,返回 0/// </summary>/// <param name="redisKey">键</param>/// <returns>返回结果(-1 表示失败)</returns>public long GetKeyLengthOfList(string redisKey){if (ConnetStatus){return _DB.ListLength(redisKey);}else{return -1;}}/// <summary>/// 返回在该列表上键所对应的元素/// </summary>/// <param name="redisKey">键</param>/// <param name="start">起始点</param>/// <param name="stop">停止点</param>/// <returns></returns>public IEnumerable<string> ListRange(string redisKey, long start = 0L, long stop = -1L){if (ConnetStatus){return ConvertStrings(_DB.ListRange(redisKey, start, stop));}else{return null;}}/// <summary>/// 移除并返回存储在该键列表的第一个元素对象/// </summary>/// <param name="redisKey">键</param>/// <param name="serializeType">序列化类型(默认是Json)</param>/// <returns>返回反序列化后对象</returns>public T PopFirstKeyObjOfList<T>(string redisKey, SerializeType serializeType = SerializeType.Json){if (ConnetStatus){switch (serializeType){case SerializeType.Binary:return Deserialize<T>(_DB.ListLeftPop(redisKey));case SerializeType.Json:return DeserializeJson<T>(_DB.ListLeftPop(redisKey));default:return default(T);}}else{return default(T);}}/// <summary>/// 移除并返回存储在该键列表的最后一个元素对象/// </summary>/// <param name="redisKey">键</param>/// <param name="serializeType">序列化类型(默认是Json)</param>/// <returns>返回反序列化后的对象</returns>public T PopLastKeyObjOfList<T>(string redisKey, SerializeType serializeType = SerializeType.Json){if (ConnetStatus){switch (serializeType){case SerializeType.Binary:return Deserialize<T>(_DB.ListRightPop(redisKey));case SerializeType.Json:return DeserializeJson<T>(_DB.ListRightPop(redisKey));default:return default(T);}}else{return default(T);}}/// <summary>/// 在列表尾部插入值。如果键不存在,先创建再插入值/// </summary>/// <param name="redisKey"></param>/// <param name="redisValue"></param>/// <returns>返回结果(-1 表示失败)</returns>public long PushKeyOfListLast<T>(string redisKey, T redisValue){if (ConnetStatus){return _DB.ListRightPush(redisKey, Serialize(redisValue));}else{return -1;}}/// <summary>/// 在列表头部插入值。如果键不存在,先创建再插入值/// </summary>/// <param name="redisKey"></param>/// <param name="redisValue"></param>/// <returns>返回结果(-1 表示失败)</returns>public long PushKeyOfListHead<T>(string redisKey, T redisValue){if (ConnetStatus){return _DB.ListLeftPush(redisKey, Serialize(redisValue));}else{return -1;}}#endregion#region 异步方式/// <summary>/// 移除并返回存储在该键列表的第一个元素/// </summary>/// <param name="redisKey"></param>/// <returns></returns>public async Task<string> PopFirtKeyOfListAsync(string redisKey){if (ConnetStatus){return await _DB.ListLeftPopAsync(redisKey);}else{return null;}}/// <summary>/// 移除并返回存储在该键列表的最后一个元素/// </summary>/// <param name="redisKey">键</param>/// <returns></returns>public async Task<string> PopLastKeyOfListAsync(string redisKey){if (ConnetStatus){return await _DB.ListRightPopAsync(redisKey);}else{return null;}}/// <summary>/// 移除列表指定键上与该值相同的元素/// </summary>/// <param name="redisKey">键</param>/// <param name="redisValue">值</param>/// <returns>返回结果(-1 表示失败)</returns>public async Task<long> PopSameKeyOfListAsync(string redisKey, string redisValue){if (ConnetStatus){return await _DB.ListRemoveAsync(redisKey, redisValue);}else{return -1;}}/// <summary>/// 在列表尾部插入值。如果键不存在,先创建再插入值/// </summary>/// <param name="redisKey">键</param>/// <param name="redisValue">值</param>/// <returns>返回结果(-1 表示失败)</returns>public async Task<long> PushKeyOfListLastAsync(string redisKey, string redisValue){if (ConnetStatus){return await _DB.ListRightPushAsync(redisKey, redisValue);}else{return -1;}}/// <summary>/// 在列表头部插入值。如果键不存在,先创建再插入值/// </summary>/// <param name="redisKey">键</param>/// <param name="redisValue">值</param>/// <returns>返回结果(-1 表示失败)</returns>public async Task<long> PushKeyOfListHeadAsync(string redisKey, string redisValue){if (ConnetStatus){return await _DB.ListLeftPushAsync(redisKey, redisValue);}else{return -1;}}/// <summary>/// 返回列表上该键的长度,如果不存在,返回 0/// </summary>/// <param name="redisKey">键</param>/// <returns>返回结果(-1 表示失败)</returns>public async Task<long> GetKeyLengthOfListAsync(string redisKey){if (ConnetStatus){return await _DB.ListLengthAsync(redisKey);}else{return -1;}}/// <summary>/// 返回在该列表上键所对应的元素/// </summary>/// <param name="redisKey">键</param>/// <param name="start"></param>/// <param name="stop"></param>/// <returns></returns>public async Task<IEnumerable<string>> ListRangeAsync(string redisKey, long start = 0L, long stop = -1L){if (ConnetStatus){var query = await _DB.ListRangeAsync(redisKey, start, stop);return query.Select(x => x.ToString());}else{return null;}}/// <summary>/// 移除并返回存储在该键列表的第一个元素对象/// </summary>/// <param name="redisKey"></param>/// <param name="serializeType">序列化类型(默认是Json)</param>/// <returns>返回反序列化后的对象</returns>public async Task<T> PopFirstKeyObjOfListAsync<T>(string redisKey, SerializeType serializeType = SerializeType.Json){if (ConnetStatus){switch (serializeType){case SerializeType.Binary:return Deserialize<T>(await _DB.ListLeftPopAsync(redisKey));case SerializeType.Json:return DeserializeJson<T>(await _DB.ListLeftPopAsync(redisKey));default:return default(T);}}else{return default(T);}}/// <summary>/// 移除并返回存储在该键列表的最后一个元素对象/// </summary>/// <param name="redisKey">键</param>/// <param name="serializeType">序列化类型(默认是Json)</param>/// <returns>返回反序列化后的对象</returns>public async Task<T> PopLastKeyObjOfListAsync<T>(string redisKey, SerializeType serializeType = SerializeType.Json){if (ConnetStatus){switch (serializeType){case SerializeType.Binary:return Deserialize<T>(await _DB.ListRightPopAsync(redisKey));case SerializeType.Json:return DeserializeJson<T>(await _DB.ListRightPopAsync(redisKey));default:return default(T);}}else{return default(T);}}/// <summary>/// 在列表尾部插入值。如果键不存在,先创建再插入值/// </summary>/// <param name="redisKey">键</param>/// <param name="redisValue">值</param>/// <returns>返回结果(-1 表示失败)</returns>public async Task<long> PushKeyOfListLastAsync<T>(string redisKey, T redisValue){if (ConnetStatus){return await _DB.ListRightPushAsync(redisKey, Serialize(redisValue));}else{return -1;}}/// <summary>/// 在列表头部插入值。如果键不存在,先创建再插入值/// </summary>/// <param name="redisKey">键</param>/// <param name="redisValue">值</param>/// <returns>返回结果(-1 表示失败)</returns>public async Task<long> PushKeyOfListHeadAsync<T>(string redisKey, T redisValue){if (ConnetStatus){return await _DB.ListLeftPushAsync(redisKey, Serialize(redisValue));}else{return -1;}}#endregion#endregion#region 5、SortedSet操作#region 同步方式/// <summary>/// SortedSet 新增/// </summary>/// <param name="redisKey">键</param>/// <param name="member"></param>/// <param name="score"></param>/// <returns></returns>public bool SortedSetAdd(string redisKey, string member, double score){if (ConnetStatus){return _DB.SortedSetAdd(redisKey, member, score);}else{return false;}}/// <summary>/// 在有序集合中返回指定范围的元素,默认情况下从低到高/// </summary>/// <param name="redisKey"></param>/// <param name="start"></param>/// <param name="stop"></param>/// <param name="order"></param>/// <returns></returns>public IEnumerable<string> SortedSetRangeByRank(string redisKey, long start = 0L, long stop = -1L,OrderType order = OrderType.Asc){if (ConnetStatus){return _DB.SortedSetRangeByRank(redisKey, start, stop, (Order)order).Select(x => x.ToString());}else{return null;}}/// <summary>/// 返回有序集合的元素个数/// </summary>/// <param name="redisKey"></param>/// <returns>返回结果(-1 表示失败)</returns>public long SortedSetLength(string redisKey){if (ConnetStatus){return _DB.SortedSetLength(redisKey);}else{return -1;}}/// <summary>/// 返回有序集合的元素个数/// </summary>/// <param name="redisKey"></param>/// <param name="memebr"></param>/// <returns>返回结果(true:表示成功)</returns>public bool SortedSetLength(string redisKey, string memebr){if (ConnetStatus){return _DB.SortedSetRemove(redisKey, memebr);}else{return false;}}/// <summary>/// SortedSet 新增/// </summary>/// <param name="redisKey"></param>/// <param name="member"></param>/// <param name="score"></param>/// <returns>返回结果(true:表示成功)</returns>public bool SortedSetAdd<T>(string redisKey, T member, double score){if (ConnetStatus){var json = Serialize(member);return _DB.SortedSetAdd(redisKey, json, score);}else{return false;}}/// <summary>/// 增量的得分排序的集合中的成员存储键值键按增量/// </summary>/// <param name="redisKey"></param>/// <param name="member"></param>/// <param name="value"></param>/// <returns>返回结果(-1 表示失败)</returns>public double SortedSetIncrement(string redisKey, string member, double value = 1){if (ConnetStatus){return _DB.SortedSetIncrement(redisKey, member, value);}else{return -1;}}#endregion#region 异步方式/// <summary>/// SortedSet 新增/// </summary>/// <param name="redisKey"></param>/// <param name="member"></param>/// <param name="score"></param>/// <returns>返回结果(true:表示成功)</returns>public async Task<bool> SortedSetAddAsync(string redisKey, string member, double score){if (ConnetStatus){return await _DB.SortedSetAddAsync(redisKey, member, score);}else{return false;}}/// <summary>/// 在有序集合中返回指定范围的元素,默认情况下从低到高。/// </summary>/// <param name="redisKey"></param>/// <returns></returns>public async Task<IEnumerable<string>> SortedSetRangeByRankAsync(string redisKey){if (ConnetStatus){return ConvertStrings(await _DB.SortedSetRangeByRankAsync(redisKey));}else{return null;}}/// <summary>/// 返回有序集合的元素个数/// </summary>/// <param name="redisKey"></param>/// <returns>返回结果(-1 表示失败)</returns>public async Task<long> SortedSetLengthAsync(string redisKey){if (ConnetStatus){return await _DB.SortedSetLengthAsync(redisKey);}else{return -1;}}/// <summary>/// 返回有序集合的元素个数/// </summary>/// <param name="redisKey"></param>/// <param name="memebr"></param>/// <returns>返回结果(true:表示成功)</returns>public async Task<bool> SortedSetRemoveAsync(string redisKey, string memebr){if (ConnetStatus){return await _DB.SortedSetRemoveAsync(redisKey, memebr);}else{return false;}}/// <summary>/// SortedSet 新增/// </summary>/// <param name="redisKey"></param>/// <param name="member"></param>/// <param name="score"></param>/// <returns></returns>public async Task<bool> SortedSetAddAsync<T>(string redisKey, T member, double score){if (ConnetStatus){var json = Serialize(member);return await _DB.SortedSetAddAsync(redisKey, json, score);}else{return false;}}/// <summary>/// 增量的得分排序的集合中的成员存储键值键按增量/// </summary>/// <param name="redisKey"></param>/// <param name="member"></param>/// <param name="value"></param>/// <returns>返回结果(-1 表示失败)</returns>public async Task<double> SortedSetIncrementAsync(string redisKey, string member, double value = 1){if (ConnetStatus){return await _DB.SortedSetIncrementAsync(redisKey, member, value);}else{return -1;}}#endregion/// <summary>/// Redis 排序类型/// </summary>public enum OrderType{Asc,Desc}#endregion#region 6、Key操作#region 同步方式/// <summary>/// 删除指定Key/// </summary>/// <param name="redisKey">键</param>/// <returns>返回结果(true:表示成功)</returns>public bool DeleteKey(string redisKey){if (ConnetStatus){return _DB.KeyDelete(redisKey);}else{return false;}}/// <summary>/// 删除指定Key列表/// </summary>/// <param name="redisKeys">键容器</param>/// <returns>移除指定键的数量(-1:表示失败)</returns>public long DeleteKey(IEnumerable<string> redisKeys){if (ConnetStatus){var keys = redisKeys.Select(x => (RedisKey)x);return _DB.KeyDelete(keys.ToArray());}else{return -1;}}/// <summary>/// 检查Key是否存在/// </summary>/// <param name="redisKey">键</param>/// <returns>返回结果(true:表示成功)</returns>public bool ExistsKey(string redisKey){if (ConnetStatus){return _DB.KeyExists(redisKey);}else{return false;}}/// <summary>/// 重命名Key/// </summary>/// <param name="redisKey">原来的键</param>/// <param name="redisNewKey">新的键名</param>/// <returns>返回结果(true:表示成功)</returns>public bool RenameKey(string redisKey, string redisNewKey){if (ConnetStatus){return _DB.KeyRename(redisKey, redisNewKey);}else{return false;}}/// <summary>/// 设置 Key 的时间/// </summary>/// <param name="redisKey">键</param>/// <param name="expiry">时间间隔</param>/// <returns>返回结果(true:表示成功)</returns>public bool SetKeyExpire(string redisKey, TimeSpan? expiry){if (ConnetStatus){return _DB.KeyExpire(redisKey, expiry);}else{return false;}}#endregion#region 异步方式/// <summary>/// 移除指定 Key/// </summary>/// <param name="redisKey">键</param>/// <returns>返回结果(true:表示成功)</returns>public async Task<bool> DeleteKeyAsync(string redisKey){if (ConnetStatus){return await _DB.KeyDeleteAsync(redisKey);}else{return false;}}/// <summary>/// 删除指定 Key 列表/// </summary>/// <param name="redisKeys">键</param>/// <returns>返回结果(-1 表示失败)</returns>public async Task<long> DeleteKeyAsync(IEnumerable<string> redisKeys){if (ConnetStatus){var keys = redisKeys.Select(x => (RedisKey)x);return await _DB.KeyDeleteAsync(keys.ToArray());}else{return -1;}}/// <summary>/// 检查 Key 是否存在/// </summary>/// <param name="redisKey">键</param>/// <returns>返回结果(true:表示成功)</returns>public async Task<bool> ExistsKeyAsync(string redisKey){if (ConnetStatus){return await _DB.KeyExistsAsync(redisKey);}else{return false;}}/// <summary>/// 重命名 Key/// </summary>/// <param name="redisKey">旧的键名称</param>/// <param name="redisNewKey">新的键名称</param>/// <returns>返回结果(true:表示成功)</returns>public async Task<bool> RenameKeyAsync(string redisKey, string redisNewKey){if (ConnetStatus){return await _DB.KeyRenameAsync(redisKey, redisNewKey);}else{return false;}}/// <summary>/// 设置 Key 的时间/// </summary>/// <param name="redisKey">键</param>/// <param name="expiry">间隔时间</param>/// <returns>返回结果(true:表示成功)</returns>public async Task<bool> SetKeyExpireAsync(string redisKey, TimeSpan? expiry){if (ConnetStatus){return await _DB.KeyExpireAsync(redisKey, expiry);}else{return false;}}#endregion#endregion#region 7、发布订阅#region 同步方式/// <summary>/// 订阅/// </summary>/// <param name="channel"></param>/// <param name="handle"></param>public void Subscribe(RedisChannel channel, Action<RedisChannel, RedisValue> handle){var sub = _ConnMultiplexer.GetSubscriber();sub.Subscribe(channel, handle);}/// <summary>/// 发布/// </summary>/// <param name="channel"></param>/// <param name="message"></param>/// <returns></returns>public long Publish(RedisChannel channel, RedisValue message){var sub = _ConnMultiplexer.GetSubscriber();return sub.Publish(channel, message);}/// <summary>/// 发布(使用序列化)/// </summary>/// <typeparam name="T"></typeparam>/// <param name="channel"></param>/// <param name="message"></param>/// <returns></returns>public long Publish<T>(RedisChannel channel, T message){var sub = _ConnMultiplexer.GetSubscriber();return sub.Publish(channel, Serialize(message));}#endregion#region 异步方式/// <summary>/// 订阅/// </summary>/// <param name="channel"></param>/// <param name="handle"></param>public async Task SubscribeAsync(RedisChannel channel, Action<RedisChannel, RedisValue> handle){var sub = _ConnMultiplexer.GetSubscriber();await sub.SubscribeAsync(channel, handle);}/// <summary>/// 发布/// </summary>/// <param name="channel"></param>/// <param name="message"></param>/// <returns></returns>public async Task<long> PublishAsync(RedisChannel channel, RedisValue message){var sub = _ConnMultiplexer.GetSubscriber();return await sub.PublishAsync(channel, message);}/// <summary>/// 发布(使用序列化)/// </summary>/// <typeparam name="T"></typeparam>/// <param name="channel"></param>/// <param name="message"></param>/// <returns></returns>public async Task<long> PublishAsync<T>(RedisChannel channel, T message){var sub = _ConnMultiplexer.GetSubscriber();return await sub.PublishAsync(channel, Serialize(message));}#endregion#endregion#region 私有方法/// <summary>/// 获取到连接的Redis对象/// </summary>/// <returns></returns>private IConnectionMultiplexer GetConnectRedisMultiplexer(){if (_ConnMultiplexer == null || !_ConnMultiplexer.IsConnected){lock (_Locker){if (_ConnMultiplexer == null || !_ConnMultiplexer.IsConnected){_ConnMultiplexer = ConnectionMultiplexer.Connect(_ConnectStr);}}}return _ConnMultiplexer;}#region 注册事件/// <summary>/// 添加注册事件/// </summary>private static void AddRegisterEvent(){_ConnMultiplexer.ConnectionRestored += ConnMultiplexer_ConnectionRestored;_ConnMultiplexer.ConnectionFailed += ConnMultiplexer_ConnectionFailed;_ConnMultiplexer.ErrorMessage += ConnMultiplexer_ErrorMessage;_ConnMultiplexer.ConfigurationChanged += ConnMultiplexer_ConfigurationChanged;_ConnMultiplexer.HashSlotMoved += ConnMultiplexer_HashSlotMoved;_ConnMultiplexer.InternalError += ConnMultiplexer_InternalError;_ConnMultiplexer.ConfigurationChangedBroadcast += ConnMultiplexer_ConfigurationChangedBroadcast;}/// <summary>/// 重新配置广播时(通常意味着主从同步更改)/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private static void ConnMultiplexer_ConfigurationChangedBroadcast(object sender, EndPointEventArgs e){Console.WriteLine($"{nameof(ConnMultiplexer_ConfigurationChangedBroadcast)}: {e.EndPoint}");}/// <summary>/// 发生内部错误时(主要用于调试)/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private static void ConnMultiplexer_InternalError(object sender, InternalErrorEventArgs e){Console.WriteLine($"{nameof(ConnMultiplexer_InternalError)}: {e.Exception}");}/// <summary>/// 更改集群时/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private static void ConnMultiplexer_HashSlotMoved(object sender, HashSlotMovedEventArgs e){Console.WriteLine($"{nameof(ConnMultiplexer_HashSlotMoved)}: {nameof(e.OldEndPoint)}-{e.OldEndPoint} To {nameof(e.NewEndPoint)}-{e.NewEndPoint}, ");}/// <summary>/// 配置更改时/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private static void ConnMultiplexer_ConfigurationChanged(object sender, EndPointEventArgs e){Console.WriteLine($"{nameof(ConnMultiplexer_ConfigurationChanged)}: {e.EndPoint}");}/// <summary>/// 发生错误时/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private static void ConnMultiplexer_ErrorMessage(object sender, RedisErrorEventArgs e){Console.WriteLine($"{nameof(ConnMultiplexer_ErrorMessage)}: {e.Message}");}/// <summary>/// 物理连接失败时/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private static void ConnMultiplexer_ConnectionFailed(object sender, ConnectionFailedEventArgs e){Console.WriteLine($"{nameof(ConnMultiplexer_ConnectionFailed)}: {e.Exception}");}/// <summary>/// 建立物理连接时/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private static void ConnMultiplexer_ConnectionRestored(object sender, ConnectionFailedEventArgs e){Console.WriteLine($"{nameof(ConnMultiplexer_ConnectionRestored)}: {e.Exception}");}#endregion 注册事件/// <summary>/// 转换为字符串/// </summary>/// <typeparam name="T">数据类型</typeparam>/// <param name="list">数据列表</param>/// <returns>返回转为字符串后的数据列表</returns>private static IEnumerable<string> ConvertStrings<T>(IEnumerable<T> list) where T : struct{if (list == null) throw new ArgumentNullException(nameof(list));return list.Select(x => x.ToString());}/// <summary>/// 序列化(二进制)/// </summary>/// <param name="obj"></param>/// <returns></returns>private static byte[] Serialize(object obj){if (obj == null)return null;string jsonString = JsonConvert.SerializeObject(obj);byte[] data = Encoding.UTF8.GetBytes(jsonString);return data;}/// <summary>/// 反序列化(二进制)/// </summary>/// <typeparam name="T"></typeparam>/// <param name="data"></param>/// <returns></returns>private static T Deserialize<T>(byte[] data){if (data == null)return default(T);string json = System.Text.Encoding.UTF8.GetString(data);T result = JsonConvert.DeserializeObject<T>(json);return result;}/// <summary>/// 序列化对象为Json字符串/// </summary>/// <typeparam name="T">实体类型</typeparam>/// <param name="obj">实体对象</param>/// <returns>返回序列化的字符串</returns>private static string SerializeJson<T>(T obj){string tmp = null;if (obj != null){tmp = JsonConvert.SerializeObject(obj);}return tmp;}/// <summary>/// 反序列化Json字符串为对象/// </summary>/// <typeparam name="T">实体类型</typeparam>/// <param name="strjson">字符串</param>/// <returns></returns>private static T DeserializeJson<T>(string strjson){T tmp = default(T);if (!string.IsNullOrEmpty(strjson)){tmp = JsonConvert.DeserializeObject<T>(strjson);}return tmp;}#endregion}
}
3、帮助类使用
- 此处的地址请换成你 redis 的地址,密码换成你自己 redis 的密码
namespace ConsoleMyRedis
{internal class Program{static async Task Main(string[] args){// 创建 RedisHelper 实例string connectionString = "192.168.119.170:6379,password=123123456"; // 根据您的 Redis 服务器配置替换连接字符串RedisHelper redisHelper = new RedisHelper(connectionString);// 1. 设置连接字符串、选择数据库redisHelper.SelectDB(0);// 2. String 操作Console.WriteLine("String 操作:");await redisHelper.SetStringOfAsync("myKey", "myValue");string value = await redisHelper.GetStringOfAsync("myKey");Console.WriteLine($"获取到的值: {value}");// 保存多个键值对var keyValuePairs = new List<KeyValuePair<string, string>>{new KeyValuePair<string, string>("key1", "value1"),new KeyValuePair<string, string>("key2", "value2")};bool setResult = await redisHelper.SetStringOfAsync(keyValuePairs);Console.WriteLine($"多个键值对保存结果: {setResult}");// 存储和获取对象var myObject = new { Name = "Alice", Age = 30 };await redisHelper.SetObjStringOfAsync("myObjectKey", myObject);var retrievedObject = await redisHelper.GetObjStringOfAsync<dynamic>("myObjectKey");Console.WriteLine($"获取的对象 - Name: {retrievedObject.Name}, Age: {retrievedObject.Age}");// 3. Hash 操作Console.WriteLine("\nHash 操作:");await redisHelper.SetHashOfAsync("myHash", "field1", "value1");string hashValue = await redisHelper.GetHashOfAsync("myHash", "field1");Console.WriteLine($"获取 Hash 值: {hashValue}");// 设置多个字段var hashFields = new List<KeyValuePair<string, string>>{new KeyValuePair<string, string>("field2", "value2"),new KeyValuePair<string, string>("field3", "value3")};await redisHelper.SetHashOfAsync("myHash", hashFields);var allHashValues = await redisHelper.HashValuesAsync("myHash");Console.WriteLine($"所有 Hash 值: {string.Join(", ", allHashValues)}");// 4. List 操作Console.WriteLine("\nList 操作:");await redisHelper.PushKeyOfListLastAsync("myList", "item1");await redisHelper.PushKeyOfListLastAsync("myList", "item2");string firstItem = await redisHelper.PopFirtKeyOfListAsync("myList");Console.WriteLine($"移除的第一个元素: {firstItem}");var allListItems = await redisHelper.ListRangeAsync("myList");Console.WriteLine($"列表中的所有元素: {string.Join(", ", allListItems)}");// 5. SortedSet 操作Console.WriteLine("\nSortedSet 操作:");await redisHelper.SortedSetAddAsync("mySortedSet", "member1", 1.0);await redisHelper.SortedSetAddAsync("mySortedSet", "member2", 2.0);var sortedSetMembers = await redisHelper.SortedSetRangeByRankAsync("mySortedSet");Console.WriteLine($"有序集合中的元素: {string.Join(", ", sortedSetMembers)}");// 6. Key 操作Console.WriteLine("\nKey 操作:");bool exists = redisHelper.ExistsKey("myKey");Console.WriteLine($"Key 是否存在: {exists}");await redisHelper.RenameKeyAsync("myKey", "myRenamedKey");exists = redisHelper.ExistsKey("myRenamedKey");Console.WriteLine($"重命名后的 Key 是否存在: {exists}");// 7. 发布订阅Console.WriteLine("\n发布订阅:");redisHelper.Subscribe("myChannel", (channel, message) =>{Console.WriteLine($"接收到消息: {message} 在频道: {channel}");});// 发布信息long publishResult = await redisHelper.PublishAsync("myChannel", "Hello, Redis!");Console.WriteLine($"消息发布结果: {publishResult}");// 确保订阅持久化,以防止程序提前退出Console.WriteLine("按任意键继续...");Console.ReadKey();}}
}
4、运行结果
相关文章:
Redis03-基础-C#客户端
零、文章目录 Redis03-基础-C#客户端 1、安装NuGet包 dotnet add package Newtonsoft.Json -v 13.0.3 dotnet add package StackExchange.Redis -v 2.8.242、操作帮助类实现 /*** 主题:Redis帮助类 功能:1、设置连接字符串、选择数据库2、String操作…...
JimuBI 积木报表 v1.9.5发布,大屏和仪表盘,免费数据可视化
项目介绍 JimuBI (积木报表BI) 是一款免费的数据可视化产品,含大屏和仪表盘、门户、移动图表,像搭建积木一样完全在线设计! 大屏采用类word风格,可以随意拖动组件,想怎么设计怎么设计,可以像百度和阿里一样…...
有关爬虫中数据库的封装——单线程爬虫
在编写爬虫程序时,数据存储是一个非常重要的环节。尤其是在单线程爬虫中,虽然并发量不大,但如果每次操作数据库都直接连接、查询、关闭,不仅代码臃肿,还容易出错,甚至影响爬虫的稳定性。 因此,…...
React19 useOptimistic 用法
用法 乐观更新 发起异步请求时,先假设请求会成功立即更新 UI 给用户反馈若请求最终失败,再将 UI 恢复到之前的状态 const [optimisticState, addOptimistic] useOptimistic(state, updateFn) 参数 state:实际值,可以是 useSta…...
简单的 shell 程序
整体思路 一个简单的 shell 程序的工作流程如下: 初始化环境:在启动时从系统获取环境变量。循环等待用户输入:不断输出命令行提示符,等待用户输入命令。解析命令:把用户输入的命令解析成可执行的格式。执行命令&…...
MIT XV6 - 1.1 Lab: Xv6 and Unix utilities - sleep
接上文 MIT XV6 - 1. 环境准备 实验正文 打开实验链接 Lab: Xv6 and Unix utilities ,可以看到他一共有6个小实验(头大,让我们争取日拱一卒吧…): Boot xv6 (easy)sleep (easy)pingpong (easy)primes (moderate)/(hard)find (moderate)xargs (moderate…...
测地型GNSS接收机_毫米高精度精准定位
在建筑安全、地灾监测、大坝桥梁隧道监测、工程测绘、国土规划等专业领域,传统工具效率低、精度差、环境适应性弱的痛点长期存在。计讯物联测地型GNSS接收机以毫米级精度、全场景适应、智能互联为核心优势,重新定义高精度空间数据采集标准&#…...
React19源码系列之 root.render过程
在创建react项目的时候,入口文件总是有这样一行代码 root.render(<App />) 所以 root.render() 执行是怎样的? 下面就来看看。 之前的文章就提及,root是一个 ReactDOMRoot 对象,其原型链上有 render 和 unmount 方法。 ReactDOMHy…...
0804标星_复制_删除-网络ajax请求2-react-仿低代码平台项目
文章目录 1 标星2 复制3 假删除4 恢复5 彻底删除结语 1 标星 操作:标星和取消标星,有2种状态的布尔值。通过更新问卷功能实现。 后端quetion.js添加接口 {// 更新问卷信息url: /api/question/:id,method: patch,response() {return {errno: 0}}},前端q…...
二叉树遍历(C语言版)
前序遍历创建树,中序遍历把创建出来的二叉树的结点打印出来 题目链接:牛客网-二叉树遍历 前序遍历创建树的思想: 把每个结点看作是子树的根节点,以根左右的顺序创建一整棵二叉树 1.空 返回空 2.非空 先是malloc一个结点ÿ…...
OceanBase数据库-学习笔记2-C#/C++程序如何访问
MySQL模式下,程序(C#)连接数据库操作demo SqlSugar public class MainModel {private static readonly ConnectionConfig connectionConfig new ConnectionConfig(){ConnectionString "serverxxx.xxx.xxx.xxx;port2881;user idroot;…...
Python中的Walrus运算符分析
Python中的Walrus运算符(:)是Python 3.8引入的一个新特性,允许在表达式中同时赋值和返回值。它的核心作用是减少重复计算,提升代码简洁性。以下是其适用的典型场景及示例: 1. 在循环中避免重复计算 当循环条件需要多次…...
【深度好文】4、Milvus 存储设计深度解析
引言 作为一款主流的云原生向量数据库,Milvus 通过其独特的存储架构设计来保证高效的查询性能。本文将深入剖析 Milvus 的核心存储机制,特别是其最小存储单元 Segment 的完整生命周期,包括数据写入、持久化、合并以及索引构建等关键环节。 …...
航顺 芯片 开发记录 (一) 2025年4月27日19:23:32
芯片型号: HK32F030MF4P6 第一步:创建工程目录 inc :头文件目录 MDK-ARM : 工程根目录 (新建工程选择该目录) src :相关资源存放位置 官方函数库相关内容 官方函数库大致结构图 ├─HK32F030MLib ├─CMSIS │ ├─CM0 │ │ └─Core │ │ arm_common_table…...
Java 设计模式
Java后端常用设计模式总览表 模式核心思想Spring / Spring Boot应用手写实现核心单例模式 (Singleton)一个类只有一个实例,提供全局访问点Spring容器中的默认Bean都是单例管理volatile synchronized 双重检查锁定,懒加载单例工厂模式 (Factory)统一管理…...
Milvus如何实现关键词过滤和向量检索的混合检索
Milvus 可以实现关键词过滤和向量检索的混合检索,具体来说,可以结合向量搜索与其他属性字段(如关键词、类别标签等)进行联合查询。这样,在检索时不仅考虑向量的相似度,还能根据特定的关键词或标签等条件对数据进行筛选,从而提高检索的精度和灵活性。 1. 理解混合检索的…...
基于Qt5的蓝牙打印开发实战:从扫描到小票打印的全流程
文章目录 前言一、应用案例演示二、开发环境搭建2.1 硬件准备2.2 软件配置 三、蓝牙通信原理剖析3.1 实现原理3.2 通信流程3.3 流程详解3.4 关键技术点 四、Qt蓝牙核心类深度解析4.1 QBluetoothDeviceDiscoveryAgent4.2 QBluetoothDeviceInfo4.3 QBluetoothSocket 五、功能实现…...
Linux日志处理命令多管道实战应用
全文目录 1 日志处理1.1 实时日志分析1.1.1 nginx日志配置1.1.2 nginx日志示例1.1.3 日志分析示例 1.2 多文件合并分析1.3 时间范围日志提取 2 问题追查2.1 进程级问题定位2.2 网络连接排查2.3 硬件故障追踪 3 数据统计3.1 磁盘空间预警3.2 进程资源消耗排名3.3 HTTP状态码统计…...
Node.js CSRF 保护指南:示例及启用方法
解释 CSRF 跨站请求伪造 (CSRF/XSRF) 是一种利用用户权限劫持会话的攻击。这种攻击策略允许攻击者通过诱骗用户以攻击者的名义提交恶意请求,从而绕过我们的安全措施。 CSRF 攻击之所以可能发生,是因为两个原因。首先,CSRF 攻击利用了用户无法辨别看似合法的 HTML 元素是否…...
线性代数—向量与矩阵的范数(Norm)
参考链接: 范数(Norm)——定义、原理、分类、作用与应用 - 知乎 带你秒懂向量与矩阵的范数(Norm)_矩阵norm-CSDN博客 什么是范数(norm)?以及L1,L2范数的简单介绍_l1 norm-CSDN博客 范数(Norm…...
微服务基础-Ribbon
1. Ribbon简介: 客户端的负载均衡: 2....
移除生产环境所有console.log
大多数团队都会要求不能在生产环境输出业务侧的内容,但是往往业务开发人员会有疏漏,所以需要在工程化环境中,整体来管理console.log。我最近也是接到这样一个需求,整理了一下实现方案。 不同团队,不同场景,…...
数字人接大模型第二步:实时语音同步
接上例第一步,还是dh_live项目,增加了一个完整的实时对话样例,包含vad-asr-llm-tts-数字人全流程,以弥补之前的只有固定的问答的不足。 VAD(Voice Activity Detection,语音活动检测)VAD用于检测用户是否正在说话,从而触发后续的语音处理流程。 ASR(Automatic Speech R…...
Tomcat的安装与配置
Tomcat Tomcat是一个Java圈子中广泛使用的HTTP服务器. 后续学习Severlet内容,就是依赖Tomcat. Java程序员,要想写个网站出来,绕不开Tomcat. 我们这里使用Tomcat8 在bin目录下,这两个文件尤为重要,需要说明的是,Tomcat是那Java写的,所以在运行时需要jdk. bat后缀:是Window…...
Spring AI Alibaba - MCP连接 MySQL
先看效果 直接问他数据库有什么表。 大模型调用MySQL进行查询 搭建项目 添加依赖 创建项目后新添加Maven 依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> …...
Spring Cloud Stream喂饭级教程【搜集全网资料整理】
文章较长,建议收藏关注,随时查看 Spring Cloud Stream 简介 Spring Cloud Stream 是 Spring 提供的一个框架,用于构建与共享消息系统相连接的高度可伸缩的事件驱动微服务,它建立在 Spring 已有的成熟组件和最佳实践之上ÿ…...
prometheus手动添加k8s集群外的node-exporter监控
1、部署node-exporter 1)helm方式部署 rootiZj6c72dzbei17o2cuksmeZ:~# helm repo add prometheus-community https://prometheus-community.github.io/helm-charts "prometheus-community" has been added to your repositories rootiZj6c72dzbei17o2cu…...
Linux(Centos版本)中安装Docker
文章目录 Linux(Centos版本)中安装Docker整体流程 Linux(Centos版本)中安装Docker整体流程 进入root权限进行安装: 下面开始安装Docker: 1、安装docker的yum管理工具:记得将yum仓库更改为国内的镜像源&…...
C语言-- 深入理解指针(4)
C语言-- 深入理解指针(4) 一、回调函数二、冒泡排序三、qsort函数3.1 使用qsort函数排序整型数据3.2 使用qsort函数排序double数据3.3 使用qsort来排序结构体数据 四、模仿qsort库函数实现通用的冒泡排序4.1 通用冒泡排序函数排序整型数据4.2 通用冒泡排…...
牟乃夏《ArcGIS Engine地理信息系统开发教程》学习笔记3-地图基本操作与实战案例
目录 一、开发环境与框架搭建 二、地图数据加载与文档管理 1. 加载地图文档(MXD) 2. 动态添加数据源 三、地图浏览与交互操作 1. 基础导航功能 2. 书签管理 3. 量测功能 四、要素选择与属性查询 1. 属性查询 2. 空间查询 五、视图同步与鹰眼…...
Spark Streaming实时数据处理实战:从DStream基础到自定义数据源集成
park-Streaming概述 Spark-Streaming是什么 Spark Streaming 用于流式数据的处理。Spark Streaming 支持的数据输入源很多,例如:Kafka、Flume、Twitter等,以及和简单的 TCP 套接字等等。数据输入后可以用 Spark 的高度抽象原语如:…...
微软GraphRAG的安装和在RAG中的使用体会
文章目录 0. 简介(1)**技术原理**(2)**优势**(3)**开源与演进** 1. 下载graphrag.git2.安装 poetry3.初始化项目:建立cases目录4. 修改.env5.修改settings.yaml,将两处 api_base改成中转站地址:…...
Python学习记录7——集合set()的使用指南
文章目录 引言一、集合特性二、创建方式三、元素操作1、添加元素(1)add(element)(2)update(iterables) 2、删除元素(1)remove(element)(2)discard(element)(3)…...
apkpure 谷歌插件 下载的apk包
谷歌插件市场搜索 apkpure 然后直接搜索下载就行了 想看apk包中的静态资源,直接改apk 为zip后缀解压就行了 apple的ipa包也是相同的道理...
Android四大核心组件
目录 一、为什么需要四大组件? 二、Activity:看得见的界面 核心功能 生命周期图解 代码示例 三、Service:看不见的劳动者 两大类型 生命周期对比 注意陷阱 四、BroadcastReceiver:消息传递专员 两种注册方式 广播类型 …...
WSL2里手动安装Docker 遇坑
在 WSL2 里手动安装 Docker Engine 时遇坑:systemctl 和 service 命令在默认的 WSL2 Ubuntu 中 无法使用,因为 WSL2 没有 systemd。怎么办? 自己操作让 Docker Engine(dockerd)直接跑起来,挂到 /var/run/do…...
【ROS2】ROS开发环境配置——vscode和git
古月21讲-ROS2/1.系统架构/1.5_ROS2开发环境配置/ ROS机器人开发肯定离不开代码编写,课程中会给大家提供大量示例源码,这些代码如何查看、编写、编译 安Linux中安装装git sudo apt install git下载教程源码 《ROS2入门21讲》课程源码的下载方式&#x…...
django.db.models.query_utils.DeferredAttribute object
在 Django 中,当你看到 django.db.models.query_utils.DeferredAttribute 对象时,通常是因为你在查询时使用了 only() 或 defer() 方法来延迟加载某些字段。这两个方法允许你控制数据库查询中的字段加载方式,从而优化查询性能。 only() 方法…...
Linux内核中的编译时安全防护:以网络协议栈控制块校验为例
引言:内存安全的无声守卫者 在操作系统内核开发中,内存溢出引发的错误往往具有极高的隐蔽性和破坏性。Linux内核作为承载全球数十亿设备的基石,其网络协议栈的设计尤其注重内存安全性。本文通过分析一段看似简单的内核代码,揭示Linux如何通过编译时静态检查(Compile-Time…...
第11章 安全网络架构和组件(一)
11.1 OSI 模型 协议可通过网络在计算机之间进行通信。 协议是一组规则和限制,用于定义数据如何通过网络介质(如双绞线、无线传输等)进行传输。 国际标准化组织(ISO)在20世纪70年代晚期开发了开放系统互连(OSI)参考模型。 11.1.1 OSI模型的…...
Git常用命令简明教程
本教程整合并优化了Git核心命令,涵盖初始化、配置、文件操作、分支管理、远程仓库操作及常见场景,适合快速入门和日常参考。命令按使用流程分组,简洁明了,包含注意事项和最佳实践。 1. 初始化与配置 初始化Git仓库并设置基本配置…...
在 Ubuntu 24.04 系统上安装和管理 Nginx
1、安装Nginx 在Ubuntu 24.04系统上安装Nginx,可以按照下面的步骤进行: 1.1、 更新系统软件包列表 在安装新软件之前,需要先更新系统的软件包列表,确保获取到最新的软件包信息。打开终端,执行以下命令: …...
数据结构——二叉树和堆(万字,最详细)
目录 1.树 1.1 树的概念与结构 1.2 树相关的术语 1.3 树的表示法 2.二叉树 2.1 概念与结构 2.2 特殊的二叉树 2.2.1 满二叉树 2.2.2 完全二叉树 2.3 二叉树存储结构 2.3.1 顺序结构 2.3.2 实现顺序结构二叉树 2.3.2.1 堆的概念与结构 2.3.2. 2 堆的插入与删除数据…...
IdeaVim 配置与使用指南
一、什么是 IdeaVim? IdeaVim 是 JetBrains 系列 IDE(如 IntelliJ IDEA, WebStorm, PyCharm 等)中的一个插件,让你在 IDE 里使用 Vim 的按键习惯,大大提升效率。 安装方法: 在 IDE 中打开 设置(Settings) →…...
前端浏览器窗口交互完全指南:从基础操作到高级控制
浏览器窗口交互是前端开发中构建复杂Web应用的核心能力,本文深入探讨23种关键交互技术,涵盖从传统API到最新的W3C提案,助您掌握跨窗口、跨标签页的完整控制方案。 一、基础窗口操作体系 1.1 窗口创建与控制 // 新窗口创建(现代浏…...
考研系列-计算机组成原理第五章、中央处理器
一、CPU的功能及结构 1.运算器的基本结构 2.控制器结构...
python+flask+flask-sockerio,部署后sockerio通信异常
前言 用python开发了一个flask web服务,前端用html,前后端通过socketio通信,开发环境,windowsminicondavscode,开发完成后本地运行没有问题,然后就开始部署,噩梦就开始了。 问题描述 程序是部…...
深度解析:TextRenderManager——Cocos Creator艺术字体渲染核心类
一、类概述 TextRenderManager 是 Cocos Creator 中实现动态艺术字体渲染的核心单例类。它通过整合资源加载、缓存管理、异步队列和自动布局等功能,支持普通字符模式和图集模式两种渲染方案,适用于游戏中的动态文本(如聊天内容、排行榜&…...
同样开源的自动化工作流工具n8n和Dify对比
n8n和Dify作为两大主流工具,分别专注于通用自动化和AI应用开发领域,选择哪个更“好用”需结合具体需求、团队能力及业务场景综合判断。以下是核心维度的对比分析: 一、核心定位与适用场景 维度n8nDify核心定位开源全场景自动化工具ÿ…...
设计模式每日硬核训练 Day 16:责任链模式(Chain of Responsibility Pattern)完整讲解与实战应用
🔄 回顾 Day 15:享元模式小结 在 Day 15 中,我们学习了享元模式(Flyweight Pattern): 通过共享对象,分离内部状态与外部状态,大量减少内存开销。适用于字符渲染、游戏场景、图标缓…...