前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从零开始学架构-day05

从零开始学架构-day05

作者头像
袁新栋-jeff.yuan
发布2021-12-07 17:35:53
2670
发布2021-12-07 17:35:53
举报

高性能缓存架构

当服务使用关系型数据库已经达到性能瓶颈的时候我们应该怎么办,数据库已经分片了,也分库分表了,索引什么也都极致了(一般不可能)但是还是扛不住高流量。有点经验的同学都会说:“加缓存,上redis or 直接应用内存(缓存)“。

什么时候用高性能缓存架构?
  1. 需要经过复杂运算后得出的数据,存储系统无能为力
    • 当我们是一个用户中心的系统,需求是提供在线用户的人数,那我们肯定不能去select count(*) 数据库去统计吧,一般
  2. 读多写少的数据,存储系统有心无力
    • 微信,我们每天发不了几个朋友圈,甚至不怎发的,然而我们每天都在看朋友圈(读多写少)
    • 据个人经历,一般C端的系统大多是读多写少的,然而B端一般都是写多读少(但是B端一般流量都不会太大)
  3. 极端的热点数据查询
    • 什么是极端 热点数据? 微博上的热搜,”爆“ ,一时间大家都去看这个点下的数据,微博如果不用缓存的结果是什么,下一个热搜又出来的 ”微博挂掉了“ (开个玩笑)。
什么是高性能缓存架构
  1. 先认识一下什么是缓存
    • 缓存,是一种存储数据的组件,它的作用是让对数据的请求更快地返回。(上面的例子充分体现)
    • 缓存一般都是放在内存中来做的,还有人认为缓存就是内存,这个世界上就没有什么绝对的事情, 见识不够,千万不要妄下定论。(360 开源的 Pika 就是使用 SSD 存储数据解决 Redis 的容量瓶颈的。)一般我们使用内存,因为我们常用的redis就是纯内存来进行存储的.
    • 缓存常见的几种类型: a. 静态缓存:静态缓存在 Web 1.0 时期是非常著名的,它一般通过生成 Velocity 模板或者静态 HTML 文件来实现静态缓存,在 Nginx 上部署静态缓存可以减少对于后台应用服务器的压力 b. 分布式缓存:Memcached、Redis c. 热点本地缓存: 热点本地缓存主要部署在应用服务器的代码中,用于阻挡热点查询对于分布式缓存节点或者数据库的压力,通过应用服务内部的容器进行存储:HashMap(currentHashMap,TreeMap等),Caffeine Cache,Guava Cache等
  2. 使用缓存带来的问题 不得不说,这都快被面试官问烂了,玩归玩,闹归闹,别拿缓存开玩笑(无里头)。来认真看下:
  • 缓存穿透
    1. 缓存穿透是指缓存没有发挥作用,业务系统虽然去缓存查询数据,但缓存中没有数据,业务系统需要再次去存储系统查询数据。
    2. 通常情况下有两种情况:
      • 存储数据不存在,有恶意请求,也有正常请求,请求本来就没有的用户
      • 缓存数据生成耗费大量时间或者资源 ,我们都知道,内存是相对比较贵的资源,我们还是比较 省着点用的,热点缓存,然后到时见失效。(这里的失效只是一部分,也需有同学就会说:这不就是缓存雪崩吗?)
  • 缓存雪崩
    1. 缓存雪崩是指当缓存失效(过期)后引起系统性能急剧下降的情况。其实很好理解也就是超热点的数据,然后key失效,导致查不到这个数据,直接击穿到数据库。
  1. 解决缓存问题的集中策略 大佬们的经验和总结,总结出来集中缓存的策略来解决我们遇到的问题,和缓存设计
  • Cache Aside(旁路缓存)策略 Cache Aside 策略(也叫旁路缓存策略),这个策略数据以数据库中的数据为准,缓存中的数据是按需加载的。它可以分为读策略和写策略, 其中读策略的步骤是:从缓存中读取数据;如果缓存命中,则直接返回数据;如果缓存不命中,则从数据库中查询数据;查询到数据后,将数据写入到缓存中,并且返回给用户。 写策略的步骤是:更新数据库中的记录;删除缓存记录。
  • Read/Write Through(读穿 / 写穿)策略
    1. 这个策略的核心原则是用户只与缓存打交道,由缓存和数据库通信,写入或者读取数据。这就好比你在汇报工作的时候只对你的直接上级汇报,再由你的直接上级汇报给他的上级,你是不能越级汇报的。
    2. Write Through 的策略是这样的:先查询要写入的数据在缓存中是否已经存在,如果已经存在,则更新缓存中的数据,并且由缓存组件同步更新到数据库中,如果缓存中数据不存在,我们把这种情况叫做“Write Miss(写失效)”。
    3. 一般来说,我们可以选择两种“Write Miss”方式:一个是“Write Allocate(按写分配)”,做法是写入缓存相应位置,再由缓存组件同步更新到数据库中;另一个是“No-write allocate(不按写分配)”,做法是不写入缓存中,而是直接更新到数据库中。
    4. 在 Write Through 策略中,我们一般选择“No-write allocate”方式,原因是无论采用哪种“Write Miss”方式,我们都需要同步将数据更新到数据库中,而“No-write allocate”方式相比“Write Allocate”还减少了一次缓存的写入,能够提升写入的性能。
    在这里插入图片描述
    在这里插入图片描述
  • Write Back(写回)策略
    1. 这个策略的核心思想是在写入数据时只写入缓存,并且把缓存块儿标记为“脏”的。而脏块儿只有被再次使用时才会将其中的数据写入到后端存储中。不描述那么多了,有兴趣的可以拜读这篇文章:https://time.geekbang.org/column/article/150881
    img
    img
  1. 说了这么多那到底什么缓存是高性能缓存架构?
  • 那就是我么通过自己的经验和具体的业务逻辑,通过某些缓存中间件设计一个可以达到高性能的高流量的服务架构。(怎么感觉我放了个屁)。
