缓存读写代码逻辑的准确姿势 [复制链接]
发表于 2026-1-31 02:11:15 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
缓存通常用于进步数据访问的服从。一样平常来说,缓存读取和写入的逻辑遵照“先从缓存取,取不到再从数据库获取并写回缓存”的原则。为了制止多个线程同时修改缓存数据,我们须要加锁来包管数据同等性。
逻辑概述


  • 读取缓存:缓存掷中直接返回。
  • 缓存未掷中:加锁,然后再次读取缓存,缓存掷中直接返回。
  • 缓存照旧未掷中:实验数据库查询并更新缓存。
  • 返回数据。
代码大抵如许写
  1. public class CacheService
  2. {
  3.     private readonly ICache _cache;
  4.     private readonly IDatabase _database;
  5.     private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
  6.     public CacheService(ICache cache, IDatabase database)
  7.     {
  8.         _cache = cache;
  9.         _database = database;
  10.     }
  11.     public string GetDataFromCacheOrDb(string key)
  12.     {
  13.         // 1. 尝试从缓存获取数据
  14.         var data = _cache.Get(key);
  15.         if (data != null)
  16.         {
  17.             return data;  // 缓存命中,直接返回
  18.         }
  19.         // 2. 如果缓存中没有,尝试加锁并获取数据
  20.         _semaphore.Wait();
  21.         try
  22.         {
  23.             // 再次检查缓存(可能另一个线程已经填充了缓存)
  24.             data = _cache.Get(key);
  25.             if (data != null)
  26.             {
  27.                 return data;  // 缓存命中,直接返回
  28.             }
  29.             // 3. 从数据库获取数据
  30.             data = _database.Query(key);
  31.             // 4. 将数据写入缓存
  32.             _cache.Set(key, data);
  33.             return data;
  34.         }
  35.         finally
  36.         {
  37.             // 释放锁
  38.             _semaphore.Release();
  39.         }
  40.     }
  41. }
复制代码
关键是缓存在锁前和锁后都要读一次,为了镌汰多个线程都在等候锁的环境,同时进来查询数据库写缓存。

分布式环境下会更复杂一些


免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金.
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表