欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MySQL HandlerSocket插件安装配置教程

程序员文章站 2024-02-29 14:20:46
一、handlersocket是什么?handlersocket是akira higuchi写的一个mysql的插件。以mysql daemon plugin的形式提供类似...

一、handlersocket是什么?
handlersocket是akira higuchi写的一个mysql的插件。以mysql daemon plugin的形式提供类似nosql的网络服务,通过这个插件,你可以直接跟mysql后端的存储引擎做key-value式的交互,省去了mysql上层的sql解释、打开关闭表、创建查询计划等cpu开销。

目前使用mysql的网站,多半同时使用memcache作为键值缓存。虽然这样的架构极其流行,有众多成功的案例,但过于依赖memcache,无形中让memcache成为故障的根源:
memcache数据一致性的问题:当mysql数据变化后,如果不能及时有效的清理掉过期的数据,就会造成数据不一致。这在强调即时性的web2.0时代,不可取。
memcache崩溃后的雪崩效应:作为缓存的memcache一旦崩溃,mysql很可能在短时间内承受高负载而宕机。

注:关于清理过期数据的问题,可以在程序架构上想办法,如果数据操作有统一dao封装的话,可以利用observer模式来清理过期数据,非主题内容,资料自查。

面对以上问题,handlersocket项目是个不错的解决方案,它通过插件的方式赋予mysql完整的nosql功能,从原理上讲,它跳过mysql中最耗时的语法解析,查询计划等步骤,直接读取数据,如果内存够大,能装下索引,mysql的查询效率能提高若干倍!
handlersocket:https://github.com/ahiguti/handlersocket-plugin-for-mysql
php-handlersocket:http://code.google.com/p/php-handlersocket/

系统信息约定:
系统版本:centos 6.3 x86
php安装目录:/usr/local/webserver/php5318
mysql安装目录:/usr/local/webserver/mysql5520
handlersocket安装路径:/usr/local/webserver/handlersocket

二、安装配置handlersocket

安装之前建议你先安装相关支持及需要的组件包:

复制代码 代码如下:
yum install gcc gcc-c++ libtool make openssl-devel perl-dbi perl-dbd-mysql
yum install rpm-build gperf readline-devel ncurses-devel time perl-time-hires

1. 安装
如果使用percona server版本的mysql就简单了,因为它已经内置了handlersocket支持,不过考虑到其内置的版本不够新,存在一些早已修复的bug,所以最好采用源代码编译。handlersocket是基于mysql数据库的,因此在安装handersocket前需要先按照常规方式部署mysql服务,同时需注意handlersocket时需要mysql的源码,因此还需要mysql源码编译方式安装。

复制代码 代码如下:

[root@iredmail opt]# git clone https://github.com/ahiguti/handlersocket-plugin-for-mysql.git
[root@iredmail opt]# cd handlersocket-plugin-for-mysql
[root@iredmail handlersocket-plugin-for-mysql]# ./autogen.sh
[root@iredmail handlersocket-plugin-for-mysql]#./configure --prefix=/usr/local/webserver/handlersocket --with-mysql-source=/opt/mysql-5.5.20 --with-mysql-bindir=/usr/local/webserver/mysql5520/bin --with-mysql-plugindir=/usr/local/webserver/mysql5520/lib/mysql/plugin

tips:
--with-mysql-source 指定mysql源码所在目录
--with-mysql-bindir 表示mysql二进制可执行文件目录
--with-mysql-plugindir 指定mysql插件的存储路径,如果不清楚这个目录在哪,可以按如下方法查询:

复制代码 代码如下:
mysql> show variables like 'plugin%';
+---------------+-------------------------------------------+
| variable_name | value                                     |
+---------------+-------------------------------------------+
| plugin_dir    | /usr/local/webserver/mysql5520/lib/plugin |
+---------------+-------------------------------------------+
1 row in set (0.00 sec)
[root@iredmail handlersocket-plugin-for-mysql]# make

常见错误:

复制代码 代码如下:
libtool: link: only absolute run-paths are allowed
make[2]: *** [handlersocket.la] error 1
make[2]: leaving directory `/opt/handlersocket-plugin-for-mysql/handlersocket'
make[1]: *** [all-recursive] error 1
make[1]: leaving directory `/opt/handlersocket-plugin-for-mysql'
make: *** [all] error 2
解决方法:
[root@iredmail handlersocket-plugin-for-mysql]# vi handlersocket/makefile
line 301:
$(handlersocket_la_link) -rpath $(pkgplugindir) $(handlersocket_la_objects) $(handlersocket_la_libadd) $(libs)
-->
$(handlersocket_la_link) -rpath /opt/handlersocket-plugin-for-mysql/handlersocket $( handlersocket_la_objects) $(handlersocket_la_libadd) $(libs)

[root@iredmail handlersocket-plugin-for-mysql]#make install


完成后,mysql-plugindir目录下应有handlersocket相关文件

2、配置mysql:

修改my.cnf配置文件:

复制代码 代码如下:
[root@iredmail handlersocket-plugin-for-mysql]# vi /etc/my.cnf
[mysqld]
plugin-load=handlersocket.so(plugin-load可略过不配)
loose_handlersocket_port = 9998 # 指定读请求端口号
# the port number to bind to (for read requests)
loose_handlersocket_port_wr = 9999 # 指定写请求端口号
# the port number to bind to (for write requests)
loose_handlersocket_threads = 16 # 指定读线程数目
# the number of worker threads (for read requests)
loose_handlersocket_threads_wr = 1 # 指定写线程数目
# the number of worker threads (for write requests)
open_files_limit = 65535
# to allow handlersocket accept many concurren connections, make open_files_limit as large as possible.

tips:innodb的innodb_buffer_pool_size,或myisam的key_buffy_size等关系到缓存索引的选项尽可能设置大一些,这样才能发挥handlersocket的潜力。

登陆mysql并激活handlersocket插件:

复制代码 代码如下:
[root@iredmail handlersocket-plugin-for-mysql]# mysql -uroot -p
mysql> install plugin handlersocket soname 'handlersocket.so';
error 1126 (hy000): can't open shared library '/usr/local/webserver/mysql5520/lib/plugin/handlersocket.so' (errno: 2 cannot open shared object file: no such file or directory)
说明:这里提示没有找到handlersocket.so扩展文件,请查看扩展文件是否存在。
mysql> install plugin handlersocket soname 'handlersocket.so';
query ok, 0 rows affected (0.00 sec)

mysql> quit;


至此,handlersocket插件安装完毕。

重启mysql服务:

复制代码 代码如下:
[root@iredmail handlersocket-plugin-for-mysql]# service mysqld restart

3、handlersocket状态测试:

MySQL HandlerSocket插件安装配置教程
 
MySQL HandlerSocket插件安装配置教程
 


也可以通过查询刚配置的端口是否已经被mysql占用来确认是否安装成功:
复制代码 代码如下:
[root@iredmail handlersocket-plugin-for-mysql]# lsof -i -p | grep mysqld
mysqld    26871 mysql   11u  ipv4  72467      0t0  tcp *:9998 (listen)
mysqld    26871 mysql   29u  ipv4  72469      0t0  tcp *:9999 (listen)
mysqld    26871 mysql   31u  ipv4  72474      0t0  tcp *:3306 (listen)

tips:if ports 9998 and 9999 don't show up.  make sure selinux is not running.

三、安装配置 php-handlersocket 扩展模块:

1、安装php-handlersocket扩展

复制代码 代码如下:
[root@iredmail opt]# wget http://php-handlersocket.googlecode.com/files/php-handlersocket-0.3.1.tar.gz
[root@iredmail opt]# tar -zxvf php-handlersocket-0.3.1.tar.gz
[root@iredmail opt]# cd handlersocket/
[root@iredmail handlersocket]# /usr/local/webserver/php5318/bin/phpize
[root@iredmail handlersocket]# ./configure --with-php-config=/usr/local/webserver/php5318/bin/php-config

./configure可加参数:

MySQL HandlerSocket插件安装配置教程
 
tips:if you get error:
configure: error: can't find hsclient  headers,please install libhsclient first,or ./configure--disable-handlersocket-hsclient --with-php-config=/usr/local/webserver/php5318/bin/php-config use native type.
复制代码 代码如下:
[root@iredmail handlersocket]#make && make install

a successful install will have created handlersocket.so and put it into the php extensions directory. you'll need to and adjust php.ini and add an extension=handlersocket.so line before you can use the extension.
复制代码 代码如下:
[root@iredmail handlersocket]# vi /usr/local/webserver/php5318/etc/php.ini
extension=handlersocket.so

至此php扩展安装完成,放问php.info页面,我们可以看到已经成功加载了handlersocket扩展

MySQL HandlerSocket插件安装配置教程
 
2、php-handlersocket 使用示例:
复制代码 代码如下:

/*
 * string  $host:mysql ip;
 * string  $port:handlersocket插件的监听端口,它有两个端口可选:一个用于读、一个用于写
 */
$hs = new handlersocket($host, $port);
打开一个数据表:
/*
 * int       $index:这个数字相当于文件操作里的句柄,handlersocket的所有其他方法都会依据这个数字来操作由这个   openindex打开的表,
 * string  $dbname:库名
 * string  $table:表名
 * string  $key:表的“主键”(handlersocket::primary)或“索引名”作为搜索关键字段,这就是说表必须有主键或索引
 *                 个人理解:要被当做where条件的key字段,这样可以认为handlersocket只有一个where条件
 * string  $column:'column1,column2' 所打开表的字段(以逗号隔开),就是说$table表的其他字段不会被操作
 */
$hs->openindex($index, $dbname, $table, $key, $column);
查询:
/*
 * int     $index: openindex()所用的$index
 * string  $operation:openindex方法中指定的$key字段所用的操作符,目前支持'=', '>=', '< =', '>',and '< ';可以理解为where条件
 * array   $value
 * int       $number(默认是1):获取结果的最大条数;相当于sql中limit的第二个参数
 * int     $skip(默认是0):跳过去几条;相当于sql中limit的第一个参数
 */
