文档章节

前两天网站访问慢的问题定位过程以及最终解决办法

红薯
 红薯
发布于 08/16 10:15
字数 1732
阅读 5760
收藏 96

前提说明:目前开源中国社区在做改版,因此网站同时存在新旧两种不同的版面,例如个人空间就是新的系统。因此整个网站包含两套系统,改版前和改版后,我们把改版前叫老系统,把改版后叫新系统。

大概一周多的时间,经常会感觉网站,包括客户端使用过程中有卡顿的情况,没太在意。但是前天这个卡顿就变得比较严重,动弹里开始出现各种反应访问慢的信息。

检查所有的机器的 CPU 使用率都在一个正常的状态,Tomcat 无特别的异常日志,应用的数据库连接池的忙连接比平时要高好多倍,但是数据库操作一些正常。

检查数据库慢查询日志,比平时多了一些,基本上集中在近期改版新的 SQL 上,把这些慢查询通过索引调整、SQL 优化方式解决后,慢查询不再出现,但是系统响应速度仍旧没有提升。

我们一度怀疑是数据库响应慢,想重启一下社区的 MySQL 数据库,这个数据库已经运行超过 5 年没重启过了!!!但还是忍住了!再试试其他不行再说。

然后发现了一个非常非常慢的操作,就是在客户端上收藏某篇文章的时候,完全没有响应,或者是要十几秒才有反应。

于是在这个收藏功能对应的代码增加了数据监控点,在日志中记录该方法几个逻辑的执行时间。更新到线上进行测试发现,从在界面上点击收藏,到日志的输出中间隔了好几十秒,而真正功能的执行时间很短。看似有很多请求在排队等 Tomcat 处理导致的堵塞,但是 Tomcat 的日志没有关于处理请求队列慢的日志信息。这是其中一个疑点。

日志显示数据库操作执行十几毫秒,缓存操作一两百毫秒,所以可以确定数据库是没问题的(幸亏没重启)。而缓存操作就算是一两百毫秒也不应该导致这个系统拖得那么慢,但是可以明确的是缓存是肯定有问题的。没准其他更复杂的缓存操作耗时要大很多,导致请求处理的卡顿。

OSChina 一直在用 J2Cache 的两级缓存框架,这个框架有很多人在喷,但是喷的人都没用过它。由于 OSChina 现在整个网站同时运行新老两个系统,因为很多页面还没改版完成。老的系统基于 J2Cache 1.x 运行,新的系统基于 J2Cache 2.x。连接的同一个 Redis 服务,使用不同的 database 进行隔离。

所以我们决定搞一个全新的干净的 Redis ,先把老系统切到这个新的 Redis 服务上,切换后先内部测试,首次访问慢一点,再次访问速度就很快了。切到生产上,所有的用户请求的转到这个系统上,访问速度很快,请求的处理速度一般只有几十毫秒。

运行了半天多,速度仍然很稳定。

但是个人空间依然很慢,因为个人空间是新的系统,接到还是之前的 Redis。于是我们又使用了另外一个独立的全新的 Redis 服务重新部署了一套空间,刚部署上线完后速度很快,但是过了半个小时一个小时候,就开始感觉没那么顺畅了。

在观察系统日志时,同时也发现了我们新的业务代码在缓存处理逻辑上的严重问题,例如生成大量动态的 Region ,而实际使用 Region 不应该这样使用,Region 应该事先在配置文件中定义好的。因为在 J2Cache 中动态创建 Region 是一个线程同步的方法,大量并发请求势必导致等待。

于是我们修改了这部分处理逻辑,不再动态创建大量的 Region ,再次更新后访问速度终于恢复了,注意这里是有两个系统。

新系统运行改版后的页面,老系统运行尚未改版的页面,新老系统通过 Nginx 进行路由。

经过一晚上运行之后,新系统感觉虽然没有之前慢,但是也时常感觉不顺畅!!!但是老系统依然很快。

于是现在的问题是:为什么老系统很快,但是新系统运行一段时间后会变慢。

礼拜二早上醒来觉得不服气,在床上操起电脑继续看各种系统日志和运行状态 —— 发现了两者在使用 Redis 服务上的一个区别:

老系统使用 J2Cache 的 hash 模式在 Redis 存储数据,而新系统使用 J2Cache 的 generic 模式记录数据。也就是说老系统操作 Redis 使用 hget/hset 这些方法,Region 对应的是 Redis 的一个 key,而具体的缓存数据是 key 对应的子 key 。而新系统直接是 get/set 这样的方法,也就是说不同 Region 的所有 Key 都揉在一起形成一个巨大的哈希表。

那么会不会是这个原因导致新系统在运行一段时间后变慢呢?理论上是不应该的,因为 Redis 的处理速度不会因为 key 数量的增加而变慢。但我们还是决定一试。

修改 J2Cache 的配置,将 redis.storage 配置值改为 hash ,清理数据,再次更新系统后,到目前运行已经一整天了,一切非常正常。

自此访问速度问题的处理告一段落。

但是仍有几个疑点没有搞清楚:

  1. 为什么 Tomcat 的请求堵塞那么就没得到处理,却没有异常信息,难道是队列还没满?
  2. 为什么 Redis 在 key 的数量达到一定程度后响应速度变慢呢?我们用的是 Redis 3.0.5 版本
  3. 早在 J2Cache 1.x 的时候,当时 Redis 版本还比较低,好像是 2.x ,那时候我测试使用 hash 性能比使用 generic 的低很多,为什么现在反过来了? 

