陆迎 發表於 2026-1-30 22:26:00

缓存读写代码逻辑的正确姿势

<p>缓存通常用于提高数据访问的效率。一般来说,缓存读取和写入的逻辑遵循“先从缓存取,取不到再从数据库获取并写回缓存”的原则。为了避免多个线程同时修改缓存数据,我们需要加锁来保证数据一致性。</p>
<h1 id="逻辑概述">逻辑概述</h1>
<ol>
<li>读取缓存:缓存命中直接返回。</li>
<li>缓存未命中:加锁,然后<strong>再次读取缓存</strong>,缓存命中直接返回。</li>
<li>缓存还是未命中:执行数据库查询并更新缓存。</li>
<li>返回数据。</li>
</ol>
<h1 id="代码大致这样写">代码大致这样写</h1>
<pre><code class="language-csharp">public class CacheService
{
    private readonly ICache _cache;
    private readonly IDatabase _database;
    private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);

    public CacheService(ICache cache, IDatabase database)
    {
      _cache = cache;
      _database = database;
    }

    public string GetDataFromCacheOrDb(string key)
    {
      // 1. 尝试从缓存获取数据
      var data = _cache.Get(key);
      if (data != null)
      {
            return data;// 缓存命中,直接返回
      }

      // 2. 如果缓存中没有,尝试加锁并获取数据
      _semaphore.Wait();

      try
      {
            // 再次检查缓存(可能另一个线程已经填充了缓存)
            data = _cache.Get(key);
            if (data != null)
            {
                return data;// 缓存命中,直接返回
            }

            // 3. 从数据库获取数据
            data = _database.Query(key);

            // 4. 将数据写入缓存
            _cache.Set(key, data);

            return data;
      }
      finally
      {
            // 释放锁
            _semaphore.Release();
      }
    }
}

</code></pre>
<h1 id="关键是缓存在锁前和锁后都要读一次为了减少多个线程都在等待锁的情况同时进来查询数据库写缓存">关键是缓存在锁前和锁后都要读一次,为了减少多个线程都在等待锁的情况,同时进来查询数据库写缓存。</h1>
<h1 id="分布式情况下会更复杂一些">分布式情况下会更复杂一些</h1>


</div>
<div id="MySignature" role="contentinfo">
    <div id="AllanboltSignature">
<p id="PSignature" style="border-top-color: #e0e0e0; border-top-width: 1px; border-top-style: dashed; border-right-color: #e0e0e0; border-right-width: 1px; border-right-style: dashed; border-bottom-color: #e0e0e0; border-bottom-width: 1px; border-bottom-style: dashed; border-left-color: #e0e0e0; border-left-width: 1px; border-left-style: dashed; padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 80px; background-image: url(https://images.cnblogs.com/cnblogs_com/pains/109838/r_copyright.png); background-attachment: initial; background-origin: initial; background-clip: initial; font-family: 微软雅黑; font-size: 11px; background-color: #e5f1f4; background-position: 1% 50%; background-repeat: no-repeat no-repeat; ">
作者:Rick Carter
<br />
出处:http://pains.cnblogs.com/
<br />
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
</p>
</div><br><br>
来源:https://www.cnblogs.com/pains/p/19555976
頁: [1]
查看完整版本: 缓存读写代码逻辑的正确姿势