• 走进缓存的世界(一)


    系列文章

    概述

    对于程序员来说多多少少都懂一点算法,算法是什么?算法是“时间”与“空间”的互换策略。

    我们常常研究一个算法的时间复杂度和空间复杂度,如果我们有绝对足够的时间和空间,那么算法就不需要了,可惜这种条件是不存在的,只是在某些情况下我们会协调两者从而达到性能上的平衡。

    缓存是一种“用空间换时间”的策略,通俗的讲,缓存就是把一些数据暂时存储起来,避免了某些重复的耗时操作,减少时间开销的一种方法。

    商业世界中常说的一句话是“现金为王”。在技术世界里,与之相近的一个说法是“缓存为王”。

    从底层到上层主要涉及:数据库模型设计,SQL优化,使用缓存等。从图中的优化模式来看,其中数据库模型设计的合理程度奠定了应用系统优化的基石,如果模型设计得不合理,随着业务发展,后续的优化将会变得很困难。另一方SQL优化也是数据库优化的一个重要方面,慢SQL和top SQL往往是系统性能杀手,它们是导致系统故障的重要潜在危险。

    缓存在构建高性能服务器中有着举足轻重的作用,很多时候sql优化, 算法优化所带来的效果可能远远不如缓存带来的优化效果。但是缓存的使用并不是零成本的,任何缓存的增加,都会带来两大问题:

    • 数据不一致
    • 系统复杂度大幅度增加

    如何解决呢?首先考虑去掉缓存。不要为了缓存而缓存,缓存不必要时,应该果断去掉,从而降低系统出错的可能性和系统复杂度。有些对数据实时性,准确性要求极高的系统,不能使用缓存。其次是分析需求,不同的业务会有不同的缓存策略,仔细分析变化与不变的数据,将不变的数据长时间缓存,变化的数据根据数据的业务要求动态调整缓存时间和存储方式。最后就是增加开发人员自身的能力,后面会详细提及各种问题的处理方法。

    什么样的缓存才是好缓存

    什么样的员工是好员工?最直接最本质的回答:能办事、且办事靠谱就是好员工,答案并不是聪明、勤奋、社交好等等,这些只是成为一个靠谱员工的充要条件。

    什么样的缓存才是好缓存呢?答案是:命中率高的缓存。

    在解决问题前提下,命中率高的缓存比命中率低的缓存,在硬件投入上一般会小很多,缓存数量比命中率低的缓存数量也少很多,寻址速度肯定也比较快,所以命中率高的缓存是好缓存。

    缓存的设计需要考虑缓存的占用空间和命中率。我们当然希望缓存占用空间小,命中率高。命中率高是缓存设计的重要考察因素, 是提高系统性能的关键。占用空间越小,需要的成本越低。低成本,高效能的缓存设计是我们追求的目标。这没有固定的设计方法和公式,需要根据不同的业务灵活调整,但是,关于缓存在业务开发中的设计方法,有一些比较常用的思路与模式,借鉴这些模式,我们可以复用或创新,解决新的业务中所出现的问题。

    缓存的命中率

    一个实体丢到缓存中后,在被缓存期间,如果一次都没有使用过,这个缓存实体的命中率就是0。这个实体被请求的次数越多,缓存命中率越高。

    上面说的是缓存中一个实体的命中率。对于缓存整体来说,命中率=命中数/总查找数。

    对于缓存来说:通常最常使用的个体占总体的很小一部分,最不常使用的占整体的很大一部分.。

    所以我们经常会看到类似这样的数据:

    缓存的1万个元素中,有100个被频繁的使用,几乎每分钟都会被使用一次。2000个数据,每小时被请求一次。3000个数据,每天被请求一次,剩下的数据,被丢到缓存中后一次都没有被使用过。

    现在硬件发展很快,如果我们只是需要缓存1万个数据的话,我们完全可以做到不管这1万个数据是否被使用到,全部丢到缓存,这样只要找数据,肯定缓存中有这个数据。而不需要作额外的运算,或者不需要向数据库发出请求。

    但是:硬件发展快,数据量发展也快。小型的网站,缓存1万条数据,也就全部缓存了。但是大型网站最少也是上百万的数据量或者上T级别的数据,这些数据量显然不能都丢到缓存。这时候设计一个合理的缓存方案,提高缓存的命中率,就非常重要而且是必须的。

    如何提高缓存命中率

    纯技术的角度来说,我们只有记录了用户单位时间的请求数,并依照它来把最常使用的数据缓存起来,从而提高缓存命中率。

    但更多的时候,我们是根据业务逻辑来提高缓存命中率的。比如:去年,前年发表的博客,这类文章的浏览请求,一般一天也就几次访问,不应该缓存到内存中。

    我们应该通过上面逻辑,根据我们实际业务逻辑,提供一个缓存算法,提高缓存的命中率。让在我们硬件允许的条件下,缓存适当的数据,而不是所有数据。

    一个反面的例子就是:不管三七二十一,一个大型的博客站点,一篇文章被用户请求的时候,发现不在内存缓存中,就从数据库中读出,然后丢到缓存。

    要知道,现在爬虫程序很多的。另外,博客这类搜索引擎友好的站点,绝大多数访问压力是搜索引擎导入的。而这些访问一般都是1小时,或者1天之内,对某篇文章只有几次甚至1次请求,之后再也没有了,这种缓存方法,命中率会非常低。

    说了这么多缓存命中率的问题,简单汇总一下缓存命中率的观点:

    • 小型网站可以全部缓存,压力也不会很大,可以忽略缓存命中率问题
    • 大型服务无法全部缓存,时候就需要架构师设计出对该业务逻辑适用的缓存方法,尽可能提高缓存命中率
    • 提高命中率的方法大多是跟业务逻辑捆绑的,需要跟具体问题具体分析
    • 对于不能被内存缓存的数据,最简单的提高性能方法就是使用文件缓存
    • 文件缓存可以整个内容缓存成一个静态文件,也可以是整个页面的一个区域被缓存成一个文件,也可以是把一个实体序列化成XML文件进行缓存

    过期策略

    缓存是临时的存储,所以缓存的生命周期是有限的。它依次可能会经历如下活动:

    • 进入缓存
    • 正常使用期
    • 更新缓存
    • 离开缓存

    最常见的几种过期策略如下:

    多长时间没有被请求,则过期,最典型的就是ASP的Section 功能。

    依赖于文件变更的缓存,一旦文件被修改,则过期,典型的是WEB站点的Web.config,一旦这个文件变更,不但缓存重起,IIS进程也会进行一次释放工作。

    在此基础上,引申出很多依赖关系的缓存过期策略,比如依赖于数据库的缓存过期策略。

    当然,业务逻辑里可能会有更复杂的过期策略,比如CSDN新版积分制论坛中,帖子列表缓存会在列表数据缓存达到600时,把它清理到550条数据。

  • 相关阅读:
    LeetCode 453 Minimum Moves to Equal Array Elements
    LeetCode 112 Path Sum
    LeetCode 437 Path Sum III
    LeetCode 263 Ugly Number
    Solutions and Summay for Linked List Naive and Easy Questions
    AWS–Sysops notes
    Linked List
    All About Linked List
    datatable fix error–Invalid JSON response
    [转]反编译c#的相关问题
  • 原文地址:https://www.cnblogs.com/crazyacking/p/5793239.html
Copyright © 2020-2023  润新知