分页: 3/74 第一页 上页 1 2 3 4 5 6 7 8 9 10 下页 最后页 [ 显示模式: 摘要 | 列表 ]

目前使用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

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

原文:http://huoding.com/2011/04/10/62

nginx的location值里没有查询字符,所以在匹配地址时用不到查询字符
另外,rewrite时,默认会把查询字符带上的,加上问号即可解决。

假设要把 /question.php?qid=123 的地址跳转到 /question/123.html
location /question.php {
  rewrite ^ /question/$arg_qid.html redirect;
}


我们会发现地址变成 /question/123.html?qid=123
你要的参数都可以找到 $arg_qid ( $arg_变量名称 )
nginx里面,在后面加上问号就可以不带上查询字符了

location /question.php {
  rewrite ^ /question/$arg_qid.html? redirect;
}


对值有要求的,可以匹配 $args ,比如(复制别人的)

location / {
    if ($args ~* "/?param1=val1&param2=&param3=[0-9]+&param4=.+&param5=[0-9]+") {
        rewrite ^ http://www.example.com/newparam/$arg_param3/$arg_param4? last;
    }
}


Tags: , ,
先温习一下替换文件里的字符的功课:

[root@aslibra ~]# ll *.html
-rw-r--r-- 1 root root 22 Aug 21 00:50 a.html
-rw-r--r-- 1 root root 32 Aug 21 00:51 index.html
[root@aslibra ~]# find . -name "*.html" | xargs sed -i 's/192/9999/'
[root@aslibra ~]# cat *.html
sdfjsldjf
9999
sdfdfdf
sldkjflsdjf
ksdjfsjd 9999
sdfsdf
[root@aslibra ~]# find . -name "*.html" | xargs sed -i 's/9999/+++++/'
[root@aslibra ~]# cat *.html
sdfjsldjf
+++++
sdfdfdf
sldkjflsdjf
ksdjfsjd +++++
sdfsdf


上面代码在linux下正常,可在mac下不正常了:

localhost:tmp hqlulu$ find . -name "*.html" | xargs sed -i 's/9999/+++++/'
sed: 1: "./a.html": invalid command code .


sed方式有点不一样,需要用 sed -iE ,当然,我们可以找到别的方式,比如perl(搜得):

perl -pi -e 's/9999/+++++/g'

下面我们看看怎么修改svn库的地址~
svn的组织方式是在目录下有.svn的目录,里面有一个entries文件,记录了svn的地址
windows下的乌龟提供了relocation功能,mac下的svn工具暂时没有发现
不过没关系,这个事情很简单

比如你的svn服务器调整了,从192.168.1.1更换为 svn.aslibra.com 里
我们先确认一下是否存在

find . -name entries | xargs grep 192.168.1.1
#你会得到类似内容:
./.svn/entries:svn://lhq@192.168.1.1/server


我们运行如下命令修改:

find . -name entries | xargs perl -pi -e 's/192.168.1.1/svn.aslibra.com/g'


OK~
Tags: , , , ,
一些文件操作如果需要和web服务器通信,是可以考虑用curl的。
正常的POST表单:

curl -d "user=nickwolfe&password=test" http://www.aslibra.com/?test.php


上传文件:

localhost:aslibra$ curl -F upload=@/Media/test.txt http://www.aslibra.com/?test/upload
Array
(
    [upload] => Array
        (
            [name] => test.txt
            [type] => text/plain
            [tmp_name] => /tmp/phpKDS0MR
            [error] => 0
            [size] => 335
        )
)


简单的php处理代码:

print_r($_FILES);
if(isset($_FILES['upload'])){
  @copy( $_FILES['upload']['tmp_name'], '/tmp/upload_'.$_FILES['upload']['name'] );
  @unlink( $_FILES['upload']['tmp_name'] );    
}

Tags: , ,
今天同事说下载某个图片回来浏览器读取不了,但地址直接放浏览器是正常的。
分析了一下,该图片服务器返回的数据是gzip压缩的,而且不管客户端是否发出支持与否,都按gzip格式发了

