那一天,人们终于回想起了被BUG支配的恐惧
Toggle navigation
Home
AboutMe
Links
Archives
Tags
Memcache初探
2016-03-20 23:48:41
374
1
0
weibo-007
#memcached介绍 memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力。它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,memcached自管理这些HashTable。为什么会有Memcache和memcached两种名称? 其实memcache是这个项目的名称,而memcached是它服务器端的主程序文件名。Memcache在高并发的情况下通过将热数据缓存到内存中来降低数据库的压力,这是目前很多网站使用Memcache的原因。 #memcached的安装 memcached的安装非常简单,去官方网站下载http://memcached.org/downloads最新的memcached资源,安装方式很简单,官方例子。唯一比较不能接受的一点是,城外的网都比较慢 ``` wget http://memcached.org/latest tar -zxvf memcached-1.x.x.tar.gz cd memcached-1.x.x ./configure && make && make test && sudo make install ``` #启动memcached服务 进入到memcached的安装目录,然后通过`daemon的方式启动`起来。 ``` localhost:Downloads MLS$ cd memcached-1.4.23 localhost:memcached-1.4.23 MLS$ ./memcached -d ``` `检查memcached进程`是否已经启动起来: ``` localhost:memcached-1.4.23 MLS$ ps -ef | grep memcached | grep -v grep 501 6978 1 0 9:37下午 ?? 0:00.01 ./memcached -d ``` 可以看到memcached服务以daemon的形式在后台运行,我们并没有制定端口和IP。memcached默认的端口11211,默认的IP就是本机地址127.0.0.1。当然memcached还给我们分配了默认的内存空间。 #Linux下试玩memcached 我们可以使用`telnet进入memcached`的运行环境,进入之后就可以对memcached进行基本的操作了 ``` localhost:memcached-1.4.23 MLS$ telnet 127.0.0.1 11211 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. ``` 注意,退出命令是`quit`加`回车` ##memcached基本命令的格式 <操作> <key> <额外信息> <存活时间> <存储字节数> <值> 注意,存活时间的单位是秒,0表示永久不过期, 操作命令包括以下操作: `set`表示按照相应的<key>存储该数据,没有的时候增加,有的覆盖。 `add`表示按照相应的<key>添加该数据,但是如果该<key>已经存在则会操作失败。 `replace`表示按照相应的<key>替换数据,但是如果该<key>不存在则操作失败 `get`获取一个key为name的数据 `delete`删除一个key为name的数据,返回DELETED表示删除成功 ##set操作 set操作注意最后一个表示字节长度的限制,如果设置的值得长度和实现指定的不符合,将抛出ERROR;如果返回STORED表示存储成功 ``` set name 0 0 7 zhongyx STORED ``` 注意指定长度的时候要严格限制,比如下面这个命令就会发生错误 ``` set key1 0 0 7 yongxiongzhong CLIENT_ERROR bad data chunk ERROR ``` ##get操作 比如获取一个key为name的数据 ``` get name VALUE name 0 7 zhongyx END ``` ##delete操作 删除一个key为name的数据,返回DELETED表示删除成功 ``` delete name DELETED ``` ##replace操作 进行replace操作的时候,一定要确保已经设定过该key的缓存值,否则会返回一个错误,假设name是存在的情况 ``` replace name 0 0 7 yongxio STORED ``` 当尝试去replace一个不存在的值时候 ``` replace name1 0 0 7 zhongyx NOT_STORED ``` #在PHP中使用memcached memcached的命令模式已经熟悉的差不多了,但是,最终我们是需要将memcached的服务接入到我们的实际应用中,由于本人就是基于php的web开发,所以本人是在PHP的环境中使用memcached服务。整个安装过程有点繁琐 ## 安装依赖库 https://launchpad.net/libmemcached/1.0/1.0.4/+download/libmemcached-1.0.4.tar.gz ``` tar -xzvf libmemcached-1.0.4.tar.gz cd libmemcached-1.0.4 ./configure && make && make install ``` ##安装memcached扩展 这里采用php扩展库里面的资源。http://pecl.php.net/get/memcached-2.0.1.tgz下载 ``` tar vxzf memcached-2.0.1.tgz cd memcache-2.0.1 phpize ./configure && make && make install ``` 装完后,最后显示Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20121212/,在该目录下生成memcached.so 我的so文件/usr/lib/php/extensions/no-debug-non-zts-20121212/memcached.so ##php配置文件中加入memcached扩展 修改php.ini文件,添加memcached扩展php.ini文件最后一行添加以下代码 ``` extension=/usr/lib/php/extensions/no-debug-non-zts-20121212/memcached.so ``` 重启php,如果安装成功,可以访问phpinfo看到以下界面 <img src="http://leanote.com/api/file/getImage?fileId=56ed259eab644116760001aa" width="500" /> ##php中使用memcached服务 在php中使用memcached非常简单,如果安装了memcached扩展,直接在php中`new Memcached`之后就可以正式使用memcached服务了,在实际应用中,一般是`set`和`get`为主 ``` <?php $mc = new Memcached(); $mc->addServer("localhost", 11211); $mc->set("foo", "Hello!"); $mc->set("bar", "Memcached..."); $arr = array( $mc->get("foo"), $mc->get("bar") ); var_dump($arr); ?> ``` ##第一个memcached应用例子 在早些年,不知道现在还有没有这种使用方法,看到php的相关教程中有以下使用例子,缓存是做在数据库层,也就是缓存的key是SQL语句的md5值,当需要从数据库中区数据的时候,需要看下memcached中时候有数据,如果通过取数据的SQL命中缓存,则直接返回结果。 ``` <?php $sql = "select * from user where id={$_GET['uid']}"; //检查缓存 $mc = new Memcached(); $mc->addServer("localhost", 11211); $row = $mc -> get(md5($sql)) if($row){ return $row; } //查询数据库 $conn = new mysql('localhost', '3306', 'root', '123456'); ....//此处省略数据库查询 $mc->set(md5($sql), $row); ``` 这种方式应该算是一种最简单的方式了,比较简单,不过这种方式也有它的缺点 1. 现在的数据库操作一般都采用PDO方式的预处理语句 2. select * 和 select username会存储不一样的缓存中,结果冗余,而且命中率低 3. 很难排查问题,获取缓存的key比较难 ##第二个memcached的应用例子 目前比较多的缓存放在业务层,通过业务逻辑去缓存内容,比如缓存一个用户的数据,是通过uid为维度的缓存,和SQL没有任何关系。这样可以带来好处 1. 缓存变得好管理,一个uid就一个缓存数据 2. 命中率增高,因为参数变成了一个uid 3. 可以很容易的知道用户缓存的key 所在这这种缓存的模型里面,维护将变得更加便捷,下面这个例子和上面的例子有点差别 ``` <?php $id = $_GET['uid']; $key = 'USER:UID:'.$id;//一般会加缓存前缀 $mc = new Memcached(); $mc->addServer("localhost", 11211); $row = $mc->get($key); if($row){ return $row; } //继续走数据库逻辑,并将数据写入mc $row->set($key, $row); ``` #memcached服务集群 ##为什么要使用集群 在一些简单的网站中,如果仅仅是为了加速网站,那单台memcached服务挂了问题也不大。但是,如果网站的访问量特别大,当memcached服挂掉了,大量的读操作直接奔向DB,那数据库肯定会奔溃掉。在稍微稳定的网站中,是绝对不允许单点故障的。所以,如果需要构建一个稳定的缓存服务,必须 1. 避免单点故障,服务要始终是可用的 2. 提升缓存服务的响应速度 ##需要一个代理 在一个大型的memcached服务集群中,少则几个memcached服务的IP地址,多则几十个memcached服务的IP地址。假如一共有20台机器提供memcached服务,加入一台服务挂了怎么办,加入需要换掉其中的10台服务怎么办,假如需要做到自动摘除挂掉的服务怎办。很显然,让应用层去处理这些情况很不实际,所以我们需要一个中间层,来自twitter的工程师为我们解决了这个问题。他们开发了代理memcached的twemproxy,目前我们团队正在使用的nutcraker ##nutcraker的安装使用 ###下载安装 下载地址:https://twemproxy.googlecode.com/files/nutcracker-0.3.0.tar.gz。解压之后,运行安装命令 ``` cd nutcracker-0.3.0/ ./configure make && make install ``` ###配置nutcracker 配置文件在conf/nutcracker.yml ``` beta: listen: 127.0.0.1:22122 #nutcraker代理监听的端口 hash: fnv1a_64 #hase算法 hash_tag: "{}" distribution: ketama auto_eject_hosts: false #是否在节点无法响应的时候临时找出,区分save data的slave和cache data的slave timeout: 400 #超时 servers: #配置真正的mc存储 - 127.0.0.1:6380:1 server1 - 127.0.0.1:6381:1 server2 - 127.0.0.1:6382:1 server3 - 127.0.0.1:6383:1 server4 ``` 这个配置表示127.0.0.1:22122这个端口的nutcraker服务代理了servers的4台正真的memcache存储,这个4台memcached服务分别为 - 127.0.0.1:6380:1 - 127.0.0.1:6381:1 - 127.0.0.1:6382:1 - 127.0.0.1:6383:1 也就是说在应用层,只有`127.0.0.1:22122`这个接口暴露给我们去使用memcached服务了,我们不关系这个服务下操纵了多少台正真的memcached服务 ###启动nutcraker服务 采用daemon的方式运行,如果你是用memcache测试的话,注意将配置文件中的`redis:true注释掉` ``` #启动 localhost:memcached-1.4.23 MLS$ src/nutcracker -d #查看 localhost:memcached-1.4.23 MLS$ ps -ef | grep nutcracker 501 17738 1 0 2:26下午 ?? 0:00.01 src/nutcracker -d 501 19559 580 0 2:54下午 ttys002 0:00.00 grep nutcracker ``` ###启动4台真正的memcached服务 如果只启动nutcracker服务是没有用的,它只是一个代理,西部要把nutcracker代理的正真的memcached服务起来,才能正常工作运转,其中方法如下 ``` #启动4台memcache服务 localhost:memcached-1.4.23 MLS$ ./memcached -d -p 6380;./memcached -d -p 6381;./memcached -d -p 6382;./memcached -d -p 6383 #查看 localhost:memcached-1.4.23 MLS$ ps -ef | grep memcached 501 17541 1 0 2:23下午 ?? 0:00.03 ./memcached -d -p 6380 501 17580 1 0 2:24下午 ?? 0:00.03 ./memcached -d -p 6381 501 17585 1 0 2:24下午 ?? 0:00.03 ./memcached -d -p 6382 501 17587 1 0 2:24下午 ?? 0:00.03 ./memcached -d -p 6383 ``` ###测试nutcraker服务 连接nutcraker服务并且向nutcraker服务代理写一个数据 ``` localhost:nutcracker-0.3.0 MLS$ telnet 127.0.0.1 22122 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. set key1 0 0 5 hello STORED ``` 存储是分布式的,并不是每一台真正的memcached服务上都有数据,而是命中其中的一台,然后将数据缓存起来,通过去每台memcached服务查看数据可以看到 ``` #6380端口 localhost:memcached-1.4.23 MLS$ telnet 127.0.0.1 6380 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. get key1 VALUE key1 0 5 hello END #6381端口 localhost:memcached-1.4.23 MLS$ telnet 127.0.0.1 6381 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. get key1 END #6382端口 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. get key1 END #6383端口 localhost:memcached-1.4.23 MLS$ telnet 127.0.0.1 6383 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. get key1 END ```
Pre:
PHP匿名函数,闭包
Next:
PHP自动加载
1
likes
374
Weibo
Wechat
Tencent Weibo
QQ Zone
RenRen
Submit
Sign in
to leave a comment.
No Leanote account?
Sign up now.
0
comments
More...
Table of content
No Leanote account? Sign up now.