$retval = $hs->executesingle($index, $operation, $value, $number, $skip);
插入(注意:此处的openindex要用$port_wr,即读写端口):
/*
 * int     $index: openindex()所用的$index
 * array   $arr:数字元素数与openindex的$column相同
 */
$retval = $hs->executeinsert($index, $arr);
删除(注意:此处的openindex要用$port_wr,即读写端口):
/*
 * int     $index: openindex()所用的$index
 * string  $operation:openindex方法中指定的$key字段所用的操作符,目前支持'=', '>=', '< =', '>',and '< ';可以理解为where条件
 * array   $value
 * int     $number(默认是1):获取结果的最大条数;相当于sql中limit的第二个参数
 * int     $skip(默认是0):跳过去几条;相当于sql中limit的第一个参数
 */
$retval = $hs->executedelete($index, $operation, $value, $number, $skip);
更新(注意:此处的openindex要用$port_wr,即读写端口):
/*
 * int     $index: openindex()所用的$index
 * string  $operation:openindex方法中指定的$key字段所用的操作符,目前支持'=', '>=', '< =', '>',and '< ';可以理解为where条件
 * array   $value
 * int       $number(默认是1):获取结果的最大条数;相当于sql中limit的第二个参数
 * int     $skip(默认是0):跳过去几条;相当于sql中limit的第一个参数
 */
$retval = $hs->executeupdate($index, $operation, $value, $number, $skip);

example:
测试库 hstestdb,测试表hstesttbl:

复制代码 代码如下:
create table `hstesttbl` (
  `id` int(11) not null auto_increment,
  `k` char(6) default null,
  `v` char(6) default null,
  primary key (`id`),
  key `idx_hstesttbl_k` (`k`)
) engine=innodb auto_increment=7 default charset=utf8;

php test code:

复制代码 代码如下:

$host       = 'localhost';
$port       = 9998;
$port_wr    = 9999;
$dbname     = 'hstestdb';
$table      = 'hstesttbl';

//get
$hs = new handlersocket($host, $port);
if (!($hs->openindex(1, $dbname, $table, handlersocket::primary, 'k,v'))) {
    echo $hs->geterror(), php_eol;
    die();
}

$retval = $hs->executesingle(1, '=', array('k1'), 1, 0);
var_dump($retval);

$retval = $hs->executemulti(
    array(
        array(1, '=', array('k1'), 1, 0),
        array(1, '=', array('k2'), 1, 0)
    )
);
var_dump($retval);
unset($hs);

//update
$hs = new handlersocket($host, $port_wr);
if (!($hs->openindex(2, $dbname, $table, '', 'v'))) {
    echo $hs->geterror(), php_eol;
    die();
}

if ($hs->executeupdate(2, '=', array('k1'), array('v1'), 1, 0) === false) {
    echo $hs->geterror(), php_eol;
    die();
}

unset($hs);

//insert
$hs = new handlersocket($host, $port_wr);
if (!($hs->openindex(3, $dbname, $table, '', 'k,v'))) {
    echo $hs->geterror(), php_eol;
    die();
}

if ($hs->executeinsert(3, array('k2', 'v2')) === false) {
    echo $hs->geterror(), php_eol;
}
if ($hs->executeinsert(3, array('k3', 'v3')) === false) {
    echo 'a', $hs->geterror(), php_eol;
}
if ($hs->executeinsert(3, array('k4', 'v4')) === false) {
    echo 'b', $hs->geterror(), php_eol;
}

unset($hs);

//delete
$hs = new handlersocket($host, $port_wr);
if (!($hs->openindex(4, $dbname, $table, '', ''))) {
    echo $hs->geterror(), php_eol;
    die();
}

if ($hs->executedelete(4, '=', array('k2')) === false) {
    echo $hs->geterror(), php_eol;
    die();
}
?>

tips:理论上handlersocket支持myisam,innodb等各种引擎,不过推荐使用innodb。
tips:to avoid the insert error,please remember set storage engine:innodb.
tips:对handlersocket一个常见的误解是只能执行primary类型的kv查询,实际上只要支持索引,一般的简单查询它都能胜任,这里就不多说了,官方文档 里有介绍。

handlersocket的缺陷:

(1)写操作并没有淘汰查询缓存——如果执行了写操作通过handlersocket,由于没有失效查询缓存, 那么你可能从mysql读到旧的数据;
(2)不支持自动递增——插入时无法从自增列上自动获得增量值。
鉴于以上问题,扬长避短,使用其合并查询操作,发挥其nosql性能获取mysql的innodb类型表数据,具体操作如下:

复制代码 代码如下:

<?php  
// 通过handlersocket获取数据  
$hs = new handlersocket(hs_host, hs_port);  
if (!($hs->openindex(1, 'dbname', 'table', handlersocket::primary, 'id,content,create_uid,create_user,created,state'))){  
   echo $hs->geterror(), php_eol;  
   die();  
}  
$datalist = array();  
foreach ($ids as $id) {
   $datalist[] = array(1, "=", array($id));  
}  
$data = $hs->executemulti($datalist);  

写在最后的:
mysql5.6提供原生的memcached api,实际就是kv型nosql了,但handlersocket并不局限于kv形式,所以仍然有生存空间。