这里写目录标题
一、我们来了解一下MemCached与MemCache之间的区别:
1.1 Memcache是什么?
-
Memcache是一个自由和开放源代码、高性能、分配的内存对象缓存系统。用于加速动态web应用程序,减轻数据库负载。
-
它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这 些HashTable。
1.2 Memcached又是什么?
-
Memcached是Memcache系统的主程序文件,以守护程序方式运行于一个或多个服务器中,随时接受客 户端的连接操作,使用共享内存存取数据。
-
那PHP中的Memcache是什么?php中的所讲的memcache是用于连接Memecached的php支持扩展之一(可用phpinfo查看),类似mbstring,eAccelerator。
二 、概述
Memcache是总的缓存系统项目名称,容易和PHP中的Memcache混淆。
我们常提到Memcache其实是PHP中的Memcache,即PHP的Memcached扩展支持。
我们常提到Memcached是服务端主程序文件,服务端安装程序。
为了让你的程序飞起来,必须安装memcached服务端程序和PHP的Memcached扩展,所以如果您要使用Memcache来缓存系统,memcache和memcached两样我们都需要安装。
2.1 、接下来,我们来了解一下Memcached有关的知识点:
Memcached是danga.com(运营LiveJournal的技术团队)开发的一套分布式内存对象缓存系统,用于在动态系统中减少数据库 负载,提升性能。
2.2 、它所具有的特点有:
-
协议简单
-
基于libevent的事件处理
-
内置内存存储方式
-
memcached不互相通信的分布式
-
Memcached处理的原子是每一个(key,value)对(以下简称kv对),key会通过一个hash算法转化成hash-key,便于查找、对比以及做到尽可能的散列。同时,memcached用的是一个二级散列,通过一张大hash表来维护。
-
Memcached有两个核心组件组成:服务端(ms)和客户端(mc),在一个memcached的查询中,mc先通过计算key的hash值来 确定kv对所处在的ms位置。当ms确定后,客户端就会发送一个查询请求给对应的ms,让它来查找确切的数据。因为这之间没有交互以及多播协议,所以 memcached交互带给网络的影响是最小化的。
2.3 、内存分配
默认情况下,ms是用一个内置的叫“块分配器”的组件来分配内存的。舍弃c++标准的malloc/free的内存分配,而采用块分配器的主要目的 是为了避免内存碎片,否则操作系统要花费更多时间来查找这些逻辑上连续的内存块(实际上是断开的)。用了块分配器,ms会轮流的对内存进行大块的分配,并 不断重用。当然由于块的大小各不相同,当数据大小和块大小不太相符的情况下,还是有可能导致内存的浪费。
同时,ms对key和data都有相应的限制,key的长度不能超过250字节,data也不能超过块大小的限制 — 1MB。
因为mc所使用的hash算法,并不会考虑到每个ms的内存大小。理论上mc会分配概率上等量的kv对给每个ms,这样如果每个ms的内存都不太一样,那 可能会导致内存使用率的降低。所以一种替代的解决方案是,根据每个ms的内存大小,找出他们的最大公约数,然后在每个ms上开n个容量=最大公约数的 instance,这样就等于拥有了多个容量大小一样的子ms,从而提供整体的内存使用率。
2.4 、 缓存策略
当ms的hash表满了之后,新的插入数据会替代老的数据,更新的策略是LRU(最近最少使用),以及每个kv对的有效时限。Kv对存储有效时限是在mc端由app设置并作为参数传给ms的。
同时ms采用是偷懒替代法,ms不会开额外的进程来实时监测过时的kv对并删除,而是当且仅当,新来一个插入的数据,而此时又没有多余的空间放了,才会进行清除动作。
2.5 、缓存数据库查询
现在memcached最流行的一种使用方式是缓存数据库查询,下面举一个简单例子说明:
App需要得到userid=xxx的用户信息,对应的查询语句类似:
“SELECT * FROM users WHERE userid = xxx”
App先去问cache,有没有“user:userid”(key定义可预先定义约束好)的数据,如果有,返回数据;如果没有,App会从数据库中读取数据,并调用cache的add函数,把数据加入cache中。
当取的数据需要更新,app会调用cache的update函数,来保持数据库与cache的数据同步。
从上面的例子我们也可以发现,一旦数据库的数据发现变化,我们一定要及时更新cache中的数据,来保证app读到的是同步的正确数据。当然我们可 以通过定时器方式记录下cache中数据的失效时间,时间一过就会激发事件对cache进行更新,但这之间总会有时间上的延迟,导致app可能从 cache读到脏数据,这也被称为狗洞问题。(以后我会专门描述研究这个问题)
2.6 、数据冗余与故障预防
从设计角度上,memcached是没有数据冗余环节的,它本身就是一个大规模的高性能cache层,加入数据冗余所能带来的只有设计的复杂性和提高系统的开支。
当一个ms上丢失了数据之后,app还是可以从数据库中取得数据。不过更谨慎的做法是在某些ms不能正常工作时,提供额外的ms来支持cache,这样就不会因为app从cache中取不到数据而一下子给数据库带来过大的负载。
同时为了减少某台ms故障所带来的影响,可以使用“热备份”方案,就是用一台新的ms来取代有问题的ms,当然新的ms还是要用原来ms的IP地址,大不了数据重新装载一遍。
另外一种方式,就是提高你ms的节点数,然后mc会实时侦查每个节点的状态,如果发现某个节点长时间没有响应,就会从mc的可用server列表里 删除,并对server节点进行重新hash定位。当然这样也会造成的问题是,原本key存储在B上,变成存储在C上了。所以此方案本身也有其弱点,最好 能和“热备份”方案结合使用,就可以使故障造成的影响最小化。
2.7 、Memcached客户端(mc)
Memcached客户端有各种语言的版本供大家使用,包括java,c,php,.net等等,具体可参见memcached api page [2]。
大家可以根据自己项目的需要,选择合适的客户端来集成。
缓存式的WEB应用程序架构
有了缓存的支持,我们可以在传统的app层和db层之间加入cache层,每个app服务器都可以绑定一个mc,每次数据的读取都可以从ms中取得,如果 没有,再从db层读取。而当数据要进行更新时,除了要发送update的sql给db层,同时也要将更新的数据发给mc,让mc去更新ms中的数据。
性能测试
Memcached 写速度
平均速度: 16222 次/秒
最大速度 18799 次/秒
Memcached 读速度
平均速度: 20971 次/秒
最大速度 22497 次/秒
Memcachedb 写速度
平均速度: 8958 次/秒
最大速度 10480 次/秒
Memcachedb 读速度
平均速度: 6871 次/秒
最大速度 12542 次/秒
三 、服务搭建
3.1 、 实验环境:首先准备俩台服务器,一台是客户端,一台是服务端
- 服务端ip地址是:20.0.0.32
- 客户端的ip地址是:20.0.0.33
3.2 、首先我们搭建服务端
[root@node abc]# tar zxvf libevent-2.1.8-stable.tar.gz -C /opt
[root@node abc]# tar zxvf memcached-1.5.6.tar.gz -C /opt
[root@node abc]# cd /opt
root@node opt]# yum install gcc gcc-c++ make 安装底层环境和编译工具
[root@node opt]# cd /opt/libevent-2.1.8-stable/
[root@node libevent-2.1.8-stable]# ./configure --prefix=/usr/local/libevent 一定要先安装通知事件库,因为内存数据库是依赖于事件库
[root@node libevent-2.1.8-stable]# make && make install
[root@node libevent-2.1.8-stable]# cd /opt/memcached-1.5.6/ 切到该扩展目录下
[root@node memcached-1.5.6]# ./configure
–prefix=/usr/local/memcached \ 指定安装路径
–with-libevent=/usr/local/libevent/
3.3 、安装好之后我们要让memcached的一些命令能让系统识别
[root@node1 memcached-1.5.6]# ln -s /usr/local/memcached/bin/* /usr/local/bin
3.4 、用memcached去指定守护进程、缓存数据的大小,指定端口及指定哪个用户对其进行管理
[root@node1 memcached-1.5.6]#memcached -d -m 32m -p 11211 -u root
[root@node1 memcached-1.5.6]# netstat -anpt |grep 11211
tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 14664/memcached
tcp6 0 0 :::11211 ::😗 LISTEN 14664/memcached
[root@node1 memcached-1.5.6]# telnet 127.0.0.1 11211 远程连接数据库,显示没有该命令
bash: telnet: 未找到命令…
[root@node1 memcached-1.5.6]# yum -y install telnet
[root@node1 memcached-1.5.6]# telnet 127.0.0.1 11211 再去连接就进去了
Trying 127.0.0.1…
Connected to 127.0.0.1.
Escape character is '^]
[root@node1 memcached-1.5.6]#add username 0 0 7
1234567
gets yang 或者 get yang 都可以查询之前输入的字节长度
VALUE yang 0 7 4
1234567
END
注释:username键值名称,第一个0,代笔不设置她的序列号,第二个0表示无时间要求,也就是说不设置的失效时间,后面的7代表你即将要输入的字节长度
set yang 0 0 8
用set可以更新已有的键值,同时还有另一层意思,如果没有该键值,它还有添加的意思;同时replace也是更新的意思,但是针对以存在的键值,这是二者的区别
set clour 0 0 3 这边创建一个没有的键值对
123
STORED
gets clour 获取里面的数据也是查询到的
VALUE clour 0 3 7
123
END
gets yang
VALUE yang 0 7 4 这后面的4是更新因子,每操作过一次更新,后面的更新因子会自增加1
1234567
END
cas 检查更新,更新因子必须与之前的更新因子一致,才能操作
gets yang 现在看到更新因子是7
VALUE yang 0 3 7
123
END
cas yang 0 0 5 7
login
STORED
gets yang
VALUE yang 0 5 8
login
END
append 在键值后追加
例如:gets yang
VALUE yang 0 5 8
login
END
append yang 0 0 4 设置一个四位的字符
book 输入一个值
STORED
get yang 获取里面的数据
VALUE yang 0 9
loginbook 会发现输入的数据已经添加到数值之后了
END
prepend 在键值前追加数据
append yang 0 0 7
example
STORED
delete yang 删除数据
flush yang 清除所有缓存数据
squit 是推出数据库
stats 显示状态信息
然后登录客户端安装lamp架构:可以点这个网址超级详细的流程和解释
搭建好之后解压文件包
[root@node2 opt]# tar xf memcache-2.2.7.tgz
[root@node2 opt]# cd memcache-2.2.7/
[root@node2 memcache-2.2.7]# ls 我们查看该扩展目录下没有configure的脚本文件
[root@node2 memcache-2.2.7]# /usr/local/php5/bin/phpiz 增加为PHP的模块后在对memcache进行配置
[root@node2 memcache-2.2.7]#ls 这时再去查看就有configure的启动脚本文件了
[root@node2 memcache-2.2.7]# ./configure \
--enable-memcache \ 启动memcache
--with-php-config=/usr/local/php5/bin/php-config 使用php5中bin目录下的一个php-config文件开启它的客户端
[root@node2 memcache-2.2.7]# make && make install
[root@node2 memcache-2.2.7]# /usr/local/php5/lib/php/extensions/no-debug-zts-20131226/ 然后我们看下有没有这条路径,如果有记录下来
[root@node2 memcache-2.2.7]# vim /usr/local/php5/php.ini
添加
extension_dir="/usr/local/php5/lib/php/extensions/no-debug-zts-20131226/" 指定目录的位置
extension=memcache.so 指定memcache的模块
注释:这边memcache就是提供了一个客户端的API服务接口,然后是由PHP去负责连接的数据库的,所有我们是需要php上生成一个API,去连接我们的缓存对象站点,然后再去连接数据库
[root@node2 memcache-2.2.7]# cd /usr/local/httpd/htdocs/
[root@node2 htdocs]# vim index.php 在这里写一个脚本,用客户端去连接服务器,如果里连接成功返回Successfull
"index.php" 0,0-1
<?php
$mencache = new Memcache();
$mencaceh->connect('20.0.0.32',11211);
$mencaceh->set('key','Memcache test Successfull !'0,60);
$result = $memcache->get('key');
unset($memcache);
echo $result;
?
然后用客户端主机访问测试