由于公司业务的快速发展导致数据库的数据量飞速增长,我们底层数据的存储,逐渐成为制约整个产品性能的核心部分。于是我们调研了各大数据库分库产品,如:hibernate5+对多租户的支持,当当ShardingJdbc,mysqlProxy,mycat等。最终考虑到国内目前各个产品的活跃度和成熟度,以及对现有业务的适配情况,最终选择了mycat作为分库分表的中间件产品。经过了几轮性能测试,发现mycat表现基本良好,性能损失率约为30%,在可接受的范围内。于是考虑在不分库分表的情况下,将mycat作为数据库代理,先在线上做个简单测试,没想到简单业务的服务没问题,但是核心服务在连接mycat时会出现请求响应缓慢的问题,一个通过主键查对象的SQL响应时间居然超过1秒钟。于是,赶紧下线mycat,重新连接mysql后,性能稳定下来。这没分库就表现这么差,分库了还了得。。。心有不甘,于是笔者踏上了mycat性能调优的汤坑之路。。
一、日志对mycat性能的影响
1.log4j.xml配置成debug级别,mycat jvm参数:Xmx4G Xms4G XX:MaxDirectMemorySize=4G
a.GC情况:
S0 S1 E O P YGC YGCT FGC FGCT GCT
88.69 0.00 77.57 5.05 � 2216 8.390 1 0.067 8.457
77.93 0.00 11.34 5.06 � 2218 8.399 1 0.067 8.466
0.00 76.96 46.41 5.06 � 2219 8.403 1 0.067 8.470
74.38 0.00 83.05 5.06 � 2220 8.408 1 0.067 8.475
60.70 0.00 18.26 5.07 � 2222 8.417 1 0.067 8.484
0.00 65.79 52.49 5.07 � 2223 8.421 1 0.067 8.488
73.44 0.00 87.12 5.07 � 2224 8.426 1 0.067 8.492
70.79 0.00 21.50 5.08 � 2226 8.435 1 0.067 8.501
每秒1~2次非常频繁
b.JVM CPU监控:
log4j占用CPU时间最长。
c.JVM MEM监控:
内存占用最多的是字符类型
d.2000个简单查询耗时统计
total costs(ms)
total costs(ms)
total costs(ms)
avg total costs(ms)
costs(ms)
costs(ms)
costs(ms)
avg costs(ms)
mysql
22935
24316
25853
24368
11
12
12
11.6
mycat
173680
171557
170718
171985
86
85
85
85.3
mysql耗时统计图:
mycat耗时统计图:
根据数据分析可得:mycat比mysql慢6.07倍
2.log4j.xml配置成error级别,mycat jvm参数:Xmx4G Xms4G XX:MaxDirectMemorySize=4G
a.GC情况:
S0 S1 E O P YGC YGCT FGC FGCT GCT
84.81 0.00 70.54 1.24 � 94 2.451 1 0.064 2.515
84.81 0.00 80.04 1.24 � 94 2.451 1 0.064 2.515
84.81 0.00 85.36 1.24 � 94 2.451 1 0.064 2.515
84.81 0.00 87.42 1.24 � 94 2.451 1 0.064 2.515
84.81 0.00 89.46 1.24 � 94 2.451 1 0.064 2.515
84.81 0.00 91.69 1.24 � 94 2.451 1 0.064 2.515
84.81 0.00 93.53 1.24 � 94 2.451 1 0.064 2.515
84.81 0.00 96.10 1.24 � 94 2.451 1 0.064 2.515
84.81 0.00 97.97 1.24 � 94 2.451 1 0.064 2.515
84.81 0.00 98.69 1.24 � 94 2.451 1 0.064 2.515
0.00 92.86 13.14 1.25 � 95 2.472 1 0.064 2.536
0.00 92.86 49.48 1.25 � 95 2.472 1 0.064 2.536
0.00 92.86 68.61 1.25 � 95 2.472 1 0.064 2.536
每秒0.08次,看来日志输出是造成mycat GC频繁的元凶
b.JVM CPU监控:
log4j占用CPU的时间已经找不到了,最长的是mycat处理查询结果的线程。
c.JVM MEM监控:
调整日志级别后,int[] 对象占用的内存大大减少了
d.2000个简单查询耗时统计
total costs(ms)
total costs(ms)
total costs(ms)
avg total costs(ms)
costs(ms)
costs(ms)
costs(ms)
avg costs(ms)
mysql
37680
36239
36705
36874
18
18
18
18
mycat
40554
39345
40623
40174
20
19
20
19.6
mysql耗时统计图:
mycat耗时统计图:
根据数据分析可得:mycat比mysql慢0.08倍
疑问:mycat在调整日志,重新启动后,第一次测试时发生了性能抖动,之后平缓
mycat性能抖动图:
结论:日志需要开启error级别,否则将会造成mycat GC频繁,从而影响 响应时间
二、DirectMemory对mycat性能的影响
1.log4j.xml配置成error级别,mycat jvm参数:Xmx4G Xms4G
a.GC对比
XX:MaxDirectMemorySize=4G
XX:MaxDirectMemorySize=3G
XX:MaxDirectMemorySize=2G
XX:MaxDirectMemorySize=1G
GC
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 89.70 67.74 1.52 � 89 2.286 1 0.061 2.348
89.41 0.00 28.13 1.54 � 90 2.313 1 0.061 2.374
89.41 0.00 85.84 1.54 � 90 2.313 1 0.061 2.374
0.00 87.12 41.31 1.56 � 91 2.343 1 0.061 2.404
0.00 87.12 98.46 1.56 � 92 2.343 1 0.061 2.404
88.52 0.00 53.41 1.57 � 92 2.373 1 0.061 2.434
0.00 89.73 9.57 1.59 � 93 2.403 1 0.061 2.465
0.00 89.73 66.74 1.59 � 93 2.403 1 0.061 2.465
90.80 0.00 23.15 1.61 � 94 2.432 1 0.061 2.494
90.80 0.00 81.01 1.61 � 94 2.432 1 0.061 2.494
0.00 90.47 37.72 1.62 � 95 2.462 1 0.061 2.523
0.00 90.47 95.76 1.62 � 95 2.462 1 0.061 2.523
93.21 0.00 53.53 1.64 � 96 2.492 1 0.061 2.553
S0 S1 E O P YGC YGCT FGC FGCT GCT
72.59 0.00 55.69 2.35 � 126 2.661 1 0.066 2.727
72.59 0.00 74.64 2.35 � 126 2.661 1 0.066 2.727
72.59 0.00 82.26 2.35 � 126 2.661 1 0.066 2.727
72.59 0.00 96.14 2.35 � 126 2.661 1 0.066 2.727
72.59 0.00 98.74 2.35 � 126 2.661 1 0.066 2.727
0.00 73.05 24.66 2.36 � 127 2.678 1 0.066 2.744
0.00 73.05 59.14 2.36 � 127 2.678 1 0.066 2.744
0.00 73.05 74.67 2.36 � 127 2.678 1 0.066 2.744
0.00 73.05 80.99 2.36 � 127 2.678 1 0.066 2.744
0.00 73.05 84.09 2.36 � 127 2.678 1 0.066 2.744
0.00 73.05 86.12 2.36 � 127 2.678 1 0.066 2.744
0.00 73.05 89.39 2.36 � 127 2.678 1 0.066 2.744
0.00 73.05 92.26 2.36 � 127 2.678 1 0.066 2.744
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 53.88 58.44 0.53 � 17 0.181 1 0.065 0.246
61.07 0.00 22.08 0.53 � 18 0.196 1 0.065 0.261
61.07 0.00 82.07 0.53 � 18 0.196 1 0.065 0.261
0.00 64.27 40.67 0.53 � 19 0.214 1 0.065 0.279
40.18 64.27 100.00 0.53 � 20 0.214 1 0.065 0.279
68.31 0.00 58.15 0.53 � 20 0.234 1 0.065 0.299
0.00 69.75 15.67 0.53 � 21 0.255 1 0.065 0.320
0.00 69.75 73.38 0.53 � 21 0.255 1 0.065 0.320
66.83 0.00 30.14 0.53 � 22 0.277 1 0.065 0.342
66.83 0.00 88.50 0.53 � 22 0.277 1 0.065 0.342
0.00 73.20 44.27 0.53 � 23 0.301 1 0.065 0.366
80.58 0.00 1.24 0.53 � 24 0.324 1 0.065 0.389
80.58 0.00 60.64 0.53 � 24 0.324 1 0.065 0.389
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 58.25 50.25 0.52 � 17 0.192 1 0.064 0.256
64.19 0.00 15.57 0.52 � 18 0.207 1 0.064 0.271
64.19 0.00 75.00 0.52 � 18 0.207 1 0.064 0.271
0.00 67.74 33.33 0.53 � 19 0.226 1 0.064 0.290
0.00 67.74 91.26 0.53 � 19 0.226 1 0.064 0.290
67.43 0.00 48.33 0.53 � 20 0.247 1 0.064 0.311
0.00 76.06 6.20 0.53 � 21 0.267 1 0.064 0.331
0.00 76.06 66.35 0.53 � 21 0.267 1 0.064 0.331
78.43 0.00 24.29 0.53 � 22 0.290 1 0.064 0.354
78.43 0.00 86.86 0.53 � 22 0.290 1 0.064 0.354
0.00 79.12 46.02 0.53 � 23 0.314 1 0.064 0.378
79.61 0.00 0.00 0.53 � 24 0.336 1 0.064 0.400
79.61 0.00 62.98 0.53 � 24 0.336 1 0.064 0.400
gc有波动,稳定后差不多是0.33次/秒
b.DirectMemory对比
XX:MaxDirectMemorySize=4G
XX:MaxDirectMemorySize=3G
XX:MaxDirectMemorySize=2G
XX:MaxDirectMemorySize=1G
DirectMemory
c.2000个简单查询对比
XX:MaxDirectMemorySize=4G
costs(ms)
XX:MaxDirectMemorySize=3G
costs(ms)
XX:MaxDirectMemorySize=2G
costs(ms)
XX:MaxDirectMemorySize=1G
costs(ms)
mysql
18
18
17
15
mycat
19.6
22
22
21
结论:XX:MaxDirectMemorySize的调整对性能影响不大
三、Xmx对mycat性能的影响
a.GC对比
Xmx4G
Xmx3G
Xmx2G
Xmx1G
GC
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 82.58 39.14 0.99 � 55 1.395 1 0.066 1.460
33.46 82.58 100.00 1.01 � 56 1.395 1 0.066 1.460
82.04 0.00 59.80 1.01 � 56 1.425 1 0.066 1.491
0.00 86.30 14.58 1.02 � 57 1.459 1 0.066 1.524
0.00 86.30 71.13 1.02 � 57 1.459 1 0.066 1.524
86.53 0.00 23.09 1.04 � 58 1.493 1 0.066 1.558
86.53 0.00 76.25 1.04 � 58 1.493 1 0.066 1.558
0.00 86.30 39.70 1.06 � 59 1.520 1 0.066 1.585
0.00 86.30 96.79 1.06 � 59 1.520 1 0.066 1.585
79.55 0.00 53.02 1.08 � 60 1.561 1 0.066 1.626
0.00 83.33 8.07 1.10 � 61 1.594 1 0.066 1.660
0.00 83.33 61.35 1.10 � 61 1.594 1 0.066 1.660
80.26 0.00 17.64 1.12 � 62 1.627 1 0.066 1.693
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 84.61 4.00 2.44 � 127 2.706 1 0.062 2.768
0.00 84.61 97.48 2.44 � 127 2.706 1 0.062 2.768
84.78 0.00 11.81 2.46 � 128 2.723 1 0.062 2.785
84.78 0.00 90.06 2.46 � 128 2.723 1 0.062 2.785
84.78 0.00 98.42 2.46 � 128 2.723 1 0.062 2.785
0.00 76.83 22.84 2.48 � 129 2.739 1 0.062 2.802
0.00 76.83 76.87 2.48 � 129 2.739 1 0.062 2.802
0.00 76.83 98.82 2.48 � 129 2.739 1 0.062 2.802
84.51 0.00 3.76 2.50 � 130 2.757 1 0.062 2.819
84.51 0.00 86.22 2.50 � 130 2.757 1 0.062 2.819
84.51 0.00 98.31 2.50 � 130 2.757 1 0.062 2.819
0.00 76.49 20.33 2.52 � 131 2.773 1 0.062 2.835
0.00 76.49 75.03 2.52 � 131 2.773 1 0.062 2.835
S0 S1 E O P YGC YGCT FGC FGCT GCT
91.65 0.00 27.10 6.25 � 292 4.636 1 0.064 4.700
0.00 90.26 50.93 6.26 � 293 4.651 1 0.064 4.715
82.54 0.00 67.42 6.28 � 294 4.667 1 0.064 4.731
0.00 86.86 81.88 6.30 � 295 4.685 1 0.064 4.749
86.29 0.00 97.60 6.33 � 296 4.700 1 0.064 4.765
87.07 0.00 14.29 6.37 � 298 4.733 1 0.064 4.798
0.00 88.58 29.21 6.38 � 299 4.750 1 0.064 4.814
89.10 0.00 45.92 6.40 � 300 4.767 1 0.064 4.831
0.00 80.04 61.14 6.42 � 301 4.783 1 0.064 4.847
84.42 0.00 77.88 6.44 � 302 4.800 1 0.064 4.865
0.00 84.94 91.44 6.45 � 303 4.818 1 0.064 4.882
0.00 84.83 1.98 6.49 � 305 4.853 1 0.064 4.917
77.33 0.00 17.87 6.51 � 306 4.868 1 0.064 4.933
S0 S1 E O P YGC YGCT FGC FGCT GCT
81.73 0.00 49.91 11.93 � 200 0.706 1 0.059 0.764
66.63 0.00 70.87 11.99 � 202 0.712 1 0.059 0.770
81.48 0.00 75.88 12.05 � 204 0.719 1 0.059 0.778
82.85 0.00 81.89 12.11 � 206 0.726 1 0.059 0.785
99.97 0.00 95.65 12.17 � 209 0.733 1 0.059 0.795
0.00 55.60 8.26 12.28 � 211 0.743 1 0.059 0.801
0.00 81.97 18.77 12.37 � 213 0.750 1 0.059 0.808
0.00 80.48 18.83 12.46 � 215 0.757 1 0.059 0.816
0.00 79.10 19.45 12.51 � 217 0.764 1 0.059 0.822
0.00 88.47 25.51 12.59 � 219 0.771 1 0.059 0.829
0.00 73.85 32.49 12.68 � 221 0.778 1 0.059 0.837
0.00 71.48 42.69 12.76 � 223 0.785 1 0.059 0.844
0.00 72.61 53.90 12.83 � 225 0.793 1 0.059 0.852
随着内存减少,GC越来越快
b.内存使用情况
Xmx4G
Xmx3G
Xmx2G
Xmx1G
堆内存
c.2000个简单查询对比
Xmx4G
costs(ms)
Xmx3G
costs(ms)
Xmx2G
costs(ms)
Xmx1G
costs(ms)
mysql
18
15
21
19
mycat
21
18
26
24
四、数据库大表对mycat性能的影响
a.400多列a_account表
1并发(ms)
10并发(ms)
100并发(ms)
200并发(ms)
300并发(ms)
mysql
3.5
4.6
32
61
85
mycat
4.5
6.2
56
81
110
b.5列a_account表
1并发(ms)
10并发(ms)
100并发(ms)
200并发(ms)
300并发(ms)
mysql
1.2
2.1
23
44
70
mycat
1.9
2.2
22
45
68
通过观察2组测试数据,可以发现:
1.400多列表的那组测试中,mycat各并发下,平均都比mysql慢30%左右,
2.5列表的那组测试中,mycat各并发下,与mysql持平
3.通过观察mycat的CPU、内存、线程发现,300列的大表,占用内存非常之高,光char[]类型就达到了700M,CPU保持在30%~40%,NIO读写线程占用CPU时间最长。
而5列的小表,内存占用非常小,gc次数明显降低,CPU也稳定到了10%~20%的水平。
结论:
1.数据库表结构过大,会对mycat性能产生较大影响
2.由大表读写导致的网络流量对mycat性能影响很大,mycat宿主机需要多网卡支持
五、大表的SELECT * 对mycat性能的影响
1.通过测试大表的SELECT 全字段,和SELECT * 对比发现,SELECT 全字段时,mycat大部分的CPU都被druid SQL解析占据,yong GC主要是由于mycat解析大SQL引起的,所以ORM框架的全字段改写SQL功能(包括读写)会降低mycat性能。
2.通过将程序的SELECT全字段改为SELECT * 后,mycat GC次数直线下降,CPU也减了下来,并且响应时间得到良好的改善,基本跟直连mysql持平。
3.性能测试时,适当减小路由缓存的参数值,可以很好的减少full gc的次数。
六、调优过程遇到的坑
1.在整个调优过程中,首先出发点有可能是错误的,我们因为mycat在生产环境发生故障,而将服务的数据源切回mysql后,系统稳定下来,以此为依据断定mycat有性能问题,导致整个调优过程都将思路局限在mycat上,而忽略了自己程序的问题。
2.测试环境中,不同JVM进程会相互抢占CPU,而影响测试结果的稳定性。
3.网络带宽的大小,一度成为我们怀疑的目标,通过各种工具监控后,发现带宽不是瓶颈。
4.AWS ELB的带宽弹性功能,也是我们怀疑过的目标之一,后来通过测试,排除掉该可能性。
5.集群中多个节点同时连接mycat,导致SQL响应缓慢,让我们怀疑到了mycat客户端数量可能是性能瓶颈点。通过测试,发现连接数不是瓶颈,客户端数排除。
6.mycat内存管理有可能成为mycat响应缓慢的元凶,通过监控GC,发现yong gc次数较多,每2秒一次,Eden区很快会被填满,这让我们怀疑到可能是响应数据太大导致,从而将目标定位到数据库表结构上。
7.通过对比大表和小表在相同环境下的响应时间,可以发现小表的表现非常好,和mysql基本持平,从而断定是数据库表结构的问题。
8.由于业务已上线很长时间,不能轻易改动表结构,所以只好继续找mycat大表表现差的原因。受大表致使mycat性能下降观念先入为主的影响,调优很长时间没有思路。
9.偶然机会,同事使用JMeter来测试mycat和mysql的表现,居然发现两者性能差别不大,于是事情有了新的突破,我们开始关注为什么使用测试工具测试没事,我们用自己的服务压测就总有问题,从而将矛头对准了我们自己的底层dal程序。
10.通过使用原生的JDBC压测发现性能很好,于是将问题定位到hibernate。发现hibernate表现非常差,从而将问题锁定为hibernate。
11.通过查看hibernate的日志,发现其和JDBC直连唯一的差别在sql上,hibernate进行了sql改写,通过id查对象时,拼接了400多全列名,并且做了重命名,导致一个SQL的大小约为17K。而将这个大SQL使用JDBC直连执行时,问题得到了重现,从而定位到了性能问题的最终元凶,“hibernate改写后的长SQL”。
12.通过将hibernate通过id获取对象的hql语句改写为SELECT * FROM object后,性能表现良好,与mysql持平,自此,问题得到了解决。。
七、调优过程用到的工具
1.Linux网络带宽监控工具: nload
2.JVM内存监控工具:jstat、jvisualvm、jmap、jstack、tprofiler、jprofiler
3.mycat集群搭建工具:haproxy
4.Linux CPU监控工具:top
5.绘图工具:gnuplot
6.性能压测工具:JMeter
7.内存分析工具:EclipseMAT