下载回来的文件格式为:
jhs_9.jpg: ASCII text, with CRLF line terminators
显然不是图片格式,是文本流

curl -I http://xxx/uploadimages/api/jhs_9.jpg
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 11 Aug 2011 01:58:15 GMT
Content-Type: image/jpeg
Connection: keep-alive
Last-Modified: Mon, 11 Jul 2011 02:05:56 GMT
ETag: "4cd000000000516-40ca-4a7c19fa8a900"
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 16560
Accept-Ranges: bytes


这个其实就做一个gzip解压就可以了:
Tags: , ,
今天测试nginx的按时间缓存,发现两个问题:

1 proxy_cache_purge的1.0版本安装到0.8.54版本会出错,请安装1.3版本,否则清除缓存时curl会收到“curl: (52) Empty reply from server”,没法清除缓存
2 proxy_store和它是冲突的,proxy_store off才行,如果http段全局有on,那就在这里需要声明off

安装proxy_cache_purge你可以访问这里查看到官方提供的第三方插件http://wiki.nginx.org/3rdPartyModules
访问 http://labs.frickle.com/nginx_ngx_cache_purge/查看具体配置方式

引用
#### proxy_cache_path 指令指定缓存的路径和一些其他参数,缓存的数据存储在文件中。缓存的文件名和key为代理URL的MD5 码。levels参数指定缓存的子目录数,所有活动的key和元数据存储在共享的内存区域中,这个区域用keys_zone参数指定,keys_zone指定缓存的名字和共享内存大小,如果在inactive参数指定的时间内缓存的数据没有被请求则被删除,默认inactive为10分钟。cache manager进程控制磁盘的缓存大小,在max_size参数中定义,超过其大小后最少使用数据将被删除。
    proxy_cache_path /www/ng_cache levels=1:2 keys_zone=tmp_cache:1000m inactive=1d max_size=10000m;


关于安装的文章太多,不重复。

缓存的特点:

md5值分段截取为文件夹
1,2层级的目录是md5值的后面1个字符和2个字符作为文件夹的
有记KEY值和相应的头信息

[root@aslibra nginx]# head d/8a/353329a20615078e7391e2c4d091e8ad
?;AN????O9AN??
              ?=???
KEY: www.aslibra.com/test/beijing/
HTTP/1.1 200 OK
Server: nginx/0.8.15
Date: Tue, 09 Aug 2011 13:42:40 GMT
Content-Type: text/html; charset=utf-8
Connection: close
X-Powered-By: PHP/5.2.10

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">....


清除缓存的响应:

[root@aslibra nginx-0.8.54]# curl -H "host:www.aslibra.com" 127.0.0.1/purge/test/
<html>
<head><title>Successful purge</title></head>
<body bgcolor="white">
<center><h1>Successful purge</h1>
<br>Key : www.aslibra.com/test/
<br>Path: /Data/cache/nginx/d/8a/353329a20615078e7391e2c4d091e8ad
</center>
<hr><center>nginx/0.8.54</center>
</body>
</html>
[root@aslibra nginx-0.8.54]# curl -H "host:www.aslibra.com" 127.0.0.1/purge/test/
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/0.8.54</center>
</body>
</html>



Tags: ,
今天测试一台服务器的php代码,发现 $_SERVER["PHP_SELF"] 是空值,这个真是奇怪,原先运行nginx没事,换成lighttpd就出了问题。我在别的地方的lighttpd没有这个毛病,经过判断,可能是php编译或者设置的问题。

特别的对照了phpinfo里面的 cgi-fcgi 一栏的配置
cgi.fix_pathinfo 的值不同
找到php的配置文件,设置为1,解决~
分页: 3/74 第一页 上页 1 2 3 4 5 6 7 8 9 10 下页 最后页 [ 显示模式: 摘要 | 列表 ]

阅读推荐

服务器相关推荐

开发相关推荐

应用软件推荐