欢迎您的光临,本博所发布之文章皆为作者亲测通过,如有错误,欢迎通过各种方式指正。

教程  php进阶(四)--memcache技术应用详解(下)

PHP学习 本站 986 0评论

四、Memcache和mysql交互流程操作原理说明


1.首先明确是不是一定要上缓存,当前架构的瓶颈在哪里,若瓶颈真是数据库操作上,再继续往下看。

2.明确memcached和redis的区别,到底要使用哪个。前者终究是个缓存,不可能永久保存数据(LRU机制),支持分布式,后者除了缓存的同时也支持把数据持久化到磁盘等,redis要自己去实现分布式缓存(貌似最新版本的已集成),自己去实现一致性hash。因为不知道你们的应用场景,不好说一定要用memcache还是redis,说不定用mongodb会更好,比如在存储日志方面。

3.缓存量大但又不常变化的数据,比如评论。

4.你的思路是对的,清晰明了,读DB前,先读缓存,如果有直接返回,如果没有再读DB,然后写入缓存层并返回。

5.考虑是否需要主从,读写分离,考虑是否分布式部署,考虑是否后续水平伸缩。

6.想要一劳永逸,后续维护和扩展方便,那就将现有的代码架构优化,按你说的替换数据库组件需要改动大量代码,说明当前架构存在问题。可以利用现有的一些框架,比如SpringMVC,将你的应用层和业务层和数据库层解耦。再上缓存之前把这些做好。

7.把读取缓存等操作做成服务组件,对业务层提供服务,业务层对应用层提供服务。

8.保留原始数据库组件,优化成服务组件,方便后续业务层灵活调用缓存或者是数据库。

9.不建议一次性全量上缓存,最开始不动核心业务,可以将边缘业务先换成缓存组件,一步步换至核心业务。

10.刷新内存,以memcached为例,新增,修改和删除操作,一般采用lazy load的策略,即新增时只写入数据库,并不会马上更新Memcached,而是等到再次读取时才会加载到Memcached中,修改和删除操作也是更新 数据库,然后将Memcached中的数据标记为失效,等待下次读取时再加载。


对于大型网站如facebook,ebay等网站,如果没有Memcache做为中间缓存层,数据访问不可能吃得消,对于一般网站,只要具备独立的服务器,完全可以通过配置Memcache提高网站访问速度和减少数据库压力,这里主要讨论一下Memcache和MySQL数据库交互过程的流程关系,了解Memcache的中间缓存层作用,从而深入了解Memcache机制原理。


Memcache和MySQL交互流程图

555.jpg

如上图,传统的查询方法是直接查询数据库,数据库将结果返回给查询语句,而当有Memcache中间缓存层时,查询的是Memcache缓存数据,下面详细了解Memcache各类数据操作原理:

1,查询数据(select),首先通过指定的Key查询(get)Memcache中间缓存层数据,如果存在相对应数据,则直接获取出数据结果,查询过程完全不需要查询数据库。如果不存在,则查询MySQL数据库,并以key对应value的形式将查询结果存储在Memcache缓存数据中,然后将结果返回给查询语句。

2,更新数据(update),首先更新数据,然后删除相关的memcache数据(delete)。

3,增加数据(add),首先删除相关缓存数据,然后增加数据。

4,删除数据(delete),删除数据,并删除Memcache数据。


对MySQL的数据操作,主要涉及到的Memcache方法如下:

1,获取:get(key)

2,设置:set(key, value [, expiry])

3,删除:delete(key [, time])


实例:

假设一个贴子,获取贴子ID为2009的值,其Memcache与MySQL交互流程如下:

$key = 'biuuu_thread_';//key前缀

$cachetime = 100;//缓存有效时间(秒)

$id = 2009;


Memcache基本操作过程:

1,查询:$result = get($key.$id);如果$result为空,则查询MySQL数据库,然后set($key.$id,$value,0,$cachetime)

2,更新:delete($key.$id);

3,增加:delete($key.$id);

4,删除:delete($key.$id);


666.jpg

通过直观图和实例应该对Memcache与MySQL的交互有一个基础的掌握,其实对于应用来说,基本上就已经足够,但如果要涉及到命名空间等相对复杂的情况,Memcache的操作方式会有所不同,但不管什么样的操作,还是离不开基础操作命令,由于这是Memcache基础篇,主要是讨论Memcache和mysql交互操作流程,当Memcache原理清楚以后,Memcache基本操作就是这么简单。


