[原创]HandlerSocket系列(三):性能及其性能优化

时间:2022-03-15 06:36:10

[原创]HandlerSocket系列(三):性能及其性能优化

前面两篇文章主要对HandlerSocket从整体上做一些介绍,本文从性能及其性能优化方面来做一些介绍。

 

一、HandlerSocket性能
HandlerSocket作者测试HandlerSocket在查询情况下QPS为75K,Memcached为40K,MySQL为10K。但是需要注意到它的测试场景,一般的应用是很难有这样的场景的,所以说一般应用是很难达到7.5倍于MySQL的情况,但是性能的大幅度提高是不容置疑的。作者的测试场景如下:
1. 关闭MySQL的query cache:也就是MySQL的每次操作都需要执行sql解析等那一系列操作。


2. CPU Bound而非I/O Bound:InnoDB Buffer Pool设置为比较大,命中率接近100%。


所以,应该更客观的来看待测试数据。对于CPU Bound而非I/O Bound类型的应用,在InnoDB_Buffer_Pool接近100%命中率的时候,HandlerSocket可以将查询性能提高7.5倍。这一点其实不难理解,因为HandlerSocket主要性能优化点在于节省了SQL层的开销,SQL层的开销主要是CPU的开销。而如果对于一个I/O Bound的应用来说,HandlerSocket的查询性能可能就达不到7.5倍了,可能距离7.5倍有比较大的差距,所以,对于HandlerSocket的应用来说,应该尽量提高InnoDB_Buffer_Pool的大小,多多益善。

 

我也做过一些基准测试,基本上在插入的情况下,HandlerSocket的性能能达到同等环境的MySQL的3-5倍,数据量越大时候越明显,特别是达到5000万以后。在查询情况下,HandlerSocket是同等环境下MySQL的1.5-2倍,这跟作者的测试的7.5倍有比较大的出入,这也是上面我特别提到的,作者的测试数据是在Innodb_Buffer_Pool足够大并且命中率很高的情况,由于我做基准测试的机器条件有限,没有足够大的Buffer Pool,命中率不是很高,所以,I/O开销不小,这也验证了上面提到的,对于I/O Bound的场景,性能的提升不会特别的明显,所以应该尽量增大InnoDB_Buffer_Pool的大小,尽量接近于数据的大小。而且我在测试的时候,没有关闭Query Cache,所以对于MySQL的测试场景来说,能重用到执行计划和Cache数据等。

 

上面说到了,HandlerSocket具有不少的优点,性能也有很大的提升,但是也需要理性的来看待,有一些需要特别注意的事项,在做决策的时候,应该整体上的考虑,我这里简单的总结一下。
1. 应该尽量达到CPU-Bound场景,而非IO-Bound,这样才能更好的发挥出HandlerSocket的优势。具体做法是增大内存,尽量提高InnoDB_Buffer_Pool大小。


2. 由于采用合并操作,响应时间会有不同程度的增加,应该考虑好是否满足你的应用场景。可以继续关注后续版本优化策略,比如可能有些朋友会想要这样的:读取的时候不是合并操作,但是写入是合并操作,当然这样的情况读取的总体性能会有不同程度降低,不过一切不就是在权衡嘛?还是看具体应用场景。

 

二、HandlerSocket性能优化
前面也提到了,HandlerSocket性能相比传统MySQL有了比较显著的提高,但是要想更好的发挥出它的优势,需要做一些相关的优化。

 

性能优化主要从以下三方面考虑,当然除了这三方面,还有其他一些优化方式,比如优化操作系统,使用Direct IO等,这里说的这三方面是相对比较容易做到并且实现技术成本也不高的方式:
1. 硬件环境
前面也提到了,应该尽量提高Innodb Buffer Pool的大小,对应到硬件上,就是要尽量增加内存的大小,最理想的情况下是内存大小与数据大小一样。如果有资源,也可以考虑采用SSD,这有个基于SSD的测试数据(http://www.percona.com/docs/wiki/benchmark:handlersocket:ssd:start),性能还是非常给力的。


2. 客户端优化
客户端与服务端基于Socket通信,打开关闭连接、OpenIndex等操作都是比较耗费资源的操作,应该尽量避免频繁的做这些操作。所以,在客户端应该要做连接池,同时应该采用一些更好的通信模型,比如Linux下基于epoll和NIO等。比如,这个Java客户端(http://code.google.com/p/hs4j/)这方面就做得不错。


3. HandlerSocket和Innodb配置
HandlerSocket配置:
//读线程的个数,推荐为逻辑CPU个数,比如超线程的应该*2
handlersocket_threads = 16
//写线程的个数,目前的版本推荐设置为1
handlersocket_thread_wr = 1
//读请求的监听端口
handlersocket_port = 9998
//写请求的监听端口
handlersocket_port_wr = 9999

 

Innodb配置:
//Innodb Buffer Pool大小,推荐越大越好
innodb_buffer_pool_size
//Innodb日志文件大小,根据需求设置,在允许的情况下越大也越好
innodb_log_file_size, innodb_log_files_in_group
//mysqld进程可以打开的文件数,推荐为65535
open_files_limit = 65535
//设置为1能提高性能,但是相应的也会消耗内存,需要权衡好
innodb_adaptive_hash_index = 1