缓存使用的场景

在一个高频访问的应用系统中,每次用户的请求需要去存储中获取数据,会对数据库造成很大的压力、容易导致数据库的奔溃。所以才会出现缓存来分担一部分的数据库的压力。

具体会产生数据库访问压力的业务场景如下:

1 高频访问数据存储会对数据库的QPS造成很大的压力。

2数据统计类的查询需要消耗很大的数据库cpu、改成由定时任务产生数据推送缓存、每次查询从缓存里面取。

3 业务中产生中间态的数据没有什么业务含义、但有需要有个存储来持久化、所以放到缓存中来。例如验证码、登录的token等。

缓存使用的问题

1 缓存一致性问题

当数据时效性要求很高时,需要保证缓存中的数据与数据库中的保持一致,而且需要保证缓存节点和副本中的数据也保持一致,不能出现差异现象。这就比较依赖缓存的过期和更新策略。一般会在数据发生更改的时,主动移除对应的缓存。

所以需要通过事物机制来保证缓存的一致性。

2缓存高并发访问问题

在高并发场景下,有多个请求去共同请求一份相同的业务数据。有可能多个请求先去从缓存中获取数据、获取不到的并发的去从数据库获取数据,对后端数据库造成极大的冲击,甚至导致 “雪崩”现象。

方案一

可以做一个随机的等待、错峰去访问缓存的信息。这样就能保证同一时刻高并发的访问、经过时间离散之后只有小部分的请求访问数据库、大部分的请求去命中缓存。

方案二

可以按照比例限制有部分数据直接访问数据库然后更新缓存、大部分的数据直接请求缓存。

按照实际的场景去做判断例如 1%的场景直接访问数据库,99%的可以通过缓存获取到数据。

方案一和方案有什么区别呢?大家可以思考下。

3缓存击穿的问题

在系统设计的的时候预期是通过缓存来减轻数据库的压力、防止数据奔溃的情况。在某个实际发生的场景中、大量的请求并没有命中缓存而导致了大量请求达到数据库、从而导致数据库有巨大冲击和压力。

场景一 缓存中没有数据

在某个大促活动中有大量的热点数据,互动一开始需要访问这些数据。由于活动开始的时候洪峰流量到来,所有的请求缓存、缓存直接击穿,访问数据库导致数据库直接cpu 100%,业务系统直接奔溃。

对于这种场景可以提前对数据进行预热,开活动开始前先将数据推送到缓存中。

场景二 缓存集中失效

由于我们在缓存使用的过程中会设置缓存的失效时间、如果设置的不合理可能会导致数据集中失效的情况。由于缓存集中失效会导致系统缓存穿透、在同一时刻高并发的访问数据,造成数据雪崩。

解决这种场景的可以将失效的时间由固定值+随机值来构成。EXPIRE_TIME=FIX_TIME+RUND_TIME 例如你想保证整个EXPIRE_TIME是5S 左右,可以 通过EXPIRE_TIME=4000+Random(1000)

3单条缓存数据过大

我们大多数缓存服务的实现都依赖于内存,而大多数缓存服务在设计的时候都是用来存储很多小数据的内存分配机制。而内存分配算法都是 512 bte ,1k,2k,4k的内存分配机制来确保系统的内存能够容纳更多的记录数。

同时对接持久存储的时候大多都遵循磁盘4k对其的刷盘原理。如果我们存储的一条记录数据超过4K、对整个缓存的性能造成很大的影响。从而导致系统oom。

例如REDIS内存分配策略:

Redis默认内存分配器采用jemalloc,可选的分配器还有:glibe、tcmalloc。

内存分配器是为了更好的管理和重复利用内存,分配内存策略一般采用固定范围的内存块进行内存分配。

这里不去深究jemalloc的内存分配原理,简单地说jemalloc将内存空间划分为三个部分:Small class、Large class、Huge class,每个部分又划分为很多小的内存块单位: 
- Small class: [8byte], [16byte, 32byte, … 128byte], [192byte, 256byte, … 512byte], [768byte, 1024byte, … 3840byte] 
- Large class: [4kb, 8kb, 12kb, … 4072kb] 
- Huge class: [4mb, 8mb, 12mb …]

https://blog.csdn.net/Leon_cx/article/details/82597722

常见使用方式

1定时失效

用发起请求后系统从缓存获取数据、获取不到从数据库获取、获取之后放入到缓存中,设置一个主动失效的时间。

2 主动失效

在数据查询的时候会设置一个时间、超时会依赖缓存自身的机制来失效数据。当数据更新的时候、会主动失效缓存。保证缓存的数据和数据库的数据尽可能一致。

3 定时更新缓存

对于统计类的需求、每次查询需要耗费很多数据库资源、直接查询数据库会严重影响数据库的性能。并且数据变化非常快、采用主动或者被动缓存都会有缓存击穿的风险。所以直接通过定时任务来统计数据、统计完以后会更新到缓存中,每次用去取都是从缓存中查询。这样做会造成缓存中的数据不是实时的,但能确保整个系统的稳定性。

3 按比例放行更新缓存

当用户在大流量访问的时候可以按照比列来更新数据缓存信息 这样既能保证数据的实时性,又能保证数据库的稳定性。在用户访问量小的情况下可以将访问数据库的比列调大一点,在数据访问的高峰期的是可以将比列调小。

最新文章

  1. 使用mac 终端 用sublime 目标文件或目标文件夹
  2. Python中的对象类型的初步介绍
  3. iOS高效开发之Xcode应用插件
  4. 引擎设计跟踪(九.14.2g) 将GNUMake集成到Visual Studio
  5. SpringMVC Cache注解+Redis
  6. 数据文件 和日志文件 收缩 Sql Server
  7. Eclipse的修改编码插件使用
  8. delphi线程的创建、挂起、激活与终止(用绘图做实验,简单又好用)
  9. PAT甲级训练刷题代码记录
  10. 学习MVC之租房网站(六)-用户登录和权限控制
  11. Redis集群之节点管理
  12. Oracle内连接、外连接、右外连接、全外连接小总结
  13. ARDC连接设备异常之ADB version mismatch的处理
  14. TypeError: argument 1 must be an integer, not _subprocess_handle/OSError: [WinError 87]
  15. 产品设计-后台管理权限设计RBAC
  16. UVA11995 I Can Guess the Data Structure!
  17. 微信https抓包,不同安卓版本、微信版本对证书的要求
  18. centos安装htop
  19. Memcached系列之一
  20. Java实现冒泡排序算法

热门文章

  1. 【转】NIO与传统IO的区别
  2. 解决用户绕过Servlet直接访问jsp页面
  3. GetEntryAssembly、GetExecutingAssembly和GetCallingAssembly的区别
  4. Go程序开发---Go环境配置:CentOS6.5+Go1.8标准包安装
  5. Beginner’s Tutorial: 3D Line and Border Effects in XAML
  6. wpf datagrid设置右键菜单打开时选中项的背景色
  7. wpf实现仿qq消息提示框
  8. 【Struts2学习笔记(3)】至Action注入属性值
  9. NSURLSession 网络库 - 原生系统送给我们的礼物
  10. 用MVVM模式开发中遇到的零散问题总结(2)