Memcache的管理与性能监控:

可以通过命令行直接管理与监控也可通过nagios,cacti等web软件进行监控

命令行:

Shell>telnet 127.0.0.1 1211 //如果在启动时指定了IP及端口号,这里要作相应改动

连接成功后命令 

Stats:统计memcached的各种信息 

Stats reset:重新统计数据 

Stats slabs:显示slabs信息,可以详细看到数据的分段存储情况 

Stats items:显示slab中的item数目 

Stats cachedump 10:列出slabs第一段里存的KEY值 

Set|get:保存或获取数据 

STAT evictions 0:表示要腾出新空间给新的item而移动的合法item数目 

其它常用软件使用:

Shell>./Memcached-tool 127.0.0.1:11211 

Shell>./Memcached-tool 127.0.0.1:11211 display 

Web软件:

Memcache.php 

Nagios插件 

Cacti模块


五、Memcache协议分析


如果你不喜欢 php_memcache.dll 扩展或者服务器目前不支持这个扩展,那么就可以考虑自己构建.

Memcahe的客户端,要先了解Memcache协议的交互,这样才能开发自己的客户端,这里简单的分析一下Memcache的协议。(更详细的协议内容请在Memcache服务器端的源码的 doc/protocol.txt文件中)


Memcache既支持TCP协议,也支持UDP协议,不过我们这里是以TCP协议的协议作为主要考虑对象,想了解UDP协议的过程,请参考 doc/protocol.txt文件。


1.[ 错误指令]

Memcache的协议的错误部分主要是三个错误提示指令:

· 普通错误信息,比如指令错误之类的

ERROR

· 客户端错误

CLIENT_ERROR <错误信息>

· 服务器端错误

SERVER_ERROR <错误信息>


2.[ 数据保存指令]

数据保存是基本的功能,就是客户端通过命令把数据返回过来,服务器端接收后进行处理。指令格式:

<命令> <键> <标记> <有效期> <数据长度>

<命令> - command name

主要是三个储存数据的三个命令, set, add, replace

· set 命令是保存一个叫做key的数据到服务器上

· add 命令是添加一个数据到服务器,但是服务器必须保证这个key是不存在的,能够保证数据不会被覆盖

· replace 命令是替换一个已经存在的数据,如果数据不存在,就是类似set功能

<键> - key

就是保存在服务器上唯一的一个表示符,必须是跟其他的key不冲突,否则会覆盖掉原来的数据,这个key是为了能够准确的存取一个数据项目

<标记> - flag

标记是一个16位的无符号整形数据,用来设置服务器端跟客户端一些交互的操作

<有效期> - expiration time

是数据在服务器上的有效期限,如果是0,则数据永远有效,单位是秒,Memcache服务器端会把一个数据的有效期设置为当前Unix时间+设置的有效时间

<数据长度> - bytes

数据的长度,block data 块数据的长度,一般在这个个长度结束以后下一行跟着block data数据内容,发送完数据以后,客户端一般等待服务器端的返回。

数据保存成功

STORED

数据保存失败,一般是因为服务器端这个数据key已经存在了

NOT_STORED


3.[ 数据提取命令]

从服务器端提取数据主要是使用get指令,格式是:

get <键>*

<键>* -key

key是一个不为空的字符串组合,发送这个指令以后,等待服务器的返回。如果服务器端没有任何数据,则是返回:

END

证明没有不存在这个key,没有任何数据,如果存在数据,则返回指定格式:

VALUE <键> <标记> <数据长度>

<数据块>

返回的数据是以VALUE开始的,后面跟着key和flags,以及数据长度,第二行跟着数据块。

<键> -key

是发送过来指令的key内容

<标记> - flags

是调用set指令保存数据时候的flags标记

<数据长度> - bytes

是保存数据时候定位的长度

<数据块> - data block

数据长度下一行就是提取的数据块内容


4.[ 数据删除指令]

数据删除指令也是比较简单的,使用delete指令,格式是:

delete <键> <超时时间>

<键> - key

key是你希望在服务器上删除数据的key键

<超时时间> - timeout

按照秒为单位,这个是个可选项,如果你没有指定这个值,那么服务器上key数据将马上被删除,如果设置了这个值,那么数据将在超时时间后把数据清除,该项缺省值是0,表示永不过期。

删除数据后,服务器端会返回:

DELETED

删除数据成功

NOT_FOUND

这个key没有在服务器上找到

如果要删除所有服务器上的数据,可以使用flush_all指令,格式:

