HandlerSocket 测试报告
HandlerSocket 测试报告
作者: 叶金荣
编写日期: 2011-04-22
目录
1 测试说明..........................................................................................................................2
1.1 HandlerSocket 简介.................................................................................................2
1.2 HandlerSocket 体系结构.........................................................................................3
1.2.1 关于 HandlerSocket 性能.....................................................................................3
1.2.2 HandlerSocket 特色.............................................................................................7
1.3 HandlerSocket 读写线程模型.................................................................................8
1.4 HandlerSocket 客户/服务器协议............................................................................9
2 HandlerSocket 使用..................................................................................................10
2.1 下载、安装.................................................................................................................10
2.2 配置.............................................................................................................................11
HandlerSocket 测试报告
2.3 HandlerSocket API 案例........................................................................................12
2.3.1 随机读取记录.........................................................................................................12
2.3.2 顺序写入记录.........................................................................................................13
2.3.3 更新记录.................................................................................................................14
2.3.4 删除记录.................................................................................................................15
3 API 简介.........................................................................................................................16
4 结语................................................................................................................................17
5 参考信息........................................................................................................................18
6 附件................................................................................................................................19
1测试说明
本次测试了 HandlerSocket 这个 NOSQL 产品在数据分析中的表现,考察
其在公司业务生产环境中实施的可行性及其性能。
HandlerSocket 测试报告
1.1HandlerSocket简介
简言之,HandlerSocket 是一个基于 MySQL InnoDB 引擎的 NOSQL 产
品,采用原生态 API 方式操作 InnoDB 引擎表空间文件。作者 Akira Higuchi
是日本人,2010 年 8 月离开 Oracle,加盟日本社交游戏公司 DeNA。它最重要
的特点就是绕过 MySQL 的 SQL 解析层、查询优化器、缓存层,直接用原生
API 存取 InnoDB 引擎表空间文件,因此获得了性能上的 N 个数量级提升。
1.2HandlerSocket体系结构
HandlerSocket 的体系结构如下图所示:
HandlerSocket 测试报告
如简介中提到的,libhsclient 直接访问 Handlersocket Plugin,绕过了
listener 和 SQL Layer,从而获得了性能上的极大提升。
1.2.1 关于HandlerSocket性能
这是作者进行的对比测试结果:
HandlerSocket 测试报告
HandlerSoket 效率非常高的原因是:
1. 绕过 SQL 解析层,大大降低了 CPU 消耗
2. 将分散的请求转化成批量操作,降低了 CPU、磁盘 IO 消耗
3. 采用自定义的服务/客户协议,降低了网络 IO 消耗
下面是用 Oprofile 工具对比探测的结果,测试方法是在客户端并发执行多
次类似操作操作 SELECT v from table where k = ?
1. 采用原始的 libmysql 接口
HandlerSocket 测试报告
明显的看到,mysqld 进程消耗了大量 CPU 资源。
看下 mysqld 进程内部的详细情况:
可以看到,SQL 解析层消耗了最多的 CPU 资源。
再看下 linux 内核的具体情况:
HandlerSocket 测试报告
Schedule 调用消耗了最多的 CPU 资源。
2. 采用 HandlerSocket 专用接口
明显的看到,mysqld 进程消耗了大量 CPU 资源。
看下 mysqld 进程内部的详细情况:
HandlerSocket 测试报告
可以看到,MySQL 内部消耗 CPU 资源最多的是 InnoDB 相关的调用。
再看下 linux 内核的具体情况:
Schedule 调用已经不是消耗 CPU 资源最多的了。
HandlerSocket 测试报告
1.2.2 HandlerSocket特色
1. 集成到 InnoDB 引擎中,和传统的引擎管理一样, 无需了解太多新知
识,很快就能投入使用
2. 目前只支持等值操作(=, >=, >, <=, <),不支持范围检索(t1 >
N and t1 < M)查询
3. 支持插入、更新、删除
4. 不支持事务控制,但底层是支持的
5. 启用 binlog 的话,数据变更采用 row-based 格式
6. 所有的操作都是永久性的,不能回滚
7. 传统的 MySQL 是每个连接创建一个线程的模式,计划在 MySQL 6 采
用线程池的机制;在 HandlerSocket 中多个连接只启用一个线程,采
用 epoll 调用,效率更高
8. HandlerSocket 比传统的 mysql 快了 7.5倍,而且%us 的 cpu 使用
率为mysql 的 3/4
HandlerSocket 测试报告
1.3HandlerSocket读写线程模型
1. 读线程模型
2. 写线程模型
HandlerSocket 测试报告
1.4HandlerSocket客户/服务器协议
传统的 MySQL 客户/服务器协议用 tcpdump 结果如下:
相比之下,HandlerSocket 协议就简单了很多:
相应的网络 IO 统计差别非常大:
HandlerSocket 测试报告
2 HandlerSocket使用
2.1下载、安装
登录官网:http://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL,下
载相应版本的源码包,同时还需要下载 MySQL 5.1或更高版本源码,分别加
压缩后,采用类似下面的参数进行编译:
./configure --with-mysql-source=../Percona-Server-5.5.10-rc20.1 --with-mysql-
bindir=/usr/local/mysql/bin && make
然后就可以在 handlersocket/.libs 目录下找到编译完后的动态库文件:
将 这些动态库文 件拷贝到 mysql 的动态库加 载 目 录 下 , 例 如 : /usr/
local/mysql/lib/mysql/plugin 目录下。
登录到 MySQL 服务器上,安装 HandlerSocket插件:
mysql> INSTALL PLUGIN HandlerSocket SONAME 'handlersocket.so';
执行”SHOW PLUGINS” 指令查看是否安装成功。
另外,如果还想要安装 Perl 客户端 API库的话,还需要多做点:
cd perl-Net-HandlerSocket
HandlerSocket 测试报告
perl Makefile.PL && make && make install
就可以把客户端 API库安装到 Perl库目录下。
2.2配置
安装完插件后,接下来修改下 MySQL 配置文件/etc/my.cnf,例如:
#HandlerSocket
#设置 handlersocket 读数据专用端口,默认值即可
loose_handlersocket_port = 9998
#设置 handlersocket 写数据专用端口,默认值即可
loose_handlersocket_port_wr = 9999
#设置 handlersocket 读数据并发线程数,可根据实际情况进行调整
loose_handlersocket_threads = 16
#设置 handlersocket 写数据并发线程数,默认值 1即可
loose_handlersocket_threads_wr = 1
重启MySQL 进程后,若无意外,就可以看到确实启用这些端口监听了:
同时,MySQL 的线程中也能看到正在运行:
其中,线程 ID号为 17 的是 HandlerSocket 的写线程,当前有 4 个连接,
HandlerSocket 测试报告
4 个活动写操作;线程号为 15 的是读线程,当前有 3 个连接,3 个活动读请求。
2.3HandlerSocket API案例
目前官方只发布了 Perl/C++/JAVA三种语言的 API,同时也支持 SOCKET
协议,因此也可以用其他语言来实现,甚至用 telnet都可以。
HandlerSocket 读写模式一般是:
1. 创建连接
2. 打开主键索引,open_index
3. 读写记录, execute_single/execute_find/insert/update/delete
4. 关闭连接
其中,最重要的一个调用方法是:execute_single,如:
execute_single(3, '=', [ 'foo' ], 1, 0)
execute_single 方法的第一个参数需要跟之前 open_index 方法的第一
个参数一致。第二个参数 '='指定了检索条件,目前支持 '=', '>=', '<=',
'>'和'<'。第三个参数[ 'foo' ]为一个 arrayref,指定了检索的 key,其长度
必须小于或者等于对应索引的列数。第四个和第五个参数指定了查询的 limit 和
offset。
HandlerSocket 测试报告
2.3.1 随机读取记录
#!/usr/bin/perl
use strict;
use warnings;
use Net::HandlerSocket;
#1. 创建连接
my $args = { host => '127.0.0.1', port => 9998 };
my $hs = new Net::HandlerSocket($args);
#2. 打开索引
#数值 0 是程序中打开句柄编号,可以自定义;
#test 是数据库名
#t1 是数据表名
#PRIMARY 是主键名
# id,k,c,pad 是后续要进行存取的列名
my $res = $hs->open_index(0, 'test', 't1', 'PRIMARY', 'id,k,c,pad');
die $hs->get_error() if $res != 0;
while (1)
{
#3. 随机读取记录
my $tmp_i = sprintf("%d", rand() * 10000000);
$res = $hs->execute_single(0, '=', [ "$tmp_i" ], 1, 0);
die $hs->get_error() if $res->[0] != 0;
shift(@$res);
for (my $row = 0; $row < 1; ++$row) {
my $id = $res->[$row + 0];
my $k = $res->[$row + 1];
HandlerSocket 测试报告
my $c = $res->[$row + 2];
my $pad = $res->[$row + 3];
#print "tmp_i:$tmp_i, $id, $k, $c, $pad\n";
}
}
#5. 关闭连接
$hs->close();
2.3.2 顺序写入记录
#!/usr/bin/perl
use strict;
use warnings;
use Net::HandlerSocket;
#1.1 establishing a connection
my $args = { host => '127.0.0.1', port => 9999 };
my $hs = new Net::HandlerSocket($args);
#1.2 open index
my $res = $hs->open_index(0, 'test', 't1', 'PRIMARY', 'id,k,c,pad');
die $hs->get_error() if $res != 0;
#2. insert
while (1)
{
my $tmp_i = sprintf("%d", rand() * 10000000);
$res = $hs->execute_insert(0, [ '0',"$tmp_i",'abcy','aasfasdyyy' ]);
my $insert_id = $res->[1];
my $ret = $res->[0];
}
HandlerSocket 测试报告
#4. closing the connection
$hs->close();
2.3.3 更新记录
#!/usr/bin/perl
use strict;
use warnings;
use Net::HandlerSocket;
#1.1 establishing a connection
my $args = { host => '127.0.0.1', port => 9999 };
my $hs = new Net::HandlerSocket($args);
#2 open index
my $res = $hs->open_index(0, 'test', 't1', 'PRIMARY', 'k');
die $hs->get_error() if $res != 0;
#3. update
#$hs->execute_single(0, '=', [ '270337481' ] , 1, 0, 'U', [ '1806176' ]);
#或者
$hs->execute_update(0, '=', [ '270337481' ] , 1, 0, [ '1806177' ]);
#4. closing the connection
$hs->close();
HandlerSocket 测试报告
2.3.4 删除记录
#!/usr/bin/perl
use strict;
use warnings;
use Net::HandlerSocket;
#1 establishing a connection
my $args = { host => '127.0.0.1', port => 9999 };
my $hs = new Net::HandlerSocket($args);
#2 open index
my $res = $hs->open_index(0, 'test', 't1', 'PRIMARY', 'k');
die $hs->get_error() if $res != 0;
#3. delete
#$hs->execute_single(0, '=', [ '270337481' ] , 1, 0, 'D');
#或者
$hs->execute_delete(0, '=', [ '270337480' ] , 1, 0);
#4. closing the connection
$hs->close();
3 API简介
上面已经提到了,HandlerSocket官方目前提供了 C++、PERL、JAVA
HandlerSocket 测试报告
这 3种 API 接口,其他开发语言的 API 需要自己开发,不过也很简单。下面是
HandlerSocket 协议的几个要点:
1. 基于简单的文本交互模式,每次命令以 LF(0x0a)结束
2. 每行文本由多部分标记组成,由HT(0x09)连接起来
3. 每个标记不是 NULL 就是编码后的字符串,如果标记内容为空,必须要
用 NULL来表示,而不是像普通数据库那样不用额外指定
4. NULL 对应的字符是 NUL(0x00)
HandlerSocket 采用了简单的请求/响应协议模式,建立连接后,客户端
发出请求,然后得到响应。主要的几种操作模式有:
1. 建立完连接后,所有的请求都是以 open_index 开始。也就是必须打
开一个主键索引后,才能进行后续的操作,包括:检索、删除、写入、
更新等。Open_index 语法格式为:
P <indexid> <dbname> <tablename> <indexname>
<columns>
2. 建立完连接后,就可以进行相应的数据操作了,例如检索数据:
find。Find 的语法格式为:
<indexid> <op> <vlen> <v1> ... <vn> <limit> <offset>
<mop> <m1> ... <mk>
操作代码OP 目前支持:'=', '>', '>=', '<', '<=' 等几种。
3. 插入新数据,insert 的语法格式为:
<indexid> '+' <vlen> <v1> ... <vn>
HandlerSocket 测试报告
4. 更新数据行,update 语法格式为:
<indexid> <op> <vlen> <v1> ... <vn> <limit> <offset>
<mop> <m1> ... <mk>
和 find 的语法格式是一样的,只不过在这里的 OP 是:U。
5. 删除数据行,delete 的语法格式和 update 一样,把OP 值改成:D。
更多的 API 案例可参考附件文档。
4结语
HandlerSocket 作为目前基于 MySQL InnoDB 引擎的 NOSQL 产品,在
web 3.0 大潮中发挥着重要作用,其独特的设计,高效性能吸引着越来越多的
使用者。在畅游的在线业务中,也有大量的应用场景可以采用,例如:
1. 官网用户验证信息表,这个表可以从原始数据中用触发器等方式维护一
个冗余表,前端验证程序通过 socket 可快速读取进行验证
2. 在线用户表,该表更新频率非常高,采用 handlersocket 将大大提升
其处理效率
3. 其他存储类型简单,读写效率要求很高的类型,例如微博网站的用户好
友关系信息表等
HandlerSocket 测试报告
5参考信息
http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html
http://www.mysqlperformanceblog.com/2011/03/28/whats-up-with-handlersocket/
http://www.mysqlperformanceblog.com/2010/11/02/handlersocket-on-ssd/
测试结果:
1. 同时运行 16 个随机读进程
[@tc_17_77 ~]# mysqladmin ext | egrep -i 'Innodb_rows_inserted|
Innodb_rows_read|handler_read_key|Handler_read_rnd_next|
Uptime_since_flush_status'
| Handler_read_key | 21386311927 |
| Handler_read_rnd_next | 407 |
| Innodb_rows_inserted | 0 |
| Innodb_rows_read | 10092637781 |
| Uptime_since_flush_status | 95763 |
[@tc_17_77 ~]# mysqladmin ext | egrep -i 'Innodb_rows_inserted|
Innodb_rows_read|handler_read_key|Handler_read_rnd_next|
Uptime_since_flush_status'
| Handler_read_key | 21391318101 |
| Handler_read_rnd_next | 780 |
| Innodb_rows_inserted | 0 |
| Innodb_rows_read | 10095000090 |
| Uptime_since_flush_status | 95785 |
每秒读取 innodb rows:105392.2857
HandlerSocket 测试报告
2. 同时运行 8 个随机写进程
[@tc_17_77 ~]# mysqladmin ext | egrep -i 'Innodb_rows_inserted|
Innodb_rows_read|handler_read_key|Handler_read_rnd_next|
Uptime_since_flush_status'
| Innodb_rows_inserted | 51218482 |
| Uptime_since_flush_status | 6863 |
每秒写 innodb rows:7445.9910
第二次测试:
| Innodb_rows_inserted | 737903418 |
| Uptime_since_flush_status | 136252 |
5415.7254
6附件
PERL API 案例:
C++ API 案例:
JAVA API 案 例 : 可 直 接 查 看 google code 资 源 :
http://code.google.com/p/handlersocketforjava/