赞
踩
Memcached是一个开源、高性能、分布式内存对象缓存系统。
Memcached是一种基于内存的key-value存储,用来存储小块的任意数据(字符串、对象),这些数据可以是数据库调用、API调用或者是页面渲染的结果。
Memcached解决了大数据量缓存的很多问题,它的API兼容大部分流行的开发语言,本质上,它是一个简洁key-value存储系统,它是非关系型数据库。
Memcached通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、提高可扩展性。
(1)memcached特性
Memcached使用了BSD许可的服务端缓存实现:相较于普通服务端缓存实现中各个缓存都运行在服务实例之上的情况,Memcached服务实例是在服务实例之外独立运行
普通缓存 | Memcached缓存 | |
---|---|---|
特性 | 缓存与特定的应用实例绑定,每个应用实例只能访问特定的缓存 | 实例独立于各个应用服务器实例运行,每个应用实例可以访问任意缓存 |
特点 | 整个应用所能访问的缓存容量变小;缓存中存在数据冗余;缓存系统整体效率降低。 | 整个应用所能访问的缓存容量变大;缓存中无数据冗余;缓存系统整体效率较高。 |
(2)缓存服务器结构的组织
(3)数据的存取过程
由于数据的异构性,我们需要在访问Memcached所记录的信息之前决定在该服务端缓存系统中到底由哪个Memcached实例记录了我们所想要访问的数据
客户端对缓存信息的访问
该客户端知道服务端缓存系统中所包含的所有Memcached服务实例
访问具有特定键值foo的数据——>根据Memcached缓存服务配置计算出用户所需要访问的信息所在的Memcached实例——>从配置中读取该Memcached服务实例所在地址——>向该Memcached实例发送数据访问请求——>从该Memcached实例中读取具有键值“foo”的信息
客户端对缓存信息的存入
缓存记录数据“bar”——>为其指定键值“foo”——>对键值“foo”计算决定存储该数据的Memcached服务实例——客户端向该实例发送请求:记录具有键值“foo”的数据“bar”
每个memcached实例都是独立的,彼此间没有交互
单个节点上不存进程间通信通信
节点之间不存在数据同步以及消息广播
便于节点的扩缩容
这些记录在服务端缓存中的数据是全局可见的,即一旦在Memcached服务端缓存中成功添加了一条新的记录,那么其它使用该缓存服务的应用实例将同样可以访问该记录
(4)记录的组成及内容特性
在Memcached中,每条记录都由四部分组成:记录的键,有效期,一系列可选的标记以及表示记录内容的数据。由于记录内容的数据中并不包含任何数据结构,因此我们在Memcached中所记录的数据需要是经过序列化之后的表示。
对缓存数据的生存期进行管理包括如何使一个记录在缓存中的数据过期, 如何在缓存空间不够时执行数据的替换等。
(1)内存管理模型
内存管理算法:内存的碎片化
在长时间地分配及回收之后,被系统所使用的内存将趋向于散落在不连续的空间中。这使得系统很难找到连续内存空间,一方面增大了内存分配失败的概率,另一方面也使得内存分配工作变得更为复杂,降低了运行效率。
Memcached的Slab结构
在该分配算法中,内存将按照1MB的大小划分为页,而该页内存则会继续被分割为一系列具有相同大小的内存块。
优点:
降低由于记录的多次读写而导致的碎片化;
通过Memcached的配置文件来指定各个块的大小,从而尽可能地减少内存的浪费。
注意:由于默认情况下Memcached中每页的大小为1MB,因此其单个块最大为1MB;除此之外,Memcached还限制每个数据所对应的键的长度不能超过250个字节
(2)内存调优
一般来说,Slab中各个块的大小以及块大小的递增倍数(如1.25倍)可能会对记录所在位置的选择及内存利用率有很大的影响。
若数据在通常情况下都比较小,就将最小块的大小调整得小一些;若数据的大小变动不是很大,则将块大小的递增倍数设置得小一些。
组成缓存系统中各个服务器的差异性使具有较大内存的Memcached实例将无法被充分利用,可以通过在具有较大内存的服务器上部署多个Memcached实例来解决这个问题。
(3)内存清理机制
LRU算法:Least recently used,它的主要衡量指标是使用的时间,附加指标是使用的次数。
Memcached过期算法:延迟过期(Lazy expiration)
当用户从Memcached实例中读取数据的时候,其将首先通过配置中所设置的过期时间来决定该数据是否过期。如果是,那么在下一次写入数据却没有足够空间的时候,Memcached会选择该过期数据所在的内存块作为新数据的目标地址。如果在写入时没有相应的记录被标记为过期,那么LRU算法才被执行,从而找到最久没有被使用的需要被替换的数据(这里的LRU是在Slab范围内的,而不是全局的)。
由于Memcached实例的个数变化会导致哈希计算的结果发生变化,从而导致所
有对数据的请求会导向到不正确的Memcached实例,使得由Memcached实例集群所提供的缓存服务全部失效,从而导致数据库的压力骤增。
Memcached所使用的解决方法就是Consistent Hashing (一致性Hash) 。在该算法的帮助下,Memcached实例数量的变化将只可能导致其中的一小部分键的哈希值发生改变。
一致性哈希原理 https://www.jianshu.com/p/735a3d4789fc
(1)内存要求高,所存储的内容非持久化
(2)集中式Cache:开辟分布式Cache的传播问题,但是需要非单点保证其可靠性,需要cluster的工作
(3)分布式扩展:部署在一台或多台服务器上的多个Memcached服务端组成一个虚拟的服务端,对于调运者来说完全透明,进而提高单机的内存利用率
(4)特殊的内存分配机制:支持最大的存储对象为1M,简单的分配机制可以更容易的回收再分配,节省cpu开销
(5)Cache机制简单:不存在同步,消息分发,两节段提交等
(6)客户端的重要性:给使用者提供很大的空间去扩展和设计客户端来满足各种场景的需要
购物网站商品类别、官网版权信息等不经常改变的内容实时性不高,应该放到缓存中
memcached工作过程
当首次访问时,数据正常地从数据库或其他数据源加载,然后存储到memcached内;再次访问此信息,从memcached中取出,节省时间和CPU循环
更新memcached中数据的过程:
更新数据库中分类的信息------->找到memcached中key值,删除------>重新插入到memcached中
memcached内的存储操作具有原子性,所以信息的更新不会让客户机只获得部分数据;它们获得的或者是老版本,或者是新版本
需求背景:网站有一个图片放映功能,页面加载时需从数据库中查询管理员所提交放映的图片信息,图片放映区共有9张图片,对应在数据库表中有9条记录。每次用户访问网站时,需查询数据库,并显示图片。当承受大规模用户同时访问时,数据库的压力可想而之。
为了降低数据库压力,提高查询速度,采用Memcache来将图片记录信息缓存到Memcache服务器上,将数据库的查询压力分散到了各缓存服务器,提高了网站访问的整体效率。
IP地址 | 角色 |
---|---|
192.168.213.131 | web(带mysql8) |
192.168.213.124 | mysql |
192.168.213.122 | memcached |
关闭防火墙
同步时间
卸载mariadb-libs和postfix
安装软件httpd和php模块,重启服务
[root@web ~]# yum install httpd php php-gb php-mysql php-memcache
[root@web ~]# systemctl restart httpd
[root@web ~]# systemctl restart mysqld
在mysql上创建用户
[root@mysql ~]#mysql -p
mysql> create user 'memcache'@'%' identified by 'Zhao123@com';
mysql> ALTER USER 'memcache'@'%' IDENTIFIED WITH mysql_native_password BY
'Cloudbu@123';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'memcache'@'%' WITH GRANT OPTION;
mysql> flush privileges;
测试httpd功能,php链接功能,和mysql
[root@mysql ~]#vim /var/www/html/index.php
<?php
phpinfo();
?>
[root@mysql ~]#vim /var/www/html/mysql.php
<?php
$link=mysql_connect('192.168.213.124','memcache','Zhao123@com');
if($link) echo "<h1>Success!!</h1>";
else echo "Fail!!";
mysql_close();
?>
(1)安装libevent和memcached
[root@memcached ~]# yum install make gcc gcc-c++ -y
[root@memcached ~]# wget http://monkey.org/~provos/libevent-1.4.14b-stable.tar.gz
[root@memcached ~]# wget https://memcached.org/files/memcached-1.5.16.tar.gz
[root@memcached ~]# tar -xf memcached-1.5.16.tar.gz -C /usr/local/src
[root@memcached ~]# tar -xf libevent-1.4.14b-stable.tar.gz -C /usr/local/src
[root@memcached ~]# mkdir /usr/local/memcached
[root@memcached ~]# mkdir /usr/local/libevent
[root@memcached ~]# cd /usr/local/src/libevent-1.4.14b-stable
[root@memcached libevent-1.4.14b-stable]# ./configure -prefix=/usr/local/libevent
[root@memcached libevent-1.4.14b-stable]# make
[root@memcached libevent-1.4.14b-stable]# make install
[root@memcached ~]# cd /usr/local/src/memcached-1.5.16
[root@memcached memcached-1.5.16]# ./configure --with-libevent=/usr/local/libevent/ --prefix=/usr/local/memcached
[root@memcached memcached-1.5.16]# make
[root@memcached memcached-1.5.16]# make install
(2)测试web和memcached的连通性
启用memcached并监听所有地址
[root@memcached ~]# /usr/local/memcached/bin/memcached -d -l 0.0.0.0 -p 11211 -u root -m 64 -c 1024 -P /var/run/memcached.pid
[root@memcached ~]# ps -ef|grep memcache
root 8137 1 0 20:10 ? 00:00:00 /usr/local/memcached/bin/memcached -d -l 0.0.0.0 -p 11211 -u root -m 64 -c 1024 -P /var/run/memcached.pid
root 8148 7992 0 20:10 pts/1 00:00:00 grep --color=auto memcache
启动参数说明:
-d 选项是启动一个守护进程,
-l 是监听的服务器IP地址,默认为所有网卡,
-p 是设置Memcache的TCP监听的端口,最好是1024以上的端口,
-u 是运行Memcache的用户,如果当前为root 的话,需要使用此参数指定用户,
-m 是分配给Memcache使用的内存数量,单位是MB,默认64MB,
-c 选项是最大运行的并发连接数,默认是1024,
-P 是设置保存Memcache的pid文件,
-M return error on memory exhausted (rather than removing items),
-f chunk size growth factor (default: 1.25),
-I Override the size of each slab page. Adjusts max item size(1.4.2版本新增),也可以启动多个守护进程,但是端口不能重复
代码测试
[root@web ~]# vim /var/www/html/memcache.php
<?php
$memcache = new Memcache;
$memcache->connect('192.168.213.122', 11211) or die ("Could not connect");
$version = $memcache->getVersion();
echo "Server's version: ".$version."<br/>";
$tmp_object = new stdClass;
$tmp_object->str_attr = 'test';
$tmp_object->int_attr = 123;
$memcache->set('key', $tmp_object, false, 10) or die ("Failed to save data at the server");
echo "Store data in the cache (data will expire in 10 seconds)<br/>";
$get_result = $memcache->get('key');
echo "Data from the cache:<br/>";
var_dump($get_result);
?>
测试结果
(3)配置session
vim /etc/php.ini
session.save_handler = memcache #设置session的储存方式为memcache
session.save_path = "tcp://192.168.213.131:11211?persistent=1&weight=1&timeout=1&retry_interval=15" #设置session储存的位置,多台memcache用逗号隔开
memcache实现session共享也可以在某个一个应用中设置:
ini_set(“session.save_handler”, “memcache”);
ini_set(“session.save_path”, “[tcp://192.168.0.9](http://192.168.0.9/):11211”);
测试memcache的可用性
[root@web ~]# vim /var/www/html/memcache1.php
<?php
session_start();
if (!isset($_SESSION['session_time']))
{
$_SESSION['session_time'] = time();
}
echo "session_time:".$_SESSION['session_time']."<br />";
echo "now_time:".time()."<br />";
echo "session_id:".session_id()."<br />";
?>
在数据库节点上创建测试数据库
[root@mysql ~]# mysql -uroot -pZhao123@com mysql> create database testab1; mysql> use testab1; mysql> create table test1( id int not null auto_increment, name varchar(20) default null, primary key(id)) engine=innodb auto_increment=1 default charset=utf8; mysql> insert into test1(name) values ('tom1'),('tom2'),('tom3'),('tom4'),('tom5'); mysql> select * from test1; +----+------+ | id | name | +----+------+ | 1 | tom1 | | 2 | tom2 | | 3 | tom3 | | 4 | tom4 | | 5 | tom5 | +----+------+ mysql> grant select on testab1.* to memcache@'%';
测试memcache是否缓存数据库成功
<?php $memcachehost = '192.168.213.122'; $memcacheport = 11211; $memcachelife = 60; $memcache = new Memcache; $memcache->connect($memcachehost,$memcacheport) or die ("Could not connect"); $query="select * from test1 limit 10"; $key=md5($query); if(!$memcache->get($key)) { $conn=mysql_connect("192.168.213.124","memcache","Zhao123@com"); mysql_select_db(testab1); $result=mysql_query($query); while ($row=mysql_fetch_assoc($result)) { $arr[]=$row; } $f = 'mysql'; $memcache->add($key,serialize($arr),0,30); $data = $arr ; } else{ $f = 'memcache'; $data_mem=$memcache->get($key); $data = unserialize($data_mem); } echo $f; echo "<br>"; echo "$key"; echo "<br>"; //print_r($data); foreach($data as $a) { echo "number is <b><font color=#FF0000>$a[id]</font></b>"; echo "<br>"; echo "name is <b><font color=#FF0000>$a[name]</font></b>"; echo "<br>"; } ?>
如果出现mysql表示memcached中没有内容,需要memcached从数据库中取得
再刷新页面,如果有memcache标志表示这次的数据是从memcached中取得的
memcached有个缓存时间默认是1分钟,过了一分钟后,memcached需要重新从数据库中取得数据
MemAdmin是一款可视化的Memcached管理与监控工具,使用PHP开发,体积小,操作简单
主要功能:
服务器参数监控:STATS、SETTINGS、ITEMS、SLABS、SIZES实时刷新
服务器性能监控:GET、DELETE、INCR、DECR、CAS等常用操作命中率实时监控
支持数据遍历,方便对存储内容进行监视
支持条件查询,筛选出满足条件的KEY或VALUE
数组、JSON等序列化字符反序列显示
兼容memcache协议的其他服务,如Tokyo Tyrant (遍历功能除外)
支持服务器连接池,多服务器管理切换方便简洁
安装方法:
(1)搭建LAMP环境
(2)在php.ini配置文件里面追加如下,让php支持memcached
extension = memcached.so
(3)安装配置MemAdmin
[root@web ~]# wget http://www.junopen.com/memadmin/memadmin-1.0.12.tar.gz
[root@web ~]# tar xf memadmin-1.0.12.tar.gz -C /var/www/html
[root@web ~]# head -n 5 /var/www/html/memadmin/config.php #设置管理帐号和密码
<?php
if (!defined('IN_MADM')) exit();
$config['user'] = "admin"; // your username
$config['passwd'] = "admin"; // your password
通过浏览器,访问memadmin目录
http://192.168.213.131/memadmin/index.php
只要支持php环境就能用,把这个文件放到你的网页存放目录下就可以了访问方法http://ip/memcache.php
[root@web ~]# wget http://pecl.php.net/get/memcache-2.2.7.tgz
[root@web ~]# tar -xf memcache-2.2.7.tgz -C /var/www/html/
[root@web ~]# vim /var/www/html/memcache-2.2.7/memcache.php
.....
define('ADMIN_USERNAME','memcache');
define('ADMIN_PASSWORD','password');
.....
$MEMCACHE_SERVERS[] = '192.168.213.122:11211'; #ip
#$MEMCACHE_SERVERS[] = 'mymemcache-server2:11212';
http://192.168.213.131/memcache-2.2.7/memcache.php
[root@memcached ~]# telnet localhost 11211
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
stats
STAT pid 1267
STAT uptime 2717
……
STAT direct_reclaims 0
STAT lru_bumps_dropped 0
END
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。