flush_all

这个指令执行后,服务器上所有缓存的数据都被删除,并且返回:

OK

这个指令一般不要轻易使,除非你确实想把所有数据都干掉,删除完以后可以无法恢复的。


5.[其他指令]

如果想了解当前Memcache服务器的状态和版本等信息,可以使用状态查询指令和版本查询指令。

如果想了解当前所有Memcache服务器运行的状态信息,可以使用stats指令,格式

stats

服务器将返回每行按照 STAT开始的状态信息,包括20行,20项左右的信息,包括守护进程的pid、版本、保存的项目数量、内存占用、最大内存限制等等信息。

如果只是想获取部分项目的信息,可以指定参数,格式:

stats <参数>

这个指令将只返回指定参数的项目状态信息。

如果只是想单独了解当前版本信息,可以使用version指令,格式:

version

将返回以 VERSION 开头的版本信息

如果想结束当前连接,使用quit指令,格式:

quit

将断开当前连接

另外还有其他指令,包括incr, decr 等,我也不太了解作用,就不做介绍了,如果感兴趣,可以自己去研究。


6.[MemAdmin]

MemAdmin是一款可视化的Memcached管理与监控工具,使用PHP开发,体积小,操作简单。

主要功能:

· 服务器参数监控:STATS、SETTINGS、ITEMS、SLABS、SIZES实时刷新

· 服务器性能监控:GET、DELETE、INCR、DECR、CAS等常用操作命中率实时监控支持数据遍历,方便对存储内容· 进行监视支持条件查询,筛选出满足条件的KEY或VALUE

· 数组、JSON等序列化字符反序列显示

· 兼容memcache协议的其他服务,如Tokyo Tyrant (遍历功能除外)

· 支持服务器连接池,多服务器管理切换方便简洁


应用实例

<?php
//memcache应用
$mem = new Memcache;
$mem->connect("127.0.0.1", 11211) or die("连接失败");
$mem->add('name','123');   //添加一个值  
$mem->add('name','1234');  //添加一个值,name的值还是不会变,还是输出123
$mem->set('name','1233');  //改变一个值,输出1233
echo $mem->get('name');
?>


六、高级Memcached客户机命令


可以在 memcached 中使用的两个高级命令是 gets casgets cas 命令需要结合使用。您将使用这两个命令来确保不会将现有的名称/值对设置为新值(如果该值已经更新过)。我们来分别看看这些命令。


1.gets

gets 命令的功能类似于基本的 get 命令。两个命令之间的差异在于,gets 返回的信息稍微多一些:64 位的整型值非常像名称/值对的 “版本” 标识符。


下面是使用 gets 命令的客户机服务器交互:

set userId 0 0 5

12345

STORED


get userId

VALUE userId 0 5

12345

END


gets userId

VALUE userId 0 5 4

12345

END


考虑 get 和 gets 命令之间的差异。gets 命令将返回一个额外的值 — 在本例中是整型值 4,用于标识名称/值对。如果对此名称/值对执行另一个 set 命令,则 gets 返回的额外值将会发生更改,以表明名称/值对已经被更新。下面显示了一个例子:


set 更新版本指示符

set userId 0 0 5

33333

STORED


gets userId

VALUE userId 0 5 5

33333

END


您看到 gets 返回的值了吗?它已经更新为 5。您每次修改名称/值对时,该值都会发生更改。


2.cas

cas(check 和 set)是一个非常便捷的 memcached 命令,用于设置名称/值对的值(如果该名称/值对在您上次执行 gets 后没有更新过)。它使用与 set 命令相类似的语法,但包括一个额外的值:gets 返回的额外值。


注意以下使用 cas 命令的交互:

set userId 0 0 5

55555

STORED


gets userId

VALUE userId 0 5 6

55555

END


cas userId 0 0 5 6

33333

STORED


如您所见,我使用额外的整型值 6 来调用 gets 命令,并且操作运行非常顺序。现在,我们来看看下面例中的一系列命令:


使用旧版本指示符的 cas 命令

set userId 0 0 5

55555

STORED


gets userId

VALUE userId 0 5 8

55555

END


cas userId 0 0 5 6

33333

EXISTS


注意,我并未使用 gets 最近返回的整型值,并且 cas 命令返回 EXISTS 值以示失败。从本质上说,同时使用 gets 和 cas 命令可以防止您使用自上次读取后经过更新的名称/值对。


缓存管理命令


