[转] HandlerSocket系列(MySQL的NoSQL插件HandlerSocket)

作者:洪小军
来源:http://www.cnblogs.com/inrie

HandlerSocket系列(一):由来

新的技术,几乎都是由需求驱动产生的。在仔细深入研究HandlerSocket之前,我觉得有必要先了解一下它所处的历史背景及其它想解决什么样的问题。我想这应该是最关键的,也是做这方面研究和技术选型时第一个应该关注的要点。

先来说一下它的作者Yoshinori Matsunobu,现为DeNA公司的数据库和基础设施架构师,HandlerSocket就是Yoshinori在DeNA公司工作时开发的。DeNA是一家来自日本的社交游戏开发商,目前在日本已经算是数一数二的社交游戏公司,并且在全球展开过一系列的收购,收购了大量的美国游戏厂商,属于一个发展势头非常猛的公司,并且现有用户和活跃度都算挺高的。对于这样一个公司的应用来说,我觉得数据访问方面最关注的应该是这几个要点:海量数据、高并发和热点问题。

对于这样的一些典型的互联网应用在发展到一定程度了都会碰到的问题,肯定也是业界都会面临和关注的问题。所以,大家其实可以看到,从08年开始有个词开始频繁的出现,它就是“NoSQL”。从08年开始,NoSQL逐渐的火热起来,各大互联网公司都有这方面的动作,各种NoSQL产品雨后春笋般的出现。甚至于在09年年初时候,如果你关注这方面架构设计方面的人的Twitter,你可以看到很多类似下面这样的言论,比如Tim Yang说的:这年头,如果一个号称有“海量数据”的互联网公司,不做一个自己的Dynamo, 出去都不好意思跟人打招呼(注: Dynamo是 Amazon开发的一个NoSQL产品,Amazon发布了Dynamo的Paper: “Dynamo: Amazon’s Highly Available Key-value Store“。由于它提出和探讨了Scale Out和Failure Handling等很多NoSQL产品都会面临的问题,使得它与BigTable的Paper差不多并称为NoSQL 研究前必须先通读的2个Paper,这两个Paper在网上都可以很容易找到)。当然了,这是一个比较夸张的说法了,但是从侧面也可以反映出,对于具有海量数据和高并发的互联网应用来说,NoSQL是一个不错的选择。在NoSQL出现之前,大部分互联网应用采用的都是MySQL+Memcached的方案。

NoSQL,意为”Not Only SQL”,而不是”No SQL”,并不是要来取代关系型数据库的,而是作为关系型数据库的补充,我相信在未来很长时间内,应该是两者共同发展。因为从应用场景来看,两者是互补关系,而不是替代关系。对于NoSQL产品来说,由于具有水平伸缩性、高并发读写性能、高可用等优势,但是同样的,有这些优势也是需要付出代价的,比如绝大部分都是只支持Key-Value 操作、有限制的查询功能、不能使用类似Join等这样的功能、大部分为最终一致性模型、还没有标准化等等,而且由于都刚发布不久,稳定性方面和系统的运维也是应该慎重考虑到的。基于NoSQL产品的这些特点,对于像类似微博、Feed等这样的互联网应用来说,是非常合适的。因为这样的应用一般业务复杂度都不高,不需要复杂的Join查询等功能,可以接受最终一致性等,但是由于需要高并发读写和具有海量的数据,这样的应用最适合使用NoSQL。而对于大部分应用,NoSQL可能暂时或者以后可能都不会支持,特别是对于一些企业信息系统,关系型数据库可能是最好的选择。

DeNA和其他互联网应用都遇到的高并发读写、海量数据等的问题,用NoSQL是一个不错的选择。但是由于NoSQL发布的时间都相对比较短暂,稳定性方面还需要慎重考虑,同时运维方面也要有所准备。在做好各种功能测试和性能测试后,最好还是需要有能力能驾驭源代码,在出现问题的时候能更好的定位、排查和解决问题,特别是对于大型的应用来说。这一点可以从之前发生的一些事情得到验证,Digg选择Cassandra,但是后来出现了一些很严重的事故,副总甚至为此引咎辞职。Foursquare选择了Mongodb,但是在前段时间出现了几次宕机。对于新产品来说,在发展的过程中肯定会碰到各种各样的问题,但是会逐步完善和稳定下来,这需要一段时间。如果我们选择在未稳定前使用的话,最好尽量保证有能力来驾驭它们。

