0%
一、前言
1. 影响缓存命中率的因素
2. 缓存为什么可以提升性能
- 缓存来自内存,比磁盘访问更快
- 减少数据库、磁盘和网络的压力,减少cpu的io时间
- 缓存最终结果,不需要再次计算
3. 各种介质数据访问延迟
操作类型 | 大致时间 |
---|
本地内存 | 100ns |
SSD磁盘搜索 | 100000ns |
网络数据包在同一个数据中心来回时间 | 500000ns |
非ssd磁盘搜索 | 10000000ns |
按顺序从网络读取1MB数据 | 10000000ns |
按顺序从非ssd磁盘读取1MB数据 | 3000000ns |
跨大西洋网络数据包来回时间 | 150000000ns |
每秒 | 1000000000ns |
二、缓存分类和添加原则
1. 使用场景分类
私有缓存
共享缓存
2. 存储位置分类
本地缓存
分布式缓存
3. 实现方式分类
代理缓存
反向代理缓存
- 反向代理是在数据中心侧缓存,用户连接数据中心先连接反向代理服务器进行缓存查找
- 可以使用多层反向代理实现缓存
CDN缓存
- 内容分发网络,为网络服务商提供的服务,不在客户端也不在数据中心
- 第一个请求到数据中心,返回页面中的各项静态资源地址为cdn的服务器,客户端请求cdn的服务器获取资源
- 由cdn请求数据中心然后缓存到cdn服务器上返回
4. 数据来源分类
通读缓存
- 客户端只从缓存服务器获取数据,失效由缓存服务器进行请求后返回
旁路缓存
- 客户端先从缓存服务器获取,失效直接请求数据中心,如对象缓存
三、缓存问题和解决
1. 缓存击穿
- 缓存击穿是指缓存中没有但是数据库中有的数据,一般是缓存到期。由于并发用户特别多,同时读缓存没有读到数据,就到数据库进行查询而形成压力
1.1. 解决方案
2. 缓存雪崩
- 缓存雪崩是指同一时间缓存大面积失效,所有请求都会落到数据库上,造成数据库短时间处理大量请求而崩掉
2.1. 解决方案
- 缓存数据的过期时间要随机设置,防止同一时间大量数据过期
- 给每个缓存数据添加缓存标记,记录缓存是否失效,标记失效立即更新,消耗较大,需要做监控
- 缓存预热,系统刚启动时先不对外提供服务,先将数据存入缓存再对外提供数据
- 互斥锁,对于某个key进行互斥,只让少量请求进行数据库操作,其余的进行排队,然后更新到缓存后就可以对缓存进行操作
3. 缓存穿透
- 缓存穿透是指缓存和数据库中都没有数据,导致所有请求都落到数据库上
- 一般是攻击数据库会造成
3.1. 解决方案
- 接口层增加校验,用户鉴权、id格式校验等
- 从缓存和数据库都取不到的数据,设置key-value为key-null,有效时间可以短一点,防止用户使用同一个key进行攻击
- 使用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一定不存在的数据会被bitmap进行拦截,减少对底层数据库的查询
4. 热key问题的处理
4.1. 添加本地缓存
4.2. 热key探查
- 集群环境下,所有流量会分布到不同设备上,在客户端进行探查会不够真实,所以一般是在客户端到redis之间添加proxy进行热key探查
1) 京东
- 在客户端和redis之间添加一层proxy,proxy对所有key进行访问统计
- 推送到客户端上,客户端对热key进行本地缓存
2) 阿里云
- 同样是proxy,但是热key的缓存放到proxy上,不会推送给客户端
5. 不需要使用缓存的场景
5. 缓存失效方式
四、分布式对象缓存
1. 查找缓存方式
- 使用客户端里面的路由算法来查找到哪个服务器
- 再通过通讯模块进行连接访问
2. 路由算法
2.1. 余数hash
- 使用取余来查找服务器
- 如果添加服务器,可能造成缓存雪崩,因为余数不一致
2.2. 一致性hash
- 一般环取 $2^{32}-1$
- 将节点计算hash放到环上,对key也计算hash在环上查找后面最近的节点,缓存就在此节点
- 可以动态扩容服务器,不会影响原有的节点hash和分布,仅影响最近的一个节点,部分key会查找到此节点
- 由于hash值不确定,可能会造成部分节点数据很多,部分很少,添加一个节点并不能分担大部分节点压力,仅能影响最近的节点
2.3. 一致性hash改进(虚拟节点)
- 物理节点分为多个虚拟节点,将虚拟节点加到环上
- 单个物理节点加入,由于虚拟节点很多,所以可以分担大部分节点压力
微信支付
支付宝