php HandlerSocket的使用
- memcache数据一致性的问题:当mysql数据变化后,如果不能及时有效的清理掉过期的数据,就会造成数据不一致。这在强调即时性的web2.0时代,不可取。
- memcache崩溃后的雪崩效应:作为缓存的memcache一旦崩溃,mysql很可能在短时间内承受高负载而宕机。据说前段时间新浪微博就遭遇了这样的问题。
注:关于清理过期数据的问题,可以在程序架构上想办法,如果数据操作有统一dao封装的话,可以利用observer模式来清理过期数据,非主题内容,资料自查。
面对这些问题,handlersocket项目是个不错的解决方案,它通过插件的方式赋予mysql完整的nosql功能,从原理上讲,它跳过mysql中最耗时的语法解析,查询计划等步骤,直接读取数据,如果内存够大,能装下索引,mysql的查询效率能提高若干倍!
性能测试:using mysql as a nosql – a story for exceeding 750,000 qps (f*ck gfw)
因为handlersocket的性能足够好,所以就没有必要使用memcache了,能节省大量的硬件资源,相当低碳!而且handlersocket操作的是mysql放在内存中的索引,没有额外的缓存,所以自然就不存在数据一致性的问题。
安装
如果使用percona server版本的mysql就简单了,因为它已经内置了handlersocket支持,不过考虑到其内置的版本不够新,存在一些早已修复的bug,所以最好采用源代码编译。
注:旧版本handlersocket的一些问题可参见:what's up with handlersocket?
官方已经有了一份简单的安装文档,但在我实际安装时,遇到了一些其他未说明的问题,所以这里就把相应的安装过程再写一遍。
首先要确保已经安装了mysql5.1以上的版本,我用的是ubuntu操作系统,事先已经用apt安装了mysql5.1.37,同时还需要相应的mysql_config,如果是ubuntu的话,可以:
shell> aptitude install libmysqld-dev
注:如果你用的mysql是从源代码编译的或官方提供的二进制版本,可以略过此步。
接着下载一份和系统mysql版本一致的mysql源代码和handlersocket源代码:
shell> tar zxf mysql-5.1.37.tar.gz shell> tar zxf ahiguti-handlersocket-plugin-for-mysql-1.0.6-76-gf5f7443.tar.gz shell> cd ahiguti-handlersocket-plugin-for-mysql-f5f7443 shell> ./autogen.sh shell> ./configure --with-mysql-source=../mysql-5.1.37 \ --with-mysql-bindir=/usr/bin \ --with-mysql-plugindir=/usr/lib/mysql/plugin
其中的参数含义如下:with-mysql-source表示mysql源代码目录,with-mysql-bindir表示mysql二进制可执行文件目录(也就是mysql_config所在目录),with-mysql-plugindir表示mysql插件目录,如果不清楚这个目录在哪,可以按如下方法查询:
mysql> show variables like 'plugin%'; +---------------+-----------------------+ | variable_name | value | +---------------+-----------------------+ | plugin_dir | /usr/lib/mysql/plugin | +---------------+-----------------------+
运行命令后,如果你使用的是mysql5.1.37版本的话,会遇到如下错误信息:
mysql source version does not match mysql binary version
明明我们的mysql源代码版本和二进制版本都是5.1.37,为什么还会出现这个错误呢?通过查询handlersocket的编译脚本,发现原来它会检索mysql源代码目录中的version文件,可mysql5.1.37的源代码目录里不知何故竟然没有这个文件,所以就报错了,既然知道了原因,那我们就照猫画虎做一个version文件放到mysql源代码目录,内容如下:
mysql_version_major=5 mysql_version_minor=1 mysql_version_patch=37 mysql_version_extra=
再次运行configure脚本,应该就ok了,把剩下的步骤进行完:
shell> make shell> make install
接着需要配置一下handlersocket,编辑mysql配置文件,加入如下内容:
[mysqld] 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 concurrent # connections, make open_files_limit as large as # possible.
此外,innodb的innodb_buffer_pool_size,或myisam的key_buffy_size等关系到缓存索引的选项尽可能设置大一些,这样才能发挥handlersocket的潜力。
注:apt包管理下的配置文件一般是/etc/mysql/my.cnf,否则一般是/etc/my.cnf
最后登陆mysql并激活handlersocket插件:
mysql> install plugin handlersocket soname 'handlersocket.so';
重启一下mysql服务,如果没有问题,就能在mysql里看到handlersocket的线程了:
mysql> show processlist;
也可以通过查询刚配置的端口是否已经被mysql占用来确认是否安装成功:
shell> lsof -i :9998 shell> lsof -i :9999
完活儿!现在你的mysql已经具备nosql的能力了!
实战
首先创建一个测试用的表:
create table if not exists `test`.`t` ( `id` int(10) unsigned not null auto_increment, `a` varchar(10) not null, `b` varchar(10) not null, primary key (`id`), key `a_b` (`a`,`b`) ) engine=innodb;
注:理论上handlersocket支持myisam,innodb等各种引擎,不过推荐使用innodb。
handlersocket的协议非常简单,指令通过tab分割,一行就是一个请求。本文用到了:
- 打开索引:p <索引标识> <数据库> <表> <索引> <字段>
- 插入数据:<索引标识> ‘+' <参数个数> <参数1> … <参数n>
- 读取数据:<索引标识> <操作> <参数个数> <参数1> … <参数n> <条数> <偏移>
sql原型:insert into test.t (id, a, b) values (1, ‘a1′, ‘b1′), (2, ‘a2′, ‘b2′)
shell> telnet localhost 9999 trying 127.0.0.1... connected to localhost. escape character is '^]'. p 1 test t primary id,a,b 0 1 1 + 3 1 a1 b1 0 1 0 1 + 3 2 a2 b2 0 1 0
注:使用handlersocket时,因为没有实际运行sql,所以binlog记录的是row格式。
sql原型:select id, a, b from test.t where id = 1 limit 1
shell> telnet localhost 9999 trying 127.0.0.1... connected to localhost. escape character is '^]'. p 1 test t primary id,a,b 0 1 1 = 1 1 1 0 0 3 1 a1 b1
sql原型:select id, a, b from test.t where id >=1 limit 2
shell> telnet localhost 9999 trying 127.0.0.1... connected to localhost. escape character is '^]'. p 1 test t primary id,a,b 0 1 1 >= 1 1 2 0 0 3 1 a1 b1 2 a2 b2
sql原型:select id, a, b from test.t where a = ‘a1′ and b = ‘b1′ limit 1
shell> telnet localhost 9999 trying 127.0.0.1... connected to localhost. escape character is '^]'. p 1 test t a_b id,a,b 0 1 1 = 2 a1 b1 1 0 0 3 1 a1 b1
对handlersocket一个常见的误解是只能执行primary类型的kv查询,实际上只要支持索引,一般的简单查询它都能胜任,篇幅所限,这里就不多说了,如果你觉得直接操作telnet有些吃力,也可以使用自己熟悉的客户端来测试,官方文档里有介绍。
注:handlersocket作者写了一个不错的ppt可以参考:handlersocket plugin for mysql
记:mysql5.6提供原生的memcached api,实际就是kv型nosql了,但handlersocket并不局限于kv形式,所以仍然有生存空间。
互联网技术发展犹如一列高速运行的火车,下一站:handlersocket!大家做好准备吧。
上一篇: 一个简洁的多级别论坛
下一篇: .httacces文件的配置技巧