我相信肯定有一些朋友也在犯愁了,我是需要NoSQL这样的产品,但是我真的承受不起可能由于不稳定带来的一些问题,同时,运维同事们最熟悉的是传统的关系型数据库,比如MySQL、Sql Server、Oracle等,对于这些他们身经百战,但是对于大部分NoSQL产品,则都比较陌生,需要去学习和积累经验,需要比较大的运维成本。其实,有关注过NoSQL的朋友,可能也都看过了类似这样的一些文章:为什么NoSQL比传统关系型数据库性能高? 这些文章都会大同小异的这样来分析:“由于传统的关系型数据库在处理每个请求的时候,需要做SQL解释、查询优化、解释执行、事务管理、锁管理等等一系列操作,损失了很多性能。但是往往一些对性能要求非常高的应用,比如微博、Feed等,是不需要这些操作的,NoSQL就是由于去掉了这些操作性能上有了很大的提高(当然NoSQL产品在其他方面上也有做了不少优化)”。

其实有些朋友可能也想过,比如对于MySQL数据库来说,从整体上来看,是分为两层:SQL层和Storage层。前面说的NoSQL抛弃掉的那些SQL解释等的操作,其实都是在SQL层的,如果把MySQL的SQL层去掉,直接跟Storage交互,性能不就能提高不少?我相信有不少人也这样想过,但是一直都没有人去做这事情。Yoshinori就是做了这样的一件事情,这个产品就是HandlerSocket。通过HandlerSocket直接跟MySQL的Storage层交互,而省去了SQL层的那些操作。Yoshinori之前是Sun/Oracle的MySQL开发和咨询顾问,所以实现这样的一个产品还是相对比较有优势。

HandlerSocket系列(二):架构、特点及其应用场景

上文介绍了为什么会产生HandlerSocket,是什么需求驱动这个产品产生的。本文主要从整体架构上做一些介绍,包括对它的一些主要优缺点和具体的应用场景。

一、HandlerSocket整体架构

HandlerSocket设计为MySQL的一个plugin,作为mysqld进程的daemon存在,与Client通过TCP/IP交互,进行CRUD相关的操作。基于此原因,不仅可以通过HandlerSocket操作存储层,还可以通过传统的MySQL的方式来操作。这样就可以实现:简单快速的操作通过HandlerSocket来实现,而对于一些复杂的操作,还是通过传统的MySQL方式来实现。

HandlerSocket的结构图如下(图片来自作者Blog):

[转] HandlerSocket系列(MySQL的NoSQL插件HandlerSocket)

这里分两条主线来分析上图:
1. MySQL Client -> MySQL Upper Layer -> Storage Engine Layer
这是传统的使用MySQL的方式,MySQL客户端通过3306端口与Upper层交互,在Upper层做SQL解析、打开表、查询计划优化、关闭表等操作,然后提交到Storage层。


2. HandlerSocket Client -> HandlerSocket daemon plugin -> Storage Engine Layer
这是采用HandlerSocket的方式,通过比较MySQL Upper Layer和HandlerSocket daemon plugin,可以明显看出,HandlerSocket减少了很多操作,这正是性能得以提高的最重要的关键点。这里使用的是9998和9999两个端口,9998作为读的端口,不能做写入操作,9999为写的端口,可以做读取操作,但是不建议使用,因为在9999端口做读取操作,从性能角度看,比起在9998端口上差一些。

下图更具体的列出了调用关系和结构:

[转] HandlerSocket系列(MySQL的NoSQL插件HandlerSocket)

注意目前版本的HandlerSocket暂时只支持Innodb,相信后续版本肯定会支持其他的Storage Engine。


二、HandlerSocket特点
HandlerSocket相比MySQL及其其他的NoSQL产品,具有一些优势:

1. 由于省去了MySQL的SQL层相关的操作,大大的减少了CPU开销。


2. 采用合并操作的方式,合并多个请求同时执行,减少了CPU开销和降低I/O操作次数。关于这个其他的一些NoSQL产品也有这样的机制,比如Mongodb。


3. 由于基于简单的文本协议,能节省不少网络流量,提高网络吞吐量。大部分的NoSQL产品都有这个优势,不少是兼容Memcached协议,当然更多的是采用专有的协议。


