Memcache

addServer
在说Memcache的长连接(pconnect)和短连接(connect)之前要先说说Memcache的addServer,Memcache的addServer是增加一个服务器到连接池中(addServer没有连接到服务器的动作,所以在memcache进程没有启动的时候,执行addServer成功也会返回true)。通过 Memcache::addServer() 打开的连接将会在脚本执行结束后自动关闭,也可以使用 Memcache::close()进行手动关闭。当使用这个方法的时候(与Memcache::connect()和 Memcache::pconnect()相反) 网络连接并不会立刻建立,而是直到真正使用的时候才建立。 因此在加入大量服务器到连接池中时也是没有开销的,因为它们可能并不会被使用。addServer的第三个参数persistent就是是否使用长连接(pconnect),默认是TRUE。

pconnect

 

Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力。它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这些HashTable。Memcache官方网站:http://www.danga.com/memcached,更多详细的信息可以来这里了解。

为什么会有Memcache和memcached两种名称?其实Memcache是这个项目的名称,而memcached是它服务器端的主程序文件名,知道我的意思了把~~~~。一个是项目名称,一个是主程序文件名,在网上看到了很多人不明白,于是混用了。

Memcache的安装

分为两个过程:memcache服务器端的安装和memcached客户端的安装。

所谓服务器端的安装就是在服务器(一般都是linux系统)上安装Memcache实现数据的存储。

所谓客户端的安装就是指php(或者其他程序,Memcache还有其他不错的api接口提供)去使用服务器端的Memcache提供的函数,需要php添加扩展。

PHP的Memcache

01<?php
02    //连接
03    $mem = new Memcache;
04    $mem->connect("db.nowamagic.net", 12000);
05    //保存数据
06    $mem->set('key1', 'This is first value', 0, 60);
07    $val = $mem->get('key1');
08    echo "Get key1 value: " . $val ."<br />";
09    //替换数据
10    $mem->replace('key1', 'This is replace value', 0, 60);
11    $val = $mem->get('key1');
12    echo "Get key1 value: " . $val . "<br />";
13    //保存数组
14    $arr = array('aaa', 'bbb', 'ccc', 'ddd');
15    $mem->set('key2', $arr, 0, 60);
16    $val2 = $mem->get('key2');
17    echo "Get key2 value: ";
18    print_r($val2);
19    echo "<br />";
20    //删除数据
21    $mem->delete('key1');
22    $val = $mem->get('key1');
23    echo "Get key1 value: " . $val . "<br />";
24    //清除所有数据
25    $mem->flush();
26    $val2 = $mem->get('key2');
27    echo "Get key2 value: ";
28    print_r($val2);
29    echo "<br />";
30    //关闭连接
31    $mem->close();
32?>

如果正常的话,浏览器将输出:

1Get key1 value: This is first value
2Get key1 value: This is replace value
3Get key2 value: Array ( [0] => aaa [1] => bbb [2] => ccc [3] => ddd )
4Get key1 value:
5Get key2 value:

程序代码分析

初始化一个Memcache的对象:$mem = new Memcache;

连接到我们的Memcache服务器端,第一个参数是服务器的IP地址,也可以是主机名,第二个参数是Memcache的开放的端口:$mem->connect("192.168.0.200", 12000);

保存一个数据到Memcache服务器上,第一个参数是数据的key,用来定位一个数据,第二个参数是需要保存的数据内容,这里是一个字符串,第三个参数是一个标记,一般设置为0或者MEMCACHE_COMPRESSED就行了,第四个参数是数据的有效期,就是说数据在这个时间内是有效的,如果过去这个时间,那么会被Memcache服务器端清除掉这个数据,单位是秒,如果设置为0,则是永远有效,我们这里设置了60,就是一分钟有效时间:$mem->set(‘key1‘, ‘This is first value’, 0, 60);

从Memcache服务器端获取一条数据,它只有一个参数,就是需要获取数据的key,我们这里是上一步设置的key1,现在获取这个数据后输出输出:

1$val = $mem->get(’key1′);
2echo "Get key1 value: " . $val;

现在是使用replace方法来替换掉上面key1的值,replace方法的参数跟set是一样的,不过第一个参数key1是必须是要替换数据内容的key,最后输出了:

1$mem->replace('key1', 'This is replace value', 0, 60);
2$val = $mem->get('key1');
3echo "Get key1 value: " . $val;