最后两个 memcached 命令用于监控和清理 memcached 实例。它们是 stats 和 flush_all 命令。


stats

stats 命令的功能正如其名:转储所连接的 memcached 实例的当前统计数据。在下例中,执行 stats 命令显示了关于当前 memcached 实例的信息:

stats

STAT pid 63

STAT uptime 101758

STAT time 1248643186

STAT version 1.4.11

STAT pointer_size 32

STAT rusage_user 1.177192

STAT rusage_system 2.365370

STAT curr_items 2

STAT total_items 8

STAT bytes 119

STAT curr_connections 6

STAT total_connections 7

STAT connection_structures 7

STAT cmd_get 12

STAT cmd_set 12

STAT get_hits 12

STAT get_misses 0

STAT evictions 0

STAT bytes_read 471

STAT bytes_written 535

STAT limit_maxbytes 67108864

STAT threads 4

END

此处的大多数输出都非常容易理解。稍后在讨论缓存性能时,我还将详细解释这些值的含义。至于目前,我们先来看看输出,然后再使用新的键来运行一些 set 命令,并再次运行 stats 命令,注意发生了哪些变化。


flush_all

flush_all 是最后一个要介绍的命令。这个最简单的命令仅用于清理缓存中的所有名称/值对。如果您需要将缓存重置到干净的状态,则 flush_all 能提供很大的用处。下面是一个使用 flush_all 的例子:

set userId 0 0 5

55555

STORED


get userId

VALUE userId 0 5

55555

END


flush_all

OK


get userId

END


缓存性能


在本文的最后,我将讨论如何使用高级 memcached 命令来确定缓存的性能。stats 命令用于调优缓存的使用。需要注意的两个最重要的统计数据是 et_hits 和 get_misses。这两个值分别指示找到名称/值对的次数(get_hits)和未找到名称/值对的次数(get_misses)。


结合这些值,我们可以确定缓存的利用率如何。初次启动缓存时,可以看到 get_misses 会自然地增加,但在经过一定的使用量之后,这些 get_misses 值应该会逐渐趋于平稳 — 这表示缓存主要用于常见的读取操作。如果您看到 get_misses 继续快速增加,而 get_hits 逐渐趋于平稳,则需要确定一下所缓存的内容是什么。您可能缓存了错误的内容。


确定缓存效率的另一种方法是查看缓存的命中率(hit ratio)。缓存命中率表示执行 get 的次数与错过 get 的次数的百分比。要确定这个百分比,需要再次运行 stats 命令,如下例所示:


计算缓存命中率:

stats

STAT pid 6825

STAT uptime 540692

STAT time 1249252262

STAT version 1.2.6

STAT pointer_size 32

STAT rusage_user 0.056003

STAT rusage_system 0.180011

STAT curr_items 595

STAT total_items 961

STAT bytes 4587415

STAT curr_connections 3

STAT total_connections 22

STAT connection_structures 4

STAT cmd_get 2688

STAT cmd_set 961

STAT get_hits 1908

STAT get_misses 780

STAT evictions 0

STAT bytes_read 5770762

STAT bytes_written 7421373

STAT limit_maxbytes 536870912

STAT threads 1

END


现在,用 get_hits 的数值除以 cmd_gets。在本例中,您的命中率大约是 71%。在理想情况下,您可能希望得到更高的百分比 — 比率越高越好。查看统计数据并不时测量它们可以很好地判定缓存策略的效率。


安装多个memcached:

sc create "Memcached Server1" start= auto binPath= "C:\memcached\memcached.exe -d runservice -m 32 -p 11220 -l 127.0.0.1" DisplayName= "Memcached Server1"


下面是启动、停止、卸载该服务的命令:

sc start "Memcached Server1" //启动

sc stop "Memcached Server1" //停止

sc delete "Memcached Server1" //卸载该服务


分布式memcached测试:

<?php
//我的电脑上有两个memcahced服务.
$mem=new Memcache;
$mem->addServer('127.0.0.1',11211);
$mem->addServer('127.0.0.1',11221);
$mem->addServer('127.0.0.1',11220);
//这里注意,把key1,放入到 11211端口的mem还是
//9999 端口的mem就不要我们操心,有$mem对象本身维护.
if($mem->set('key1','hello',MEMCACHE_COMPRESSED,300)){
echo 'add ok!';
}
if($mem->set('key2','hello2',MEMCACHE_COMPRESSED,300)){
echo 'add ok!';
}
if($mem->set('key3','hello3',MEMCACHE_COMPRESSED,300)){
echo 'add ok!';
}
?>


