下一站:HandlerSocket!
来源:Asp之家 发布时间:2011-04-11 09:02:00
目前使用MySQL的网站,多半同时使用Memcache作为键值缓存。虽然这样的架构极其流行,有众多成功的案例,但过于依赖Memcache,无形中让Memcache成为故障的根源:
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 (GFW)
因为HandlerSocket的性能足够好,所以就没有必要使用Memcache了,能节省大量的硬件资源,相当低碳!而且HandlerSocket操作的是MySQL放在内存中的索引,没有额外的缓存,所以自然就不存在数据一致性的问题。
安装
如果使用Percona Server版本的MySQL就简单了,因为它已经内置了HandlerSocket支持,不过考虑到其内置的版本不够新,存在一些早已修复的BUG,所以最好采用源代码编译。
官方已经有了一份简单的安装文档,但在我实际安装时,遇到了一些其他未说明的问题,所以这里就把相应的安装过程再写一遍。
首先要确保已经安装了MySQL5.1以上的版本,我用的是Ubuntu操作系统,事先已经用apt安装了MySQL5.1.37,同时还需要相应的mysql_config,如果是Ubuntu的话,可以:
shell> aptitude install libmysqld-dev
注:如果你用的MySQL是从源代码编译的或官方提供的二进制版本,可以略过此步。
接着下载一份和系统MySQL版本一致的MySQL源代码和HandlerSocket源代码:
ahiguti-HandlerSocket-Plugin-for-MySQL-1.0.6-76-gf5f7443.tar.gz
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里看到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
互联网技术发展犹如一列高速运行的火车,下一站:HandlerSocket!请系好安全带。(来源:火灯笔记)
猜你喜欢
- 例如1441,那么会产生“运行时错误”,报错信息类似下面:SessionID 错误 'ASP 0164 : 80004005'
- Inserted 表中的行是触发器表中新行的副本。 语法 返回所有列 INSERT INTO [tableName] ([columnNam
- 作者:Henny Swan / co-lead of WaSP ILG译者:JunChen / member of WaSP ILG原文:h
- CREATE TABLE table1( [ID] [bigint] IDENTITY(1,1) NOT NULL, [Name] [nva
- 在MySQL的管理过程中,会遇到PC Server脱机或者重启,我需要在主机启动后再将MySQL服务启动。如果上百台或者更多的MySQL主机
- 过滤html代码的函数,当然也可以使用正则表达式。<%Function FilterHTML(strToFilter)&nb
- 一、DAFONT 英文字体很多,分类很详细,字体多数都是免费,唯一的缺点中文字体少了些.http://www.dafont.co
- CSS样式和JavaScript脚本是应该放在外部文件中呢?还是把它们放在页面本身之内呢?如何处理是关于一些性能规则的思维,就这些问题,我们
- 参数strSQL 要导出的SQL查询语句strFields 字段名称列表,如果为空字符,则使用SQL语句中的字段名用法示例:1:export
- 昨天在网上看到一个防采集软件,说采集只访问当前网页,不会访问网页的图片、JS等,今天突然想到,通过动态程序和Js访问分别记录访问者的IP,然
- 代码如下:--CAST 和 CONVERT 函数 Percentage DECLARE @dec decimal(5,3), @var va
- DTD实际上可以看作一个或多个XML文件的模板,这些XML文件中的元素、元素的属性、元素的排列方式/顺序、元素能够包含的内容等,都必须符合D
- 本文详细解说了MySQL Order By Rand()效率优化的方案,并给出了优化的思路过程,是篇不可多得的MySQL Order By
- 在看到7yue博客——“换手来用”的思考 有这么一句话:RIA是一个更趋向于“体验”设计的领域,不仅仅包括“开发人员”,还包括“设计人员”,
- 如何在线查询本地机的文件?看看下面的例子,默认子目录与子虚拟目录为同一级别且名称一致,另我们使用了"http://intels.n
- asp数字分页涵数参数说明:SQL: 查询语句,PageSizeN: 每页显示多少新闻记录classid: 栏目ID,PageCountS:
- 惊叹于老外的发现 《CSS Background image on html image element?》,自己从没关注过,也没想过如此的
- 似乎讨论分页的人很少,难道大家都沉迷于limit m,n?在有索引的情况下,limit m,n速度足够,可是在复杂条件搜索时,where s
- 阅读上一篇:W3C优质网页小贴士(一) 使用 alt 属性描述每幅图像alt 属性有什么用?alt 属性可以在一系列标签中使用(如
- 锁是指在某组资源中,两个或两个以上的线程在执行过程中,在争夺某一资源时而造成互相等待的现象,若无外力的作用下,它们都将无法推进下去,死时就可