20
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 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

Handler socket测试报告 - 20110422

Embed Size (px)

DESCRIPTION

MySQL Handler socket测试报告

Citation preview

Page 1: Handler socket测试报告 - 20110422

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

Page 2: Handler socket测试报告 - 20110422

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 产品在数据分析中的表现,考察

其在公司业务生产环境中实施的可行性及其性能。

Page 3: Handler socket测试报告 - 20110422

HandlerSocket 测试报告

1.1HandlerSocket简介

简言之,HandlerSocket 是一个基于 MySQL InnoDB 引擎的 NOSQL 产

品,采用原生态 API 方式操作 InnoDB 引擎表空间文件。作者 Akira Higuchi

是日本人,2010 年 8 月离开 Oracle,加盟日本社交游戏公司 DeNA。它最重要

的特点就是绕过 MySQL 的 SQL 解析层、查询优化器、缓存层,直接用原生

API 存取 InnoDB 引擎表空间文件,因此获得了性能上的 N 个数量级提升。

1.2HandlerSocket体系结构

HandlerSocket 的体系结构如下图所示:

Page 4: Handler socket测试报告 - 20110422

HandlerSocket 测试报告

如简介中提到的,libhsclient 直接访问 Handlersocket Plugin,绕过了

listener 和 SQL Layer,从而获得了性能上的极大提升。

1.2.1 关于HandlerSocket性能

这是作者进行的对比测试结果:

Page 5: Handler socket测试报告 - 20110422

HandlerSocket 测试报告

HandlerSoket 效率非常高的原因是:

1. 绕过 SQL 解析层,大大降低了 CPU 消耗

2. 将分散的请求转化成批量操作,降低了 CPU、磁盘 IO 消耗

3. 采用自定义的服务/客户协议,降低了网络 IO 消耗

下面是用 Oprofile 工具对比探测的结果,测试方法是在客户端并发执行多

次类似操作操作 SELECT v from table where k = ?

1. 采用原始的 libmysql 接口

Page 6: Handler socket测试报告 - 20110422

HandlerSocket 测试报告

明显的看到,mysqld 进程消耗了大量 CPU 资源。

看下 mysqld 进程内部的详细情况:

可以看到,SQL 解析层消耗了最多的 CPU 资源。

再看下 linux 内核的具体情况:

Page 7: Handler socket测试报告 - 20110422

HandlerSocket 测试报告

Schedule 调用消耗了最多的 CPU 资源。

2. 采用 HandlerSocket 专用接口

明显的看到,mysqld 进程消耗了大量 CPU 资源。

看下 mysqld 进程内部的详细情况:

Page 8: Handler socket测试报告 - 20110422

HandlerSocket 测试报告

可以看到,MySQL 内部消耗 CPU 资源最多的是 InnoDB 相关的调用。

再看下 linux 内核的具体情况:

Schedule 调用已经不是消耗 CPU 资源最多的了。

Page 9: Handler socket测试报告 - 20110422

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

Page 10: Handler socket测试报告 - 20110422

HandlerSocket 测试报告

1.3HandlerSocket读写线程模型

1. 读线程模型

2. 写线程模型

Page 11: Handler socket测试报告 - 20110422

HandlerSocket 测试报告

1.4HandlerSocket客户/服务器协议

传统的 MySQL 客户/服务器协议用 tcpdump 结果如下:

相比之下,HandlerSocket 协议就简单了很多:

相应的网络 IO 统计差别非常大:

Page 12: Handler socket测试报告 - 20110422

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

Page 13: Handler socket测试报告 - 20110422

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 个连接,

Page 14: Handler socket测试报告 - 20110422

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。

Page 15: Handler socket测试报告 - 20110422

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];

Page 16: Handler socket测试报告 - 20110422

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];

}

Page 17: Handler socket测试报告 - 20110422

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();

Page 18: Handler socket测试报告 - 20110422

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

Page 19: Handler socket测试报告 - 20110422

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>

Page 20: Handler socket测试报告 - 20110422

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. 其他存储类型简单,读写效率要求很高的类型,例如微博网站的用户好

友关系信息表等

Page 21: Handler socket测试报告 - 20110422

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

Page 22: Handler socket测试报告 - 20110422

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/