一、Nuget引入 StackExchange.Redis、DistributedLock.Redis依赖
二、使用 StackExchange.Redis 对redis操作做简单封装
public class RedisHelper { private static ConnectionMultiplexer _redis; private static string _connectionString;// 静态构造函数,确保在程序启动时初始化连接 static RedisHelper() { _connectionString = "127.0.0.1:6379,password=ist123$%^"; // 替换为你的Redis服务器地址和端口,例如:"localhost:6379" _redis = ConnectionMultiplexer.Connect(_connectionString); }// 获取数据库实例 public static IDatabase GetDatabase() { return _redis.GetDatabase(); }// 字符串设置与获取 public static void SetString(string key, string value) { GetDatabase().StringSet(key, value); }public static string GetString(string key) { return GetDatabase().StringGet(key); }// 哈希设置与获取 public static void SetHashField(string key, string field, string value) { GetDatabase().HashSet(key, field, value); }public static string GetHashField(string key, string field) { return GetDatabase().HashGet(key, field); }// 列表操作 public static long ListRightPush(string key, string value) { return GetDatabase().ListRightPush(key, value); }public static string ListLeftPop(string key) { return GetDatabase().ListLeftPop(key); }// 集合操作 public static bool SetAdd(string key, string value) { return GetDatabase().SetAdd(key, value); }public static bool SetRemove(string key, string value) { return GetDatabase().SetRemove(key, value); }public static bool SetContains(string key, string value) { return GetDatabase().SetContains(key, value); }// 键的其他操作 public static bool KeyExists(string key) { return GetDatabase().KeyExists(key); }public static void Remove(string key) { GetDatabase().KeyDelete(key); }// 异步方法示例 public static async Task SetStringAsync(string key, string value) { await GetDatabase().StringSetAsync(key, value); }public static async Task<string> GetStringAsync(string key) { return await GetDatabase().StringGetAsync(key); }// 关闭连接(通常在应用程序关闭时调用) public static void CloseConnection() { if (_redis != null && _redis.IsConnected) { _redis.Close(); _redis.Dispose(); } }}
三、模拟从Redis获取缓存数据的逻辑
/// <summary> /// 模拟操作 /// </summary> public class RedisOper {public static string GetDataByRedis(string RedisKey){string ThreadId = Thread.GetCurrentProcessorId().ToString();string data = string.Empty;//从redis读数据if (RedisHelper.KeyExists(RedisKey)){data = RedisHelper.GetString(RedisKey);Console.WriteLine($"查询到缓存数据:{data} 线程ID:{ThreadId}");}else{Console.WriteLine($"未查询到缓存数据,准备从数据库查询存入缓存 线程ID:{ThreadId}");//模拟从数据库查询存入redis,使用分布式锁,只允许一个请求完成var redisDistributedLock = new RedisDistributedLock("lockkey", RedisHelper.GetDatabase());Console.WriteLine($"尝试获取锁 线程ID:{ThreadId}");using (redisDistributedLock.Acquire()){//再次判断是否存在缓存if (!RedisHelper.KeyExists(RedisKey)){Console.WriteLine($"获取到锁,模拟将数据库数据写入缓存 线程ID:{ThreadId}");var GetDataByDB = "This is test data";RedisHelper.SetString(RedisKey, GetDataByDB);Thread.Sleep(2000);}}}return data;}public static async Task<string> GetDataByRedisAsync(string RedisKey){Console.WriteLine($"当前线程ID:{Thread.GetCurrentProcessorId()}");string data = string.Empty;//从redis读数据if (RedisHelper.KeyExists(RedisKey)){data = await RedisHelper.GetStringAsync(RedisKey);Console.WriteLine($"查询到缓存数据:{data}");}else{Console.WriteLine($"未查询到缓存数据,准备从数据库查询存入缓存");//模拟从数据库查询存入redis,使用分布式锁,只允许一个请求完成var redisDistributedLock = new RedisDistributedLock("lockkey", RedisHelper.GetDatabase());Console.WriteLine($"尝试获取锁 ");using (redisDistributedLock.Acquire()){//再次判断是否存在缓存if (!RedisHelper.KeyExists(RedisKey)){Console.WriteLine("获取到锁,模拟将数据库数据写入缓存");var GetDataByDB = "This is test data";await RedisHelper.SetStringAsync(RedisKey, GetDataByDB);await Task.Delay(2000);}}}return data;} }
四、测试
string redisKey = "testData"; RedisHelper.Remove(redisKey); //模拟10个线程同时去获取Redis缓存 List<Task> tasksList= new List<Task>(); tasksList.Add(Task.Run(()=>RedisOper.GetDataByRedis(redisKey))); tasksList.Add(Task.Run(() => RedisOper.GetDataByRedis(redisKey))); tasksList.Add(Task.Run(() => RedisOper.GetDataByRedis(redisKey))); tasksList.Add(Task.Run(() => RedisOper.GetDataByRedis(redisKey))); tasksList.Add(Task.Run(() => RedisOper.GetDataByRedis(redisKey))); tasksList.Add(Task.Run(() => RedisOper.GetDataByRedis(redisKey))); tasksList.Add(Task.Run(() => RedisOper.GetDataByRedis(redisKey))); tasksList.Add(Task.Run(() => RedisOper.GetDataByRedis(redisKey))); tasksList.Add(Task.Run(() => RedisOper.GetDataByRedis(redisKey))); tasksList.Add(Task.Run(() => RedisOper.GetDataByRedis(redisKey))); Task.WaitAll(tasksList.ToArray()); await Task.Run(() => RedisOper.GetDataByRedis(redisKey));