问题描述

系统背景:大型线上Java服务集群(活跃用户数上千万),业务重度使用Redis存储个管理Session,业务并发量>1WQPS,基本上每个请求都需要访问Redis(可能是多次),使用了AWS的Redis服务

Redis在平时正常流量下平均响应时间是1-2ms,但是在系统峰值流量上来后Redis在这种情况下平均响应延时会超过20ms,在130万的并发现会延时达到30ms左右,严重影响了整个系统的吞吐量和性能,系统会卡死甚至最严重的情况下会JVMCrash

问题排查

  • 第一步:快速缓解问题

因为线上业务严重受到影响,首先采用了最快速可以缓解问题的办法:升级AWS中Redis的实例,从m3.2xlarge升级到了r3.2xlarge,高峰时平均响应延时从20ms降到了18ms,但只是简单缓解了问题,系统在高峰期的卡死现象还是偶尔会出现(只是次数减少了)

  • 第二步:排查问题根源,彻底解决问题

展开对Redis的详细的问题排查,排查的方向分为以下三个:

1. 业务端是否有很多不合理的Redis请求

研究发现Redis在服务器端 new connection/s: 100左右, new commands/s 70000 左右,commands/per connection 700左右,研究发现使用pipeline比较多,可以考虑使用mget命令。发现这并不是问题的根源。

2. Redis服务器本身有性能问题

可以参考以下链接(蘑菇先生的博客):https://www.cnblogs.com/mushroom/p/4738170.html

  • 我们查询Redis的slowlog get,没有特别大的发现(只有一个17ms的慢查询)
  • 进一步查看,发现Redis响应慢时,Redis服务器的网络输出带宽接近1G。怀疑这个是瓶颈,分析发现我们用的AWS实例支持10G的上线,也排除了这个可能性

3. 业务集群中用到的Redis客户端:Jedis

  • JedisShardedPool maxConnection只设置为128, 怀疑并发比较大Jedis连接不够用了,调整为256试试看结果,发现结果并不明显(Redis服务器本身并不是多线程去相应服务的,一味的加大客户端的并发并不会有效解决的问题),只要自己Jedis连接数能和业务最大并发匹配就可以了
  • 网上找中文文章没什么可以参考的经验,最后索性开始看Jedis的英文文档,看看是不是哪些性能相关的参数,我们主要设置的参数有:MaxTotal 96, MaxIdle=64, testOnBorrow=true。 testOnBorrow是指每次Jedis在跟Redis服务器发起请求之前会先发一个test命令去检查Redis是否准备就绪,主要来应对网络和服务器不稳定性的,这平白无故的把Jedis对后台的并发翻了个倍。我们用的是成熟的AWS Redis服务,而且是内网访问,这些testOnBorrow请求完全是多余的。所以果断的改成testOnBorrow=false。见证奇迹的时刻,修改后观察系统在业务高峰情况下稳稳当当,Redis的响应最多也就5ms,平均恢复到2ms。问题搞定
  • 同时居安思危,我们也发现了系统性能瓶颈的隐患,如果我们的业务再翻个倍,redis这块会继续成为瓶颈。所以我开始着手后续第三部的改造。
  • 第三步:长治久安:引入RedisCluster方案,把系统的缓存提升到>15WQPSLevel

这里我们主要进行了两个大的改造:

1. 首先从业务上把Redis进行拆分,根据业务类型把需要存储在之前一个Redis库的数据拆分成了4个Redis库。这样每个库都可以抗接近7W的QPS了

2. 针对负载最重的Redis库(Session库),在AWS上升级为集群方案,也把我们客户端的Jedis改造成JedisCluster客户端。最后验证下来AWS的Redis集群可以最少支持15W+的QPS,平均响应时间能保证在2ms左右

3. 把一些批量的Redis操作,使用Jedis的pipeline方式减小并发度

最后的胜利:经过这一轮改造,我们的缓存模块一直平稳运行了快2年了,系统的流量最少也翻了6-7倍,这个Redis方案依然稳稳的。老板再也不用担心宕机问题了。

经验总结

1. 遇到线上问题,不能慌了手脚,要先快速的缓解问题,帮组正式分析和正式方案上线争取宝贵时间(那段时间高峰期经常宕机重启,确实捏了一把冷汗啊)

2. 解决问题时(特别是当没有头绪时),还是要从全局出发,理清楚思路,从各个可能出问题的模块逐一去分析排查,抽丝剥茧总能找出根源并制定解决方案

3. 居安思危,出了问题要想想将来系统发展更大后是否有类似的隐患,早点进行重构改造,做到长治久安。