具体实现的一个高性能架构
使用到的中间件

redis ,guava cache , canal mysql kafka 。

业务场景
  1. 后台配置config ,应用需要读取config 进行使用,读取的量很大,有上万级别的QPS,再次更改的时候可以达到实时且安全的更新。
方案
  1. 数据的持久化,mysql
  2. 流量太高,mysql 甚至redis也有点危险,所以两级缓存,redis + guava cache (内存)
  3. 需要实时更新,监听mysql的binlog 发送消息给应用更新内存 canal + kafka (其他的消息队列也没什么问题)
  4. 具体的业务架构图:
在这里插入图片描述
在这里插入图片描述
  1. 看完图,你也许心中会飘过:“画的这是个吊玩意!!!!“ 我接受批评,确实不好看,也不清晰
  2. 我大概描述一下过程:
  • 更新表的过程:
代码语言:javascript
复制
后台更新table a 表,更新后canal监听binlog  通过队列消息推送给应用端,应用端拿到消息后 刷新redis ,

且同时再发送消息给一个内存队列(异步防止这个流程太长),且同时存储内存的时候,将key 存入tableB 中(后续进行对数,防止数据不一致的问题)

  • 重新启动服务的过程:

分页拉去数据库数据,更新进内存和缓存中去。

  • job的作用是每周进行对数: 将内存和数据库,还有guava 中的进行对数更新。
  • 我这只是画了存储的,读取的没有画,大家想想怎么读取数据呢?? (其实是我不想写了)
  • 还有就是这种架构结合上面的集中策略,会有什么问题呢?(我们一块思考一下)

参考

https://time.geekbang.org/column/article/150881

https://time.geekbang.org/column/article/8640

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-06-14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 高性能缓存架构
    • 什么时候用高性能缓存架构?
      • 什么是高性能缓存架构
        • 具体实现的一个高性能架构
          • 使用到的中间件
          • 业务场景
          • 方案
      • 参考
      相关产品与服务
      云数据库 Redis
      腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档