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!大家做好准备吧。

(0)

相关推荐

  • 深入php socket的讲解与实例分析

    在这一章里你将了解到迷人而又让人容易糊涂的套接字(Sockets).Sockets在PHP中是没有充分利用的功能.今天你将看到产生一个能使用客户端连接的服务器,并在客户端使用socket进行连接,服务器端将详细的处理信息发送给客户端.当你看到完整的socket过程,那么你将会在以后的程序开发中使用它.这个服务器是一个能让你连接的HTTP服务器,客户端是一个Web浏览器,这是一个单一的 客户端/服务器 的关系. ◆ Socket 基础PHP使用Berkley的socket库来创建它的连接.你可以知

  • 浅析PHP Socket技术

    phpsocketSocket位于TCP/IP协议的传输控制协议,提供客户-服务器模式的异步通信,即客户向服务器发出服务请求,服务器接收到请求后,提供相应的反馈或服务!我练习了一个最基本的例子: 使用并发起一个阻塞式(block)连接,即服务器如果不返回数据流,则一直保持连接状态,一旦有数据流传入,取得内容后就立即断开连接.代码如下: 复制代码 代码如下: <?php$host = www.sohu.com; //这个地址随便,用新浪的也行,主要是测试用,哪个无所谓$page = "/in

  • php空间不支持socket但支持curl时recaptcha的用法

    1.修改recaptchalib.php中的两个方法 复制代码 代码如下: function _recaptcha_http_post($host, $path, $data, $port = 80) { $req = _recaptcha_qsencode ($data); $response = ''; $url = $host.$path; $post_data = $req; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url);

  • 在php中使用sockets:从新闻组中获取文章

    PHP能打开远程或本地主机上的Socket端口.本文是一个使用Socket的小例子:连接到一个Usenet新闻组服务器,同服务器对话,从新闻组中下载一些文章. 在php中打开一个socket使用fsockopen()打开一个socket.这个函数在php3和php4种都可以使用.函数声明是这样的: int fsockopen (string hostname, int port _[, int errno [, string errstr [, double timeout]]]) 这个函数将打

  • 使用php通过Socket进行发信源码,支持发信认证

    使用php直接打开socket端口进行发信的小程序特点是使用smtp认证,能够更好的使用满足一般网友建站需要. 整个源码附在本文中,同样内容可到下列地址下载.转载请注明出处. http://www.knowsky.com/download/phpsendmail.rar /******************************************//*          Php webmail sender            *//*           www.ebugs.org

  • 基于PHP Socket配置以及实例的详细介绍

    2个php测试文件server.php 复制代码 代码如下: <?php     //phpinfo();//确保在连接客户端时不会超时set_time_limit(0);$ip = '127.0.0.1';$port = 1935;/* +------------------------------- *    @socket通信整个过程 +------------------------------- *    @socket_create *    @socket_bind *    @s

  • PHP异步调用socket实现代码

    PHP异步调用实现方式 浏览器和服务器之间只一种面向无连接的HTTP协议进行通讯的,面向无连接的程序的特点是客户端请求服务端,服务端根据请求输出相应的程序,不能保持持久连接. 这样就出现了一个问题,一个客户端的相应服务端可能执行1秒也有可能执行1分钟,这样浏览器就会一直处于等待状态,如果程序执行缓慢,用户可能就没耐心关掉了浏览器. 而有的时候我们不需要关心程序执行的结果,没有必要这样浪费时间和耐心等待,那我们就要想出办法让程序不收等待在后台静默执行. 比如现在有一个场景,给1000个用户发送一封

  • 解析:通过php socket并借助telnet实现简单的聊天程序

    以下是通过php的socket扩展模块实现的一个简单的消息处理服务器端:绑定在一个本机的端口,监听客户端的连接,接收数据并转发给发送者之外的所有客户端socket_server.php 复制代码 代码如下: #!/usr/bin/env php<?php//author:zhxiaif(!extension_loaded('sockets')){    die('the sockets extension is not loaded!');}const PORT=9981;$socket=soc

  • php模拟socket一次连接,多次发送数据的实现代码

    复制代码 代码如下: <?php //post.php function Post($host,$port) { //$host="127.0.0.1"; //建立连接 $conn = fsockopen($host,$port); if (!$conn) { die("Con error"); } //循环发送5次数据 // for($i = 0;$i<5;$i++) { $data="user_name=admin".$i; Wr

  • PHP实现Socket服务器的代码

    <?php ob_implicit_flush(); set_time_limit(0); $address = "192.40.7.93";//换成你自己的地址 $port = 10000; if(($socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) == false)  echo "错误(socket_create):".socket_strerror(socket_last_error()).&qu

  • PHP Socket 编程

    下面是相应的代码: PHP 代码: 复制代码 代码如下: <? // 设置一些基本的变量 $host = "192.168.1.99"; $port = 1234; // 设置超时时间 set_time_limit(0); // 创建一个Socket $socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n"); //绑定Socket到端口 $resul

  • PHP SOCKET 技术研究

    今天试着写一个 PHP 与 C 语言通过socket通讯的程序,看过PHP手册,发现有好几种方式可以建立socket 客户端. 1.通过 fsockopen() 建立socket连接,然后用 用fputs() 发送消息,用 fgets() 接收消息. 2.通过 socket_create() 建立 socket 连接,然后用 socket_send() or socket_write() 发送消息,用 socket_recv() or socket_read() 发送消息. 很奇怪,我在手册上看

  • php win下Socket方式发邮件类

    复制代码 代码如下: <?php /* * php smtp发送邮件Scoket类 * ZhozPhpSmtpSendMail.php * Created on 2008/09/02 zhoz.com * @author zhoz * v 1.72 update 2008/09/26 zhoz.Com */ class ZhozPhpSmtpSendMail { //您的SMTP 服务器供应商,可以是域名或IP地址 var $smtp = ""; //SMTP需要要身份验证设值为

  • php中使用Curl、socket、file_get_contents三种方法POST提交数据

    抓取远程内容,之前一直都在用file_get_content函数,其实早就知道有curl这么一个好东西的存在,但是看了一眼后感觉使用颇有些复杂,没有file_get_content那么简单,再就是需求也不大,所以没有学习使用curl.直到最近,要做一个网页小偷程序的时候才发现file_get_content已经完全不能满足需求了.我觉得,在读取远程内容的时候,file_get_content除了使用比curl便捷以外,其他都没有curl好. php中curl和file_get_content的一

  • 基于php socket(fsockopen)的应用实例分析

    fsockopen函数能够运用,首先要开启php.ini中的allow_url_open=on;fsockopen是对socket客户端代码的封装,该函数中封装了socket_create,socket_connect.服务器端代码:server.php 复制代码 代码如下: <?phperror_reporting(E_ALL);set_time_limit(0);$address = '127.0.0.1';$port = 10008;//创建端口if (($sock = socket_cr

  • php socket方式提交的post详解

    <?  /*  ** POST报文到主机  */  function PostToHost($url, $data) {  $url = parse_url($url);  if (!$url) return "couldn\'t parse url";  if (!isset($url[\'port\'])) { $url[\'port\'] = ""; }  if (!isset($url[\'query\'])) { $url[\'query\'] = 

  • php获取远程图片的两种 CURL方式和sockets方式获取远程图片

    方式1:sockets 复制代码 代码如下: $a = "http://jb51.net/content/uploadfile/201106/thum-f3ccdd27d2000e3f9255a7e3e2c4880020110622095243.jpg"; $local = 'socket1.gif'; $aa = getImg($a,$local); /* *@ 完整的图片地址 *@ 要存储的文件名 */ function getImg( $url = "", $

  • 在PHP中使用Sockets 从Usenet中获取文件

    作者:Armel Fauveau  原文地址:http://www.phpbuilder.net/columns/armel20010427.php3 PHP能够打开远程或者本地服务器的sockets!这里是一个使用socket的简单的例子:连接到Usenet的新闻服务器,与服务器沟通,并从一个精确的新闻分组中下载一些文章. 使用PHP打开Socket 使用fsockopen()来打开一个Socket.这个函数在PHP3和PHP4中都存在.函数的原型如下: <?php intfsockopen 

随机推荐