大型系统的Redis性能优化的更多相关文章

  1. redis性能优化、内存分析及优化

    redis性能优化.内存分析及优化 1.优化网络延时 2.警惕执行时间长的操作 3.优化数据结构.使用正确的算法 4.考虑操作系统和硬件是否影响性能 5.考虑持久化带来的开销 5.1 RDB 全量持久 ...

  2. 《吐血整理》Redis 性能优化的 13 条军规!史上最全

    Redis 是基于单线程模型实现的,也就是 Redis 是使用一个线程来处理所有的客户端请求的,尽管 Redis 使用了非阻塞式 IO,并且对各种命令都做了优化(大部分命令操作时间复杂度都是 O(1) ...

  3. 吊打面试官系列:Redis 性能优化的 13 条军规大全

    1.缩短键值对的存储长度 键值对的长度是和性能成反比的,比如我们来做一组写入数据的性能测试,执行结果如下: 从以上数据可以看出,在 key 不变的情况下,value 值越大操作效率越慢,因为 Redi ...

  4. C# 大型电商项目性能优化(一)

    经过几个月的忙碌,我厂最近的电商平台项目终于上线,期间遇到的问题以及解决方案,也可以拿来和大家多做交流了. 我厂的项目大多采用C#.net,使用逐渐发展并流行起来的EF(Entity Framewor ...

  5. redis性能优化——生产中实际遇到的问题排查总结

    背景 redis-K,V数据库,因其高性能的操作性和支持丰富的数据结构,目前大量被用于衔接应用层和关系数据库中间的缓存层.随着使用的场景越来越多,和数据量快速的递增,在生产环境中经常会遇到相关的性能瓶 ...

  6. 大型系统中使用JMS优化技巧–Sun OpenMQ

    我们先来看看在Sun OpenMQ系统中 一个持久.可靠的方式传送消息的步骤是怎么样的,如图所示: 查看大图请点击这里 在传送过程中,系统处理JMS消息分为以下两类:   ■ 有效负荷消息,由生成方发 ...

  7. 【转载】大型系统中使用JMS优化技巧

    [本文转自:http://www.javabloger.com/article/sun-openmq-jms-large-scale-systems.html] 我们先来看看在Sun OpenMQ系统 ...

  8. redis性能优化

    redis日志截图:

  9. Redis性能优化之redis.cnf配置参数

    redis调优总结 1.相应的参数调优 加内存2.redis使用结构调优3.使用合理的数据类型说明:redis存储的数据为redis hash(字符映射表) 单key多字段结构. 1)调整配置文件中配 ...

随机推荐

  1. PHP生成excel(3)

    这一节主要是设置背景颜色.边框.字体大小.表格宽度 效果图 代码如下 <?php header("Content-Type:text/html;charset=utf-8") ...

  2. android-auto-scroll-view-pager

    https://github.com/eltld/android-auto-scroll-view-pager

  3. Codeforces 558C Amr and Chemistry

    题意: n个数.每次能够选一个数 让其 *=2 或者 /=2 问至少操作多少次使得全部数相等. 思路: 对于每一个数,计算出这个数能够变成哪些数,以及变成那个数的最小步数,用两个数组保存 cnt[i] ...

  4. mysql有哪几种索引

    从数据结构角度 1.  B+树索引(O(log(n))) 2.  hash索引 3.  FULLTEXT索引 4.  R-Tree索引 从物理存储角度 1. 聚集索引 2.  非聚集索引 从逻辑角度 ...

  5. easyUI datagrid组件能否有display:none的隐藏效果

    这个项目用了JQ easyUI datagrid 组件,我今天做了一个页面,页面有个div层,div里放了一个easyUI datagrid,页面初始化时div隐藏(display:none),通过点 ...

  6. java-冒泡

    一.java冒泡排序 冒泡排序(Bubble Sort)是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要 ...

  7. c++学习笔记之基础---类内声明函数后在类外定义的一种方法

    在C++的“类”中经常遇到这样的函数, 返回值类型名 类名::函数成员名(参数表){ 函数体.} 双冒号的作用 ::域名解析符!返回值类型名 类名::函数成员名(参数表) { 函数体. } 这个是在类 ...

  8. RDLC后台自己定义报表模板

    首先封装一个公共类,统一来操作RDLC报表 using System; using System.Collections.Generic; using System.Linq; using Syste ...

  9. MD5加密实现类不是Windows平台下联邦信息处理标准验证过的加密算法的一部分

    在.NET应用程序中,MD5CryptoServiceProvider实例化时,造成This implementation is not part of the Windows Platform FI ...

  10. VK Cup 2016 - Round 1 (Div. 2 Edition) C. Bear and Forgotten Tree 3

    C. Bear and Forgotten Tree 3 time limit per test 2 seconds memory limit per test 256 megabytes input ...