态度决定一切

0%

账号中心异常日志问题排查

今天上午发现调用账号中心接口异常,于是立马去线上查看日志发现了大量的异常信息,异常日志如下:

1
Error querying database.  Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

于是上网查了下相关文章,给出如下解释

MySQL默认连接存活时长为28800秒,即8小时。如果在wait_timeout期间内,数据库连接(java.sql.Connection)一直处于等待状态,MySQL就将该连接关闭。此时,数据库连接池仍然合法地持有该连接,当用该连接来进行数据库操作时,就报上述错误。

查了下线上账号中心库的 wait_timeout时间为259200s=3天

确实从异常日志文件也能看到异常信息:

1
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 1,536,593,656 milliseconds ago.  The last packet sent successfully to the server was 1,536,593,656 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.

从日志文件看出有些数据库操作正常的,有些查询是异常的,所有猜测大概是数据库连接池中部分链接其实已经断开。

其中异常日志也给出了原因和响应的解决办法:

1
or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.

方法一:
即使用autoReconnect=true来避免面这个这个问题,但是查了下配置文件中发现已经配置了此参数

1
xxxauth.datasource.url=jdbc:mysql://xxxxx?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&rewriteBatchedStatements=TRUE&useSSL=false

既然已经配置了那为什么还有这个问题,于是查了想相关文档
autoReconnect=true这个参数对 mysql5以上的版本不生效,现在公司 mysql 使用的都是5.6版本,所以这个方法不行。

方法二:
将数据库 wait_timeout调大,但是就算调大可能链接空闲等待的时间还是会超出等待时间还是不能解决实际问题。

方法三:
数据库连接池配置:testOnBorrow、testOnReturn、testWhileIdle属性,意义分别是取得、返回对象和空闲时,是否进行对象有效性检查,默认都是False关闭状态。只要都设置为True,并提供validationQuery语句即可保证数据库连接始终有效。
检查了下账号中心相关配置

账号中心是有配置但是为啥还是有这个问题?
于是 debug 了下DataSourceConfig这个类加载过程发现这么些个配置文件竟然只加载了前四项
有图有真相

xxxauth.datasource.tomcat开头的都解析不了咯。
继续看,发现如下代码

系统会在家 prefix + “.” + reflaxName的的配置信息,而这里的prefix是在类注解是这样的

1
@ConfigurationProperties(prefix = "xxxauth.datasource")

所以只会加载xxxauth.datasource.test-on-borrow这样的配置加载不到xxxauth.datasource.tomcat.test-on-borrow类似这样的配置。

将配置文件修改

1
2
3
4
5
6
7
8
9
10
11
xxxauth.datasource.driver-class-name=com.mysql.jdbc.Driver
xxxauth.datasource.test-on-borrow=true
xxxauth.datasource.test-while-idle=true
xxxauth.datasource.max-active=30
xxxauth.datasource.test-on-return=true
xxxauth.datasource.test-on-connect=true
xxxauth.datasource.initial-size=10
xxxauth.datasource.min-idle=10
xxxauth.datasource.validation-query=SELECT 1
xxxauth.datasource.validation-interval=5000
xxxauth.datasource.log-validation-errors=true

再次 debug 发现 这些配置以及加载到了

Kafka存储结构详解

1 Topic

  • 用一个Topic的消息可以分布在一个或者多个broker上
  • 一个 Topic 包含一个或者多个 partation
  • 每个消息都属于且仅属于一个Topic
  • Producer 发布数据时,必须指定该消息发布到哪一个 Topic 上
  • Consumer 订阅消息时,必须制定订阅哪个 Topic


阅读全文 »

前言

在介绍 Netty之前一定要先搞明白同步和异步、阻塞和非阻塞、BIO、NIO、AIO 都是什么,然后有哪些优缺点,再来看 Netty 出现的原因,有哪些优势,使用场景是什么。这样循序渐进的学习,更容易理解。

阅读全文 »

实现一个短连接服务

所用技术 功能 完成度
Spring Boot 框架 已完成
MySQL 数据存储 已完成
Redis 二级缓存 X
OpenResty 代理 + 一级缓存 已完成
EhCache 三级缓存 已完成
布隆过滤器 判断hash是否存在 已完成

代码地址

阅读全文 »

代码地址

问题1:如果是先修改数据库,再删除缓存,如果删除缓存失败,那么会导致数据库中的数据是新数据,缓存中的是旧数据
,数据不一致。

解决思路:先删除缓存,再修改数据库,如果删除缓存成功了,修改数据库失败了,那么数据库中是旧数据,缓存中是空的,那么数据不会不一致,因为读的时候缓存没有,则读数据库中旧数据,然后更新到缓存中

Cache Aside Pattern

  • 读的时候,先读缓存,缓存没有的话,那么就读数据库,然后取出数据后放入缓存,同时返回响应

  • 更新的时候,先操作数据库,再删除缓存

1.如果先删除缓存,可能因为并发太大,数据库还没更新老的数据又被另外一个查询放入了缓存,这时候缓存是老数据,数据库是新数据。数据不一致。

2.但是如果先操作数据库,后删除缓存,如果删除缓存失败。缓存是老数据,数据库是新数据,但是删除缓存失败的概率比上面并发造成数据不一致的概率要小得多。但是具体还是要结合场景来考虑

为什么是删除缓存,而不是更新缓存

阅读全文 »