总结:

1. mem服务的数据不是同步的, 数据是分布的

2. 把什么数据放入到哪个memcached是由客户端的mem对象决定

3. 当执行addServer的时候,并不是立即去连接mem服务,而是通过计算,hash后才去决定连接哪个mem服务,因此当你大量加入服务器到连接池,没有多余开销


七、Memcache的安全


我们上面的Memcache服务器端都是直接通过客户端连接后直接操作,没有任何的验证过程,这样如果服务器是直接暴露在互联网上的话是比较危险,轻则数据泄露被其他无关人员查看,重则服务器被入侵,因为Mecache是以root权限运行的,况且里面可能存在一些我们未知的bug或者是缓冲区溢出的情况,这些都是我们未知的,所以危险性是可以预见的。

为了安全起见,我做两点建议,能够稍微的防止黑客的入侵或者数据的泄露。


· 内网访问
最好把两台服务器之间的访问是内网形态的,一般是Web服务器跟Memcache服务器之间。普遍的服务器都是有两块网卡,一块指向互联网,一块指向内网,那么就让Web服务器通过内网的网卡来访问Memcache服务器,我们Memcache的服务器上启动的时候就监听内网的IP地址和端口,内网间的访问能够有效阻止其他非法的访问。

# memcached -d -m 1024  -u root -l 192.168.0.200 -p 11211 -c 1024 -P /tmp/memcached.pid

Memcache服务器端设置监听通过内网的192.168.0.200的ip的11211端口,占用1024MB内存,并且允许最大1024个并发连接。


· 设置防火墙

防火墙是简单有效的方式,如果却是两台服务器都是挂在网的,并且需要通过外网IP来访问Memcache的话,那么可以考虑使用防火墙或者代理程序来过滤非法访问。

一般我们在Linux下可以使用iptables或者FreeBSD下的ipfw来指定一些规则防止一些非法的访问,比如我们可以设置只允许我们的Web服务器来访问我们Memcache服务器,同时阻止其他的访问。

# iptables -F

# iptables -P INPUT DROP

# iptables -A INPUT -p tcp -s 192.168.0.2 --dport 11211 -j ACCEPT

# iptables -A INPUT -p udp -s 192.168.0.2 --dport 11211 -j ACCEPT

上面的iptables规则就是只允许192.168.0.2这台Web服务器对Memcache服务器的访问,能够有效的阻止一些非法访问,相应的也可以增加一些其他的规则来加强安全性,这个可以根据自己的需要来做。

 

八、Memcache的扩展性


Memcache算是比较简洁高效的程序,Memcache 1.2.0 的源代码大小才139K,在Windows平台上是不可想象的,但是在开源世界来说,这是比较正常合理的。
Memcache目前都只是比较简单的功能,简单的数据存取功能,我个人希望如果有识之士,能够在下面两方面进行扩展。


1. 日志功能
目前Memcache没有日志功能,只有一些命令在服务器端进行回显,这样是很不利于对一个服务器的稳定性和负载等等进行监控的,最好能够相应的加上日志的等功能,便于监控。


2. 存储结构
目前的数据形式就是: key => data 的形式,特别单一,只能够存储单一的一维数据,如果能够扩展的话,变成类似数据库的格式,能够存储二维数据,那样会让可以用性更强,使用面更广,当然相应的可能代码效率和存取效率更差一些。


3. 同步功能

数据同步是个比较重要的技术,因为谁都不能保证一台服务器是持久正常的运行的,如果能够具有类似MySQL的 Master/Slave 的功能,那么将使得Memcache的数据更加稳定,那么相应的就可以考虑存储持久一点的数据,并且不用害怕Memcache的down掉,因为有同步的备份服务器,这个问题就不是问题了。

以上三点只是个人拙见,有识之士和技术高手可以考虑。


阅读本文上:php进阶--memcache技术应用详解(上) 


参考网址:

http://www.runoob.com/memcached/memcached-tutorial.html 

http://php.net/manual/zh/book.memcache.php 

https://www.cnblogs.com/lizucq/p/5948784.html 

https://blog.csdn.net/hanjianqiang2468/article/details/52606379

https://www.cnblogs.com/yjken/articles/3927503.html


转载请注明: ITTXX.CN--分享互联网 » php进阶(四)--memcache技术应用详解(下)

最后更新:2019-03-21 13:20:27

赞 (4) or 分享 ()
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