缓存穿透导致数据库性能不稳定

事件描述 && 解决过程

  1. DAY1 19:47 业务新增一个访问接口来增加网站的访问量 。业务访问量比较少,当天没有发现问题。

2.DAY2 下午业务开发联系我们,发现了一些下面的错误:

### Error querying database.  Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object

通过 google 可以发现是MySQL 的dbcp 连接池上的连接数使用完了,新的 client 请求没法获取可使用的连接池,等待超时。

3.当时首先想到的是增加连接池的最大连接数,咨询了下开发,连接数从原来的50增加到 100.

4.随后数据库服务器开始出现突然的 load 飙到40+,然后瞬间降到0.1 左右,业务数据量很少,请求频率也不高,每次报警的时候上去看了下,发现连接都不多,只有10+个用户连接。

5.第一步确认下是不是 Linux Server 本身问题呢?联系 SA ,SA 大大说可能是 xfs 文件系统的一个bug。可是数据库系统都是统一配置的,为什么就这个机器有问题呢?当时后面 SA 的建议是迁移走数据,机器升级。

6.随后数据库稳定,就没有继续追究,先看看连接数增加到 100 是否有效果。如果不行,考虑准备迁移走业务、升级机器。 [虽然业务量不大,但是物理机器上好几个 MySQL 小业务,迁移都需要联系对应的开发,也是个辛苦活。]

7.DAY3 8:30 数据库 load 继续忽高忽低,DBA 接收到断线报警,查看监控平台信息,只有 cpu 的使用率也随着 load 呈现相似变化。登录到数据库机器上看的时候,load 变得很低,top 查看进程的资源消耗也很低。找了一个资深的 SA 大大帮忙看了下,麻烦他确认下是不是Linux 系统问题。

8.SA 大大开了多终端,看了下 Linux机器的信息,发现没有啥问题,但是他在top 监控机器的过程中突然发现 MySQL 的cpu 使用率瞬间达到2000%,然后几秒后又很低甚至消失在top 的前几个资源进程消耗上。

9.DAY3 9:10 左右DBA[调侃他下]开始 top 和 show processlist 来实施捕捉 MySQL 的进程状况,发现每过4-5min 左右,就会大量的出现 select now() from dual 和 select user()的请求,那个时间的相关业务连接数的确也非常高,接近100.

10.最后让业务开发检查下原因。

10.1 诊断期间有修改 dbpc 的配置,比如 validationQuery 从 select now() 改为 select 1, timeBetweenEvictionRunsMillis 和 minEvictableIdleTimeMillis 从1000 改为 3min ,5min 。 [效果不大]

10.2 最后是开发那边对缓存上了 lock,避免缓存穿透,效果明显。

解释:如果多个client发现缓存数据失效,只允许一个线程从数据库读取数据,放置到缓存供后续的请求读取。这样可以有效的避免当缓存失效的时候[开发设置5min],所有的 client 请求都下发到 DB ,造成DB 瞬间的请求处理请求数量增加,从而 cpu 和load 自然暴涨起来了。

事后总结

虽然这个事情最后是解决了,但是我发现这次解决问题的思路还是有些问题的。我就马后炮的总结下诊断事故的正确姿势。

1.业务开发给出错误以后,DBA 首先看看出错日志的原因。比如这次是连接池等待资源超时。

2.DBA 要连接到数据库机器上,查看当前的数据库资源使用情况,对应实例的连接情况,是否有阻塞的SQL等,确保其他业务还能正常使用。[一个 MySQL 实例可能有多个业务在上面]

3.咨询开发人员,这个业务什么时候开始出现这些错误的,错误频率如何 .[这个当时没有咨询,只是考虑到可能是我们数据库这边出现了问题]

3.1 如果是最近出现问题 && 并且数据库没有做任何变更,就要咨询是否最近业务是否变更、请求量是否最近有增加。[太重要了!!!业务更新不是每次都会通知DBA的]

3.2 如果业务让然没有变更,看看数据库服务器历史资源使用情况 [比如最近几天的load cpu io tcp 连接数变化等],一来是看看数据库最近的变化,二来看看是否是其他业务导致了这个业务受到影响。

4.看看慢查询日志,查看最近是否有高频并且占用资源较高的SQL。

5.如果的确没有什么请求量,数据库这边没有啥动静,并且业务出现错误了,可能需要其他专业人士 SA 也来帮忙看下,是否是 Linux 机器本身的问题,或者是网络问题。

容易陷入的陷阱:

1.没有数据库自我检查结束,就潜意识以为是DB 问题,其他方面出现问题的可能性没有考虑全[硬件、网络、业务本身问题]。

2.处理问题的全局性不够,没有再次出现问题就以为事情解决了,也没有后续跟进修改业务参数以后的效果。

posted @ 2017-03-30 17:45  流水无情88  阅读(1286)  评论(0编辑  收藏  举报