同样的,Memcache也是可以保存数组的,下面是在Memcache上面保存了一个数组,然后获取回来并输出:

1$arr = array('aaa', 'bbb', 'ccc', 'ddd');
2$mem->set('key2', $arr, 0, 60);
3$val2 = $mem->get('key2');
4print_r($val2);

现在删除一个数据,使用delte接口,参数就是一个key,然后就能够把Memcache服务器这个key的数据删除,最后输出的时候没有结果:

1$mem->delete('key1');
2$val = $mem->get('key1');
3echo "Get key1 value: " . $val . "<br />";

最后我们把所有的保存在Memcache服务器上的数据都清除,会发现数据都没有了,最后输出key2的数据为空,最后关闭连接:

1$mem->flush();
2$val2 = $mem->get('key2');
3echo "Get key2 value: ";
4print_r($val2);
5echo "<br />";

Memcache的使用

使用Memcache的网站一般流量都是比较大的,为了缓解数据库的压力,让Memcache作为一个缓存区域,把部分信息保存在内存中,在前端能够迅速的进行存取。那么一般的焦点就是集中在如何分担数据库压力和进行分布式,毕竟单台Memcache的内存容量的有限的。我这里简单提出我的个人看法,未经实践,权当参考。

分布式应用

Memcache本来支持分布式,我们客户端稍加改造,更好的支持。我们的key可以适当进行有规律的封装,比如以user为主的网站来说,每个用户都有User ID,那么可以按照固定的ID来进行提取和存取,比如1开头的用户保存在第一台Memcache服务器上,以2开头的用户的数据保存在第二胎Mecache服务器上,存取数据都先按照User ID来进行相应的转换和存取。

但是这个有缺点,就是需要对User ID进行判断,如果业务不一致,或者其他类型的应用,可能不是那么合适,那么可以根据自己的实际业务来进行考虑,或者去想更合适的方法。

减少数据库压力

这个算是比较重要的,所有的数据基本上都是保存在数据库当中的,每次频繁的存取数据库,导致数据库性能极具下降,无法同时服务更多的用户,比如MySQL,特别频繁的锁表,那么让Memcache来分担数据库的压力吧。我们需要一种改动比较小,并且能够不会大规模改变前端的方式来进行改变目前的架构。

我考虑的一种简单方法:

后端的数据库操作模块,把所有的Select操作提取出来(update/delete/insert不管),然后把对应的SQL进行相应的hash算法计算得出一个hash数据key(比如MD5或者SHA),然后把这个key去Memcache中查找数据,如果这个数据不存在,说明还没写入到缓存中,那么从数据库把数据提取出来,一个是数组类格式,然后把数据在set到Memcache中,key就是这个SQL的hash值,然后相应的设置一个失效时间,比如一个小时,那么一个小时中的数据都是从缓存中提取的,有效减少数据库的压力。缺点是数据不实时,当数据做了修改以后,无法实时到前端显示,并且还有可能对内存占用比较大,毕竟每次select出来的数据数量可能比较巨大,这个是需要考虑的因素。

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服务器,同时阻止其他的访问。

view sourceprint?

1# iptables -F
2# iptables -P INPUT DROP
3# iptables -A INPUT -p tcp -s 192.168.0.2 –dport 11211 -j ACCEPT
4# iptables -A INPUT -p udp -s 192.168.0.2 –dport 11211 -j ACCEPT

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

 

 

 

 

 

Memcache::pconnect()和 Memcache::connect()非常类似,不同点在于这里建立的连接是持久化的。这个连接不会在脚本执行结束后或者Memcache::close()被调用后关闭。同样你也可以使用函数memcache_pconnect()。

关于Memcache的长连接是如何重用的,这是一个网友的解释“persistent为false时的表现是很好理解的,请求来了就连接。请求完毕就关闭对Memcache Server的连接。至于 persistent为true的情况,处理也是比较简单的。一个Memcache的连接hash值主要跟host、port以及timeout有关。有一个连接请求到来时就根据host和port生成一个hash值,然后查表。有则取出,没有则新建一个连接,新建后放入连接池。请求关闭时并不关闭对Memcache Server的连接,而是把这个连接(在做一些状态更新后)放入连接池(就是前面提到的那个hash 表),供下次查询使用。”Memcache的长连接(pconnect)开销较小,但是占用TCP端口。