全文完 !

© 著作权归作者所有

共有 人打赏支持
红薯

红薯

粉丝 20732
博文 130
码字总数 47104
作品 8
深圳
产品经理
私信 提问
加载中

评论(87)

Skyogo
Skyogo
5年了,mysql老了:joy:
OSC_npnlTf
OSC_npnlTf
测试
灰大叔
这里我可以回复下楼主的问题2。实际上,Redis的数据结构字典和Java中的hashmap类似,都是存放键值的,底层都是有数组和链表构成的,也就是我们说的哈希表,比如我们哈希表的数组是3, 如果键值对很多,那么链表就很长,你们懂的,链表的检索不像数组那样,利用索引定位,所以越长越慢。不过,为了处理这种情况,Redis提供了rehash机制,有兴趣的可以研究下
爱宝贝丶
爱宝贝丶

引用来自“osc前美工”的评论

新系统不是光改了一下UI吗?
卍解
哈哈镜达大厦
哈哈镜达大厦
为什么不重启mysql数据库呢?是基于哪些考虑呢?
haitaosoft
haitaosoft
这种实际问题的发现到解决,是很有借鉴意义的。。。。虽然最后还是没分析总结出原因
AT弘毅
AT弘毅
切换redis是为了验证问题点,为么先切走老的,再次又切走新的,直接把新的切走不更直接吗?
Rison
Rison
收藏并不是即时响应。之前记得看过一个redis 文章 ,说单表超过200万,用Redis有问题。��
挖红薯
挖红薯
第一个疑点中有错别字
Mr_Qi
Mr_Qi

引用来自“Mr_Qi”的评论

这样expire也不能针对每一个key设置了吧
https://my.oschina.net/qixiaobo025/blog/1617486
OSC 服务器迁移到独立机柜后,个别用户反应访问慢的分析

周六凌晨我们将 OSC 的服务器(除了 Git@OSC 外)全部搬到独立的机柜,此举是为了接下来的系统扩容做好准备。整个搬移过程很顺利,大约耗时 40 分钟,感谢 @范堡 当天晚上跟我在机房挨冻。迁...

红薯
2015/06/29
818
6
Mac 安装Homebrew 以及brew update

0、前提"安装CocoaPods 因为最近两天我更换了ssd固态硬盘和重装了 macOS Sierra 10.12系统,需要重新安装cocoaPods Xcode8 macOS Sierra 10.12 安装CocoaPods 我在安装过程pod setup遇到问题...

朝雨晚风
2016/12/20
0
0
一个DLOG4J博客网站频繁宕机的问题解决

这是一个特例,可能不具备普遍的参考意义。 网站:http://www.dlog.cn 系统:Linux + MySQL + Tomcat + Nginx + (DLOG4J) 现象:频繁宕机,网页无法打开,在服务器上测试 Tomcat 的HTTP端口无...

红薯
2009/10/19
535
3
前端调试望闻问切:记Iscroll4 疑难杂症之z-index失效

前言 承认有点标题党了,用了一个很大的词“前端调试”,事情是这样的,这两天一直在解决一个bug,我们用iscroll做了一个下拉刷新的产品列表页面,总会出现页面渲染错乱的问题,只要用js动态...

愚坤
07/12
0
0
记录一次vue2.0(history模式)下微信自定义分享的坑

吐槽:关于微信自定义分享前前后后翻了文档两三遍,感觉大佬们写文档都是这么潇洒么?躲在角落里的我瑟瑟发抖了两天..... 下面我们(带着愤怒)来看微信文档来进行开发:传送门 1. 根据文档来...

One day,
09/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

iframe里弹出的层显示在整个网页上

通过在iframe页面添加js脚本,动态给父窗体创建一个div,然后设置让其显示在最顶层这样就可以了 在文件夹中创建两个文件,一个iframe页面,一个父页面index。

少年已不再年少
31分钟前
1
0
聊聊storm trident spout的_maxTransactionActive

序 本文主要研究一下storm trident spout的_maxTransactionActive MasterBatchCoordinator storm-core-1.2.2-sources.jar!/org/apache/storm/trident/topology/MasterBatchCoordinator.java ......

go4it
40分钟前
1
0
js时间函数getTime() 在苹果手机上返回NaN的问题

一、出现问题 var newStartDate = new Date('2017-08-30');var newStartTime = newStartDate.getTime(); 获取到的时间戳,在Android手机正常,在IPhone中返回NaN。 问题说明: 在苹果手机...

tianma3798
42分钟前
1
0
访问日志不记录静态文件、切割和静态元素过期时间

11月16日任务 11.22 访问日志不记录静态文件 11.23 访问日志切割 11.24 静态元素过期时间 11.22、 访问日志不记录静态文件 网站大多元素为静态文件,如图片、css、js等,这些元素可以不用记录...

zgxlinux
48分钟前
1
0
爬虫教程」Python做一个简单爬虫,小白也能看懂的教程

俗话说“巧妇难为无米之炊”,除了传统的数据源,如历史年鉴,实验数据等,很难有更为简便快捷的方式获得数据,在目前互联网的飞速发展写,大量的数据可以通过网页直接采集,“网络爬虫”应运...

糖宝lsh
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部