zoukankan      html  css  js  c++  java
  • 缓存应用设计中的经验总结、注意事项

    关注公众号 架构师之路很久,沈剑分享的很多干货,收益良多。结合工作需要整理一下缓存应用中需要注意的问题。

    缓存无处不在,跨进程的缓存:浏览器本地缓存–>cdn–>webServer(Nginx)–>appServer(tomcat,jetty,WAS)–>缓存服务器–>DB。

    缓存的分类介绍

    进程内缓存,一级缓存,二级缓存。

    缓存分类

    本地缓存

    • 特点
      优点:store in jvm;本地访问,快速访问,省去网络开销;各节点独立存储,适合小量数据,只读数据。
      缺点:存储量有限,一份数据复制多份,每个jvm一份,浪费内存,多节点间数据更新同步复杂,影响服务无状态化,开发复杂度提高。
    • 常见实现方式
      HashMap
      ConcurrentHashMap,
      Ehcache
      • 使用场景
        少量高频只读数据
      • 缓存更新方式
        应用启动时,初始化缓存,缓存预热。
        读缓存,过期则 单线程从DB获取数据,存入本地缓存。
        源数据更新,直接删除缓存。 缓存只提供读服务,不做缓存的更新修改。
        多节点部署时,源数据更新,发消息到MQ,各个服务节点消费消息,删除本地缓存。

    缓存服务-分布式缓存服务

    • Redis
    • MemCache
    • Apache Ignite

    缓存常见误用

    现象: 缓存当数据管道使用,多个应用进程读写同一个缓存服务

    • 使用不当原因
      - 应用间耦合严重,缓存偏向于数据存储层,存储直接暴漏给外部系统,架构分层上不合理。
      - 服务器间Rpc通信,暴漏接口,针对接口建立协议,而不是针对实现。
      - 数据权限归属不清
      - 系统读写速度不同,互相影响,资源使用存在争抢问题。
    • 解决方案
      系统间通过服务接口约定交互协议。通过MQ解耦,缓存只是接口实现层面的事情。

    现象:缓存雪崩

    • 原因:缓存服务整体挂掉,导致流量压垮源数据库,导致源数据库启动不了。
    • 解决办法:
      容量规划、缓存水平切分,缓存局部挂掉,不影响整体。
      缓存失效策略
      限流方案

    现象:调用方缓存数据

    • 原因:开发人员原因
    • 解决办法:
      服务方缓存,作为服务的实现方式,对调用方隐藏。服务调用方只通过接口访问数据,客户端与缓存解耦合。

    现象:缓存穿透

    • 原因:访问大量不存在的数据,导致回源流量过大,给DB带来很大压力。

    • 解决办法 :
      缓存空对象。如果缓存未命中,而数据库中也没有这个对象,则可以缓存一个空对象到缓存。如果使用Redis,这种key需设置一个较短的时间,以防内存浪费。
      缓存预测,预测key是否存在,如果缓存的量不大可以使用hash来判断,如果量大可以使用布隆过滤器来做判断.

    • 缓存更新策略
      单线程独立写数据到缓存服务

    缓存、源系统读写一致性问题

    • WriteThrough
    • ReadThrough
      • 什么是“Cache Aside Pattern”?
      • 读过程
        先读cache,再读db
        如果,cache hit,则直接返回数据
        如果,cache miss,则访问db,并将数据set回缓存
      • 写过程
        第一步要操作数据库,第二步操作缓存
        缓存,采用delete淘汰,而不是set更新
        写过程–** 争议的地方**
        考虑DB,缓存服务都是集群的情况:
        1、先写DB,后同步缓存
        正常情况:
        db主–>db从同步完成–>缓存读新值,缓存存放最新的值。
        异常情况:
        db主写–>缓存服务读db从(旧值)–>db从同步新值。缓存存放旧值直到过期。
        解决办法:
        业务需求不要求实时一致,可忽略不处理。
        技术上解决写时的不一致:
      • 第一种办法:
        1、写数据时记录key值到分布式cache.预估数据同步时间段,设置key缓存有效期和同步时间一致。
        2、读数据时,先从分布式cache查询key是否存在,若存在,则数据正在同步中,读节点为脏数据,从主节点读取,不存在,数据没有修改,从节点读取。
        当然这种方案,依赖cache的高可用,只是缩小数据不一致的时间段,同时,
      • 另一种办法
        1、先写DB,db节点数据同步的同时,异步发消息到MQ
        2、缓存服务消费MQ内容,淘汰数据,从主DB同步最新数据。
        此种办法,依赖MQ的高可用,消息有序。

    总之,不管那种方案,基础服务,消息中间件的稳定性、可用性都是必须要有保障的,越基础的越重要。写服务数据主从同步期间,会出现短暂不一致,业务上是否可接受缓存数据的暂时不准确是首先要考虑的。

  • 相关阅读:
    时间控件的操作
    Appium环境搭建
    测试常用英文词汇
    自动化测试中一段代码对应多个用例
    Linux常见命令
    元素的操作的简谈
    eclipse代码编辑界面代码块收缩的实现
    关键字驱动和数据驱动
    uni-app中如何判断浏览器内核
    JS实现 图片放大镜功能
  • 原文地址:https://www.cnblogs.com/coding-now/p/14660599.html
Copyright © 2011-2022 走看看