connect
Memcache::connect()建立一个到memcached服务端的连接。 使用方法 Memcache::connect()打开的连接在脚本执行结束后会自动关闭。当然,你也可以使用方法 Memcache::close()来主动关闭。 同时你也可以使用 memcache_connect()函数来获取一个连接。

Memcached的连接数
登录到Memcache Server查看服务器的状态

1
2

 telnet 127.0.0.1 11211
 stats

得到如下结果

STAT pid 23193
STAT uptime 5846159
STAT time 1350869831
STAT version 1.4.9
STAT libevent 1.4.13-stable
STAT pointer_size 64
STAT rusage_user 18130.632724
STAT rusage_system 53822.121793
STAT curr_connections 2048
STAT total_connections 98471150
STAT connection_structures 2383
STAT reserved_fds 20
STAT cmd_get 3570290772
STAT cmd_set 98386836
STAT cmd_flush 2
STAT cmd_touch 0
STAT get_hits 2697025276
STAT get_misses 873265496
STAT delete_misses 6124562
STAT delete_hits 26956415
STAT incr_misses 0
STAT incr_hits 0
STAT decr_misses 0
STAT decr_hits 0
STAT cas_misses 0
STAT cas_hits 0
STAT cas_badval 0
STAT touch_hits 0
STAT touch_misses 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 138982259474
STAT bytes_written 3052329831433
STAT limit_maxbytes 8589934592
STAT accepting_conns 1
STAT listen_disabled_num 0
STAT threads 4
STAT conn_yields 2322
STAT hash_power_level 21
STAT hash_bytes 16777216
STAT hash_is_expanding 0
STAT expired_unfetched 743266
STAT evicted_unfetched 0
STAT bytes 1109591787
STAT curr_items 2343667
STAT total_items 98338176
STAT evictions 0
STAT reclaimed 1492847
END

发现当前打开着的连接数(curr_connections)已经达到了上限2048,而命中率 = get_hits/cmd_get * 100 = 75.54% 这个效率已经相当低了,Memcached最大同时连接数默认是1024,增加最大连接数命中率应该会有所改变。

关于PHP使用Memcache的详细参数和示例推荐这篇文章:php操作memcache的使用测试总结
关于Memcached的全面解析,这里有几篇翻译不错的文章
也顺便推荐下一个不错的Memcached图形化管理监控工具:MemAdmin