4. 能同时使用传统MySQL和HandlerSocket的方式访问MySQL数据库,互相不冲突。这个优势其实挺突出的,是HandlerSocket 的核心竞争力之一。

5. 支持较大的并发连接,可以通过my.cnf的handlersocket_threads来配置连接数。


6. 还可以继续使用MySQL的Master-Slave、Replication等成熟的机制,系统运维与传统的MySQL运维一致。这也是HandlerSocket相比其他NoSQL产品具有的最大的优势。


7. 避免有双重缓存,比如对于Memcached+MySQL的应用来说,在Memcached和MySQL中都存有数据,需要双倍的内存资源,同时也可能会有数据不一致的问题。而采用HandlerSocket则可以避免这样的问题。具体的在接下来的应用场景里介绍。


8. 具有较高的读写性能,在CPU Bound的场景中,读取性能一般是同等环境下MySQL的3-7.5倍。同时写入性能也能达到3-5倍。

具有这些优势的同时,也要看到它目前存在的待改进或者应该注意的问题:
1. 由于采用合并操作的方式,这样做牺牲了响应时间,响应时间相比MySQL来说大一些。


2. 没有安全相关的保证,绝大部分NoSQL产品都有这样的问题。由于采用这样产品的应用的数据一般都不是核心数据,比如不会涉及到账户信息、用户信息等的,所以,安全性方面的暂时应该都不是什么大问题。


3. 在I/O Bound的场景中,性能的提升可能不是很明显。在这种场景下,性能的提升主要依靠的是合并操作,减少I/O操作次数,但是提高的幅度有限。


4. 由于2010年11月份刚发布,目前版本还有部分Bug待修复,比如通过HandlerSocket做Update操作后,没有清除Query Cache,这可能出现数据不一致的情况。


5. 目前只支持5.1和5.5的Innodb存储引擎,以后应该会支持其他存储引擎。

三、HandlerSocket应用场景
HandlerSocket目前已经在DeNA的生产环境上使用,据作者介绍,运行状态很不错,节省了不少Memcached和MySQL Slave服务器,同时网络传输量也减少了。到目前为止还没有发现什么性能问题,比如响应时间比较长等。

纵观目前绝大部分大型互联网应用,基本上采用的都是Memcached+MySQL的方式。这是一种很成熟并且很有效的方式,基本都成了标准方式。由于HandlerSocket在Innodb Buffer Pool命中率很高的情况下性能不会逊色于Memcached,所以在这种情况下,可以采用HandlerSocket+MySQL来替代Memcached+MySQL。这样有以下几个优势:
1. 采用Memcached+MySQL,需要保存两份数据:Memcached和MySQL本身的缓存,需要双倍的内存资源。而HandlerSocket+MySQL的方式,只需要保存一份缓存数据。


2. 采用Memcached+MySQL,需要保持Memcached与MySQL的数据一致性,有时候可能会出现数据不一致的情况,而如果用HandlerSocket+MySQL就没这情况。


3. 采用Memcached+MySQL,还有一个这样的应用都非常小心和特别注意的问题,就是雪崩效应。新应用上线的时候需要先做好各种预热,尽量减少瞬间超级大的I/O压力。前段时间新浪微博出现一次比较严重的故障,据不完全可靠消息证实,就是雪崩效应引起的,当时有部分Memcached服务器出现故障或者失效,导致DB服务器压力瞬间增大,支撑不住。当然了,HandlerSocket应用不是不需要预热,也是需要的,但是在面对这样的问题的时候,它的支撑能力比起MySQL+Memcached的能力强。

通过以上说明,可以看出,HandlerSocket特别适用于海量数据、高并发的具有简单业务模型的应用,比如微博、Feed。可以用来替代传统Memcached+MySQL的方式,而且性能上也接近于目前主流的NoSQL产品,所以还是有比较大的优势。但是需要清楚理性的看待这个问题,由于目前还刚发布不久,还远没有Memcached+MySQL成熟,所以,还是需要更多的功能和性能测试,更多地去研究它的源代码,这样才能更加放心的使用。现在的Memcached+MySQL的方式还是很好的方式,我觉得还将会长久下去,HandlerSocket+MySQL的出现,是给大家多了一个选择。

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

你可能感兴趣的:(mysql,互联网,NoSQL,memcached,网络应用)