Memcache 教程

作者: zccst

一、 Memcache 概述

Memcache 是 danga.com 的一个开源项目,可以类比于 MySQL 这样的服务。 memcached 是高效、快速的分布式内存对象缓存系统,主要用于加速 WEB 动态应用程序。

用自己的话说, memcache 是一个服务器端软件,跟 apache 、 mysql 一样,也有自己的端口。维护一个存在于内存中的 hash 表。

二、 Memcache 工作原理

( 1 )初级

首先 memcached 是以守护程序方式运行于一个或多个服务器中,随时接受客户端的连接操作,客户端可以由各种语言编写,目前已知的客户端 API 包括 Perl/PHP/Python/Ruby/Java/C#/C 等等。客户端在与 memcached 服务建立连接之后,接下来的事情就是存取对象了,每个被存取的对象都有一个唯一的标识符 key ,存取操作均通过这个 key 进行,保存到 memcached 中的对象实际上是放置内存中的,并不是保存在 cache 文件中的,这也是为什么 memcached 能够如此高效快速的原因。注意,这些对象并不是持久的,服务停止之后,里边的数据就会丢失。

与许多 cache 工具类似, Memcached 的原理并不复杂。它采用了 C/S 的模式,在 server 端启动服务进程,在启动时可以指定监听的 ip ,自己的端口号,所使用的内存大小等几个关键参数。一旦启动,服务就一直处于可用状态。 Memcached 的目前版本是通过 C 实现,采用了单进程,单线程,异步 I/O ,基于事件 (event_based) 的服务方式 . 使用 libevent 作为事件通知实现。多个 Server 可以协同工作,但这些 Server 之间是没有任何通讯联系的,每个 Server 只是对自己的数据进行管理。 Client 端通过指定 Server 端的 ip 地址 ( 通过域名应该也可以 ) 。需要缓存的对象或数据是以 key->value 对的形式保存在 Server 端。 key 的值通过 hash 进行转换,根据 hash 值把 value 传递到对应的具体的某个 Server 上。当需要获取对象数据时,也根据 key 进行。首先对 key 进行 hash ,通过获得的值可以确定它被保存在了哪台 Server 上,然后再向该 Server 发出请求。 Client 端只需要知道保存 hash(key) 的值在哪台服务器上就可以了。

其实说到底, memcache 的工作就是在专门的机器的内存里维护一张巨大的 hash 表,来存储经常被读写的一些数组与文件,从而极大的提高网站的运行效率(当然花钱就是必不可免的事了,听说 MySpace 的每台 Cache 服务器都配备了至少 64G 的内存)。但是也要注意 memcache 不是万能的,毕竟网络方面的不稳定因素还是比较多的,如果不是很大的应用,我建议大家使用一些本地的轻量级的 Cache 库,比如 PHP 的 Cache_Lite 或者 Java 的 FileCache 等,最后希望大家读完这篇能有所收获 :)

( 2 )高级

很多人把它当作和 SharedMemory 那种形式的存储载体来使用,虽然 memcached 使用了同样的“ Key=>Value ”方式组织数据,但是它和共享内存、 APC 等本地缓存有非常大的区别。 Memcached 是分布式的,也就是说它不是本地的。它基于网络连接(当然它也可以使用 localhost )方式完成服务,本身它是一个独立于应用的程序或守护进程( Daemon 方式)。

Memcached 使用 libevent 库实现网络连接服务,理论上可以处理无限多的连接,但是它和 Apache 不同,它更多的时候是面向稳定的持续连接的,所以它实际的并发能力是有限制的。在保守情况下 memcached 的最大同时连接数为 200 ,这和 Linux 线程能力有关系,这个数值是可以调整的。关于 libevent 可以参考相关文档。 Memcached 内存使用方式也和 APC 不同。 APC 是基于共享内存和 MMAP 的, memcachd 有自己的内存分配算法和管理方式,它和共享内存没有关系,也没有共享内存的限制,通常情况下,每个 memcached 进程可以管理 2GB 的内存空间,如果需要更多的空间,可以增加进程数。

三、为什么要在 Web 中使用( memcache 解决什么问题)

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

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

( 2 )什么场合使用?

在很多时候, memcached 都被滥用了,这当然少不了对它的抱怨。我经常在论坛上看见有人发贴,类似于“如何提高效率”,回复是“用 memcached ”,至于怎么用,用在哪里,用来干什么一句没有。 memcached 不是万能的,它也不是适用在所有场合。

Memcached 是“分布式”的内存对象缓存系统,那么就是说,那些不需要“分布”的,不需要共享的,或者干脆规模小到只有一台服务器的应用, memcached 不会带来任何好处,相反还会拖慢系统效率,因为网络连接同样需要资源,即使是 UNIX 本地连接也一样。 在我之前的测试数据中显示, memcached 本地读写速度要比直接 PHP 内存数组慢几十倍,而 APC 、共享内存方式都和直接数组差不多。可见,如果只是本地级缓存,使用 memcached 是非常不划算的。

Memcached 在很多时候都是作为数据库前端 cache 使用的。因为它比数据库少了很多 SQL 解析、磁盘操作等开销,而且它是使用内存来管理数据的,所以它可以提供比直接读取数据库更好的性能,在大型系统中,访问同样的数据是很频繁的, memcached 可以大大降低数据库压力,使系统执行效率提升。另外, memcached 也经常作为服务器之间数据共享的存储媒介,例如在 SSO 系统中保存系统单点登陆状态的数据就可以保存在 memcached 中,被多个应用共享。

需要注意的是, memcached 使用内存管理数据,所以它是易失的,当服务器重启,或者 memcached 进程中止,数据便会丢失,所以 memcached 不能用来持久保存数据。很多人的错误理解, memcached 的性能非常好,好到了内存和硬盘的对比程度,其实 memcached 使用内存并不会得到成百上千的读写速度提高,它的实际瓶颈在于网络连接,它和使用磁盘的数据库系统相比,好处在于它本身非常“轻”,因为没有过多的开销和直接的读写方式,它可以轻松应付非常大的数据交换量,所以经常会出现两条千兆网络带宽都满负荷了, memcached 进程本身并不占用多少 CPU 资源的情况。

四、安装 memcache (在服务器端)

( 1 ) windows 下

( 2 )在 linux 下

五、 memcached 服务器的管理

( 1 ) Windows 下:

启动

查看端口,是否启动成功

( 2 ) Linux 下:

运行 memcached 守护程序很简单,只需一个命令行即可,不需要修改任何配置文件(也没有配置文件给你修改 ):

/usr/bin/memcached -d -m 128 -l 192.168.10.1 -p 10101 -u httpd

参数解释:
-d 以守护程序( daemon )方式运行 memcached ;
-m 设置 memcached 可以使用的内存大小,单位为 M ;
-l 设置监听的 IP 地址,如果是本机的话,通常可以不设置此参数;
-p 设置监听的端口,默认为 11211 ,所以也可以不设置此参数;
-u 指定用户,如果当前为 root 的话,需要使用此参数指定用户。

当然,还有其它参数可以用, man memcached 一下就可以看到了。

六、使用 memcache (在客户端)

不同语言:可以是 php/JAVA 等

首先,建立连接。通过 IP 和端口。访问 apache 、 mysql 也是通过 IP 和端口。

其实,连接成功后,使用:

Add

Set/replace

Get

Quit

遍历:本身没提供。

State 子命令: stat items

Stats cachedump 1 0

附: PHP 的 Memcache

< ?php

// 连接

$mem = new Memcache;

$mem->connect("192.168.0.200", 12000);

// 保存数据

$mem->set('key1', 'This is first value', 0, 60);

$val = $mem->get('key1');

echo "Get key1 value: " . $val ."<br />";

// 替换数据

$mem->replace('key1', 'This is replace value', 0, 60);

$val = $mem->get('key1');

echo "Get key1 value: " . $val . "<br />";

// 保存数组

$arr = array('aaa', 'bbb', 'ccc', 'ddd');

$mem->set('key2', $arr, 0, 60);

$val2 = $mem->get('key2');

echo "Get key2 value: ";

print_r($val2);

echo "<br />";

// 删除数据

$mem->delete('key1');

$val = $mem->get('key1');

echo "Get key1 value: " . $val . "<br />";

// 清除所有数据

$mem->flush();

$val2 = $mem->get('key2');

echo "Get key2 value: ";

print_r($val2);

echo "<br />";

// 关闭连接

$mem->close();

?>

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

Get key1 value: This is first value

Get key1 value: This is replace value

Get key2 value: Array ( [0] => aaa [1] => bbb [2] => ccc [3] => ddd )

Get key1 value:

Get 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 ,现在获取这个数据后输出输出:

$val = $mem->get('key1 ′ );

echo "Get key1 value: " . $val;

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

$mem->replace( ‘ key1 ′ , ‘ This is replace value', 0, 60);

$val = $mem->get( ‘ key1 ′ );

echo "Get key1 value: " . $val;

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

$arr = array(‘aaa', ‘bbb', ‘ccc', ‘ddd');

$mem->set( ‘ key2 ′ , $arr, 0, 60);

$val2 = $mem->get( ‘ key2 ′ );

print_r($val2);

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

$mem->delete( ‘ key1 ′ );

$val = $mem->get( ‘ key1 ′ );

echo "Get key1 value: " . $val . "<br>";

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

$mem->flush();

$val2 = $mem->get( ‘ key2 ′ );

echo "Get key2 value: ";

print_r($val2);

echo "<br>";

七、 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教程相关推荐

  1. 08nosql memcache 教程

    在线文档1:https://docs.qq.com/doc/DQVdadWNzcWJBSWdB Memcache常用命令:https://docs.qq.com/doc/DQVh5dWtQSXVjdE ...

  2. 使用Zabbix监控memcached

    转载来源 :使用Zabbix监控memcached :https://www.jianshu.com/p/0f08d73afa54 一. 环境准备(这里是测试环境) zabbix-server.3.2 ...

  3. phpst安装memcache扩展_在 Ubuntu/Debian 下安装 PHP7.3 教程

    介绍 最近的 PHP 7.3.0 已经在 2018 年12月6日 发布 GA,大家已经可以开始第一时间体验新版本了,这里先放出 PHP7.3 安装的教程以便大家升级. 适用系统: Ubuntu 18. ...

  4. PHP框架Yii系列教程(四):使用Memcache保存会话

    2019独角兽企业重金招聘Python工程师标准>>> 1环境准备 安装Memcached服务端:yum -y installmemcached.x86_64安装PHP-Memcac ...

  5. memcache基础教程

    memcache是什么 Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力. 它可以应 ...

  6. [浪风推荐]php的memcache应用入门教程

    所需环境: php 5.3.3 apache 2.2.7 mysql 5.5.8 解压Memcached_1.2.5文档,cmd下执行memcached.exe -d -install 将php5.3 ...

  7. php 内存队列,memcache构建简单的内存消息队列_PHP教程

    本文章来给各位同学介绍使用memcache构建简单的内存消息队列,用一个比较不错的实例来给大家介绍,希望此方法对大家有帮助哦. memcache功能太简单了,只能 set get 和delete, 只 ...

  8. ubunntu安装php7.0_在 Ubuntu/Debian 下安装 PHP7.3 教程

    介绍 最近的 PHP 7.3.0 已经在 2018 年12月6日 发布 GA,大家已经可以开始第一时间体验新版本了,这里先放出 PHP7.3 安装的教程以便大家升级. 适用系统: Ubuntu 18. ...

  9. 黑客渗透入门教程 第一课:粗暴的端口扫描

    很多人想学黑客知识,却不知如何入门,网上的教程也太繁琐,小白看了也头疼,那还是我来写黑客系列入门教程吧,跟着我做,你能黑客入门的. 端口扫描是指发送一组扫描消息,了解其提供的计算机网络服务类型(这些网 ...

最新文章

  1. Android Dialog 弹框之外的区域 默认透明背景色修改
  2. Gastroenterology:住院期间COVID-19患者肠道菌群的变化
  3. java 最少使用(lru)置换算法_「面试」LRU了解么?看看LinkedHashMap如何实现LRU算法...
  4. 一步一图,带你走进 Netty 的世界!
  5. Hibernate(九)一对多双向关联映射
  6. Expandable Input Toolbar
  7. Maven中dependencies与dependencyManagement的区别
  8. java多用户商城b2b2c源码
  9. 树莓派Raspberry Pi OS开机自启动脚本
  10. 丢失控制文件恢复实验记录--4(在线日志文件没有损坏,归档日志丢失,直接重建控制文件(跟踪控制文件trace是旧的情况))...
  11. 在Java中基于mysql驱动包连接MySQL数据库
  12. 微信小程序底部导航栏tabBar及不显示问题解决记录
  13. Windows下载安装 PostgreSQL和PostGIS工具,并解决The pgAdmin 4 server could not be contacted:
  14. 测量学matlab使用心得,测量学实习心得体会4篇
  15. 如何解析(读取)LZ4压缩格式的Spark EventLog日志
  16. 三菱fx2n64mr说明书_三菱基本单元 FX2N-64MR-001
  17. ubuntu系统dhcp服务器,ubuntu如何启用dhcp服务器配置
  18. 在全民直播的背景下,金融机构做直播带货是必须的吗?
  19. SpringBoot+Vue实现前后端分离的网吧管理系统
  20. H5 移动端上传图片 和 视频 页面显示缩略图

热门文章

  1. Centos篇-Centos Minimal安装
  2. Linux signal、sigaction的使用总结
  3. c/c++ read 函数和 write 函数
  4. Unity中在运行时获取AnimationClip中的关键帧信息
  5. 联想拯救者Y7000/Y7000P EFI
  6. Windows文件管理器异常无响应,访问共享文件导致无响应的处理办法
  7. Linux安装docker及其他镜像
  8. 我的编程之路:从好玩到玩好
  9. 深谈个人对新技术的看法
  10. 程序设计之学生宿舍管理系统