<think>好的,我现在需要向用户介绍Memcache。首先,我应该回忆一下Memcache的基本概念和主要用途。Memcache是一个分布式内存缓存系统,对吧?它主要用于减轻数据库负载,通过缓存数据来提升应用性能。接下来,我需要确定用户可能关心的几个方面,比如工作原理、主要特性、使用场景、优缺点以及和类似技术的比较。 用户可能想知道Memcache是如何工作的。这时候我需要解释它基于键值存储,数据存储在内存中,所以访问速度很快。另外,分布式特性也很重要,Memcache可以在多台服务器上运行,客户端通过一致性哈希来选择节点。不过,这里可能需要详细说明一下一致性哈希的作用,避免用户不理解。 然后,主要特性方面,内存存储、键值对结构、分布式、LRU淘汰策略都是关键点。需要简单解释每个特性的作用和好处。例如,LRU策略用于在内存不足时自动移除最久未使用的数据,保持缓存的有效性。 使用场景部分,用户可能想知道什么时候应该使用Memcache。常见的场景包括数据库查询缓存、会话存储、API调用缓存和页面片段缓存。每个场景都需要一个例子,比如缓存频繁查询的数据库结果,减少数据库压力。 优缺点方面,优点包括高速访问、扩展性好、简单易用;缺点则是数据易失性、不支持复杂查询、容量受限。这里需要平衡说明,让用户了解在什么情况下适合使用Memcache,什么情况下可能需要其他解决方案。 可能用户还会想知道Memcache和Redis的区别,但用户没有直接问,不过作为补充说明可以提到,比如Redis支持持久化和更多数据结构,而Memcache更简单,适合纯缓存需求。但根据系统指令,用户不可见层要求只回答用户的问题,可能需要避免扩展太多,除非必要。 接下来需要确保使用正确的格式,行内数学表达式用$...$,比如提到内存容量时,如果有涉及数值可能需要,但可能这里不太需要。不过根据示例,用户提到了变量和方程的例子,可能这里不太适用,但要注意如果有数学相关内容的话要正确应用格式。 结构方面,需要分点清晰,使用标题和子标题,但根据Markdown格式,用户希望的是结构清晰,但实际输出可能需要避免使用Markdown,所以可能需要用文字描述结构,比如用数字和项目符号。不过根据用户提供的示例回答,是使用了加粗和分点,但可能不需要Markdown语法,而是自然语言的结构。 另外,需要检查LaTeX语法是否正确,虽然Memcache的介绍可能不涉及太多数学公式,但如果提到性能指标或算法名称,可能需要确认。例如,LRU算法可以提到,但不需要用公式,除非特别说明。 最后,确保用中文回答,语言简洁明了,逐步解释,帮助用户理解Memcache的各个方面。需要避免技术术语过于复杂,必要时进行解释,比如“一致性哈希”可能需要简单说明其作用,如帮助数据分布和节点增减时的最小数据迁移。 总结,回答的结构应该是:概述、工作原理、主要特性、使用场景、优缺点,最后可能有个小结。每个部分分点说明,使用例子帮助理解,同时确保符合系统级指令的格式要求,没有使用任何Markdown,行内公式正确应用(如果有的话),独立公式单独成段(但可能这里不需要)。检查语法和正确性,确保信息准确无误。</think>Memcache 是一种高性能的分布式内存缓存系统,主要用于通过缓存数据来减轻数据库负载、提升应用响应速度。以下是其核心内容的逐步解析: --- ### 1. **基本概念** - **定位**:Memcache 专为缓存设计,将数据存储在内存中,通过键值对(Key-Value)形式提供快速访问。 - **分布式特性**:支持多服务器节点组成的集群,数据分布通过**一致性哈希算法**实现(例如:节点增减时仅影响部分数据)。 --- ### 2. **工作原理** - **数据存储**:应用程序将查询结果或计算数据存入 Memcache,键名(Key)需唯一,值(Value)可以是字符串、对象等。 - **数据读取**:请求优先访问 Memcache,若命中(存在数据)则直接返回;若未命中(无数据),则从数据库读取并回填缓存。 - **内存管理**:采用 **LRU(Least Recently Used)算法** 自动淘汰最久未使用的数据,释放内存空间。 --- ### 3. **主要特性** - **高速访问**:内存操作使得读写延迟极低(通常为毫秒级)。 - **横向扩展**:可通过增加节点提升容量与吞吐量。 - **协议简单**:基于文本或二进制的协议(如 `memcached protocol`),易于集成。 - **无持久化**:数据仅存于内存,重启或崩溃后丢失。 --- ### 4. **典型使用场景** - **数据库查询缓存**:缓存频繁访问的 SQL 查询结果(例如:商品信息)。 - **会话存储**:存储用户登录状态(Session),替代传统文件或数据库存储。 - **API 响应缓存**:缓存第三方 API 结果(例如:天气数据),避免重复调用。 - **页面片段缓存**:缓存网页局部内容(例如:导航栏),加速页面渲染。 --- ### 5. **优缺点分析** #### **优点** - 显著降低数据库压力,提升吞吐量。 - 分布式架构易于扩展。 - 轻量级,部署和维护成本低。 #### **缺点** - 数据易失性:不适用于需持久化的场景。 - 功能单一:仅支持键值操作,不支持复杂查询或事务。 - 容量限制:受内存大小制约,需合理规划淘汰策略。 --- ### 6. **与 Redis 的对比** - **Memcache**:专注纯缓存场景,多线程模型性能高,但仅支持字符串类型。 - **Redis**:支持持久化、更多数据结构(如列表、哈希),适合需复杂操作的场景。 --- ### 7. **示例代码(伪代码)** ```python # 连接 Memcache 客户端 client = memcache.Client(['127.0.0.1:11211']) # 缓存数据(键:user_123,值:用户对象,过期时间:300秒) client.set('user_123', user_data, time=300) # 读取数据 user_data = client.get('user_123') if not user_data: user_data = db.query("SELECT * FROM users WHERE id=123") client.set('user_123', user_data, time=300) ``` --- ### 总结 Memcache 是解决高并发场景下数据库性能瓶颈的经典工具,适用于对速度要求高、允许数据临时性的场景。使用时需结合业务特点设计键名策略、过期时间和淘汰机制,以最大化缓存效率。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值