扫盲:php session缓存至memcached中的方法

memcached是一套分布式的快取系统,当初是Danga Interactive为了LiveJournal所发展的,但被许多软件(如MediaWiki)所使用。这是一套开放源代码软件,以BSD license授权协议发布。[1]

memcached仅支持一些非常简单的命令 比如get(获取某个键值) set(用来设定或保存一个缓存);

其本身是缓存服务器,但本身无法决定缓存任何数据,其缓存机制依赖于服务端和客户端两者必不可少(存储是由服务端进行存储,但存储什么是由客户端进行决定的)

因此客户端要自己提供缓存的键名以及时长、标志位、整个数据大小等等

例如:只存储hello 但只存储60秒

set key 5 60 hello

并告知服务器端,这样存储过了60秒后,由服务端进行清除数据

但是其工作机制非常独特,其缓存功能是基于Lazy模型的:

只要空间未满则不清理

那么问题来了:如果空间过小,而需缓存的内容过大的话,那么导致缓存抖动非常严重,存完即清理其次再去缓存这样会导致命中率下降,而毫无意义

有些时候,有些数据管理不善有可能导致缓存崩溃等

如果memcached崩溃仅导致业务层的影响,最多是速度降低 而不会导致数据层

memcached如何实现缓存的

memcached通过内存进行缓存数据,但并不实现持久缓存

存数数据的下限:

最小为48字节

最大不能超过1MB

但存储的数据大小有可能不一致,比如:

index.html10k

test.jpg34k

那memcached如何在内存中管理缓存数据

假如我们分别存储不同大小的数据以上为例

很显然只要分配一个足够大的空间就可以了,但是在内存中去找对应的数据我们必须要有对应的缓存对象的边界(起始存储位地址和结束存储位地址)将其当做独立的单位来管理

等其缓存失效了,空间会被腾出,时间久了可能会带来碎片,因为存储的都是非常小的数据单元,按理说如果再想高速利用则会困难,所以在这种机制下memcached的存储数据 查询数据等操作都是非常缓慢的

由此,不停快速基于内存的申请、释放反复操作,这种释放本身也消耗大量的资源和时间

因此我们需要一种高效的机制来解决内存的创建和释放的问题

对于memcached来讲首要必须解决这类内存碎片问题,不然由于内存的碎片导致进程运行的非常缓慢

在linux内核中引入了两种机制避免内存碎片

1.buddy system    伙伴系统

为了实现整个内存中以页面方式管理内存的时候有足够大的连续内存空间可用的,在物理内存中,事实上内存的管理和分配在内核级别通常以页面方式分配和使用的

通常是4k大小一个页面,buddy就是为了将这些零碎的、空闲的合并成一个连续的大的内存空间,这样就避免了页面之间产生碎片的,因此,其主要目的是为了避免内存外碎片

2.slab allocator  slab分配器

实现将存储小于页面单位的非常小的数据内存结构的时候之前事先分配并随时等待有需求的进程或要存储的对象使用,当我们使用之后它也不会自动消毁结构而是随时重复使用

避免内存内部碎片

最新版本的memcached使用的是增长因子(growth factor)来明确定义起始点开始依次增长

比如:

我们定义增长因子为其2倍

我们存储一个单位为48bytes,那么会分配其48*2 = 96bytes

如果增长因子为1.1倍

那么48+48*1.1

一旦存储空间满了,则会清理,没有存满则不会清理数据

memcached也支持分布式缓存基础概念

memcached也支持分布式缓存,但是彼此之间不会通信,但是一个memcached也不会缓存过多数据,如果将来缓存的数据很大的话,那只能使用多台memcached提供服务

假设这么一个场景:

前端的应用服务器很多,这些服务器角色都需要连接至数据库,为了加速数据库的性能,可对其提供memcached服务器,经过一段时间观察,我们的memcached数据库缓存过多,请求量过大一台机器根本扛不住,这时需要对其扩容。

于是我们又加入了一台memcached,但是memcached服务器之间是不能通信的

所以某一应用服务器A 要缓存数据不能只盯一台memcached,所以我们要让其轮流来提供服务,但是对memcached而言它的分布式算法是在应用程序(客户端)中实现的,而不是取决于服务器自身

客户端是如何分布式调度服务端

需要一定分布式算法,和调度器

(如果memcached非常多的话,完全可以使用第三方调度器进行调度,比如nginx+持久连接)

或一致性哈希算法:

参考:http://blog.csdn.net/kongqz/article/details/6695417

总结:

1、在内存中缓存

2、内存要使用slab allocator将其分配成很多slab trunk,每个trunk用来存储一类数据的,而真正存的数据很有可能不会被精确匹配,而我们需要给其找一个最佳的匹配机制就是用来slab trunk来存储 但是难免会浪费内存空间,但是可以让我们内存分配效率非常高

安装配置memcached服务

Memcached依赖于libeventAPI库,所以首先要安装libevent

[[email protected]]# tar xf libevent-2.0.21-stable.tar.gz

[[email protected]]# cd libevent-2.0.21-stable

[[email protected]]# ./configure --prefix=/usr/local/memcached--with-libevent=/usr/local/libevent

[[email protected]]# make && make install

安装memcached

[[email protected]]#cd memcached-1.4.15

[[email protected]]# ./configure --prefix=/usr/local/memcached--with-libevent=/usr/local/libevent && make && make install

启动memcached

启动之前我们先来看一下memcahced关键的几个参数

关键参数说明

[[email protected]]# ./memcached -h

-p 监听tcp协议的监听端口

-T 监听UDP协议id监听端口默认都是11211

-s 如果只在本地通信那么可以将其监听在某个套接字上,比如mysql.scok 能够利用共享内存方式进行通信的

-c 最大并发连接数

-l 监听的地址,如果服务器有多块网卡,那么用-l来指定监听的某个网卡上

-d 以一个服务方式运行

-r 设定最大内核大小限制

-u 以某个用户身份运行

-m  以兆为单位指定memcached最大内存可用空间

-t 用于处理入站请求最大的线程数,仅在memcached编译时开启了支持线程才有效,而linux对线程支持是非常有限的,所以不用关心了

-f 设定slab定义预先分配内存空间大小固定的块时使用的增长因子

-n 最小的存储单位是多大,默认是48字节,单位是字节

-P 指定pid文件

-L 视图使用最多的内存空间

-S 启用SSL认证功能

启动memcached

这里先放在前台运行,并观察其增长因子,如下所示:

[[email protected]]# /usr/local/memcached/bin/memcached -m 128 -n 20 -f 1.25 -vv -u nobody

slabclass1: chunksize72 perslab14563

slabclass2: chunksize96 perslab 10922

slabclass3: chunksize120 perslab 8738

slabclass4: chunksize 152 perslab 6898

slabclass5: chunksize192 perslab5461

slabclass6: chunk size240 perslab4369

slabclass7: chunk size304 perslab3449

#################中间略#################

slabclass40: chunk size493552 perslab2

slabclass41: chunk size616944 perslab1

slabclass42: chunk size771184 perslab1

slabclass43: chunksize1048576perslab1

<26server listening (auto-negotiate)

<27server listening (auto-negotiate)

<28send buffer was 229376, now 268435456

<28server listening (udp)

<29send buffer was 229376, now 268435456

<29server listening (udp)

<28server listening (udp)

<29server listening (udp)

<28server listening (udp)

<29server listening (udp)

<28server listening (udp)

<29server listening (udp)

chunk size 表示最小为72 以1.25倍的方式增加

slab class 表示分配给Slab之后根据slab的大小切分成chunk,chunk用于缓存记录,特定大小的chunk组称为slab class

perslab 表示一共有多少个空闲空间可用

结束进程,将增长因子换种方式增长,并观察效果

[[email protected]]# /usr/local/memcached/bin/memcached -m 128 -n 20 -f 1.1 -vv -u nobody

slabclass1: chunksize72perslab14563

slabclass2:chunk size80 perslab13107

slabclass3:chunk size88 perslab11915

slabclass4: chunksize96perslab10922

slabclass5: chunk size112 perslab9362

slabclass6: chunk size128 perslab8192

###################中间略#################

slabclass95: chunk size750904 perslab1

slabclass96: chunk size826000 perslab1

slabclass97: chunk size908600 perslab1

slab class98: chunk size1048576 perslab1

以上,我们很明确对比出其差别

由此接下来我们就将其放在后台运行,加入-d参数

[[email protected]]# /usr/local/memcached/bin/memcached -m 128 -n 20 -f 1.1-u nobody -d

查看监听端口

[[email protected]]#netstat -lntup | grep memcache

tcp00 0.0.0.0:112110.0.0.0:*LISTEN9464/memcached

tcp00 :::11211:::*LISTEN9464/memcached

udp00 0.0.0.0:112110.0.0.0:*9464/memcached

udp00 :::11211:::*9464/memcached

连接memcahced

[[email protected]]# telnet 127.0.0.1 11211

使用add命令为memcahced新建键

格式:

addkeyname flag  timeout  datasize

例如:

addmykey 0 10 12
Hello world!

<30add mykey 0 10 12
hello

<30add mykey 0 10 12
hello

让php支持memcached

[[email protected]]# tar xf memcache-2.2.6.tgz

[[email protected] tools]# cd memcache-2.2.6

[[email protected]]# /usr/local/php/bin/phpize

Configuringfor:

PHP ApiVersion:20100412

ZendModule Api No:20100525

ZendExtension Api No:220100525

[[email protected]]# ./configure --with-php-config=/usr/local/php/bin/php-config--enable-memcache

[[email protected]]# make && make install

编译成功后,可以看到有如下反馈信息,将其路径记下

Installingshared extensions:/usr/local/php/lib/php/extensions/no-debug-non-zts-20100525/

查看模块是否存在

[[email protected]]#ls/usr/local/php/lib/php/extensions/no-debug-non-zts-20100525/

memcache.so

将其模块写入至php.d/目录下

[[email protected]]# echo‘extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20100525/memcache.so‘>/etc/php.d/memcache.ini

重启fastcgi

[[email protected]]# /etc/init.d/php-fpm restart

访问phpinfo,并查看是否有memcache模块扩展,如下所示:

对memcached功能进行测试

建立php测试页面,内容如下:

[[email protected]]# vim test.php

<?php
$mem = new Memcache;

;创建memcache对象连接其11211端口 ,如果能连接则说明可以访问memcache
$mem->connect("127.0.0.1", 11211)  or die("Could notconnect");

;如果服务能连接上,则显示其版本号是多少
$version = $mem->getVersion();
echo "Server‘s version: ".$version."<br/>\n";

;并且创建key名称为hellokey 内容为hello world 期限为600秒,这里没有长度,其会自动判断长度
$mem->set(‘hellokey‘, ‘Hello World‘, 0, 600) or die("Failed to savedata at the memcached server");
echo "Store data in the cache (data will expire in 600seconds)<br/>\n";

$get_result = $mem->get(‘hellokey‘);
echo "$get_result is from memcached server.";    
?>

访问测试:

连接memcahced ,可以看到,我们保存的键值与上一致

[[email protected]]#telnet 127.0.0.1 11211

Trying127.0.0.1...

Connectedto 127.0.0.1.

Escapecharacter is ‘^]‘.

get hellokey

VALUEhellokey 0 11

HelloWorld

END

由此可见,我们的php可以使用memcache了

将php的session会话信息保存至memcached当中

编辑php.ini配置文件

找到session相关参数

session.save_handler= files     #默认是使用文件保存session的

更改为:

session.save_handler= memcache

session.save_path="tcp://127.0.0.1:11211?persistent=1&weight=1&timeout=1&retry_interval=15"

如果memcahced使用的是公网服务器的话最好使用其公网地址

保存退出并重启服务

[[email protected]]# /etc/init.d/php-fpm restart

Gracefullyshutting down php-fpm . done

Startingphp-fpmdone

创建测试页setsession.php

[[email protected]]# cat setsession.php

<?php

session_start();

if(!isset($_SESSION[‘test‘])) {

$_SESSION[‘test‘] = time();

}

print$_SESSION[‘test‘];

print"<br><br>";

print"Session ID: " . session_id();

?>

新建php页面showsess.php,获取当前用户的会话ID:

[[email protected]]# cat showsess.php

<?php

session_start();

$memcache_obj= new Memcache;

$memcache_obj->connect(‘127.0.0.1‘,11211);

$mysess=session_id();

var_dump($memcache_obj->get($mysess));

$memcache_obj->close();

?>

而后找一其他主机,使用负载均衡轮询到不同的主机上,可以发现无论刷新至哪个页面 其用户的session是一样的

访问setsession.php

1399775256         #为获取时间
Session ID: 9a0itlgjlurghq83ibvmol5pc7     #为session的id号

获取session

可以看到其时间是与上面setsession是一样的

总结

这样一来比php将session保存在本地效率要快很多,如果以后要使用多台memcached的话至于开发程序能否实现负载均衡,到底是使用取余的算法还是使用一致性哈希的算法完全要看开发人员的决定了

感谢各位。

扫盲:php session缓存至memcached中的方法

时间: 2024-10-31 13:57:09

扫盲:php session缓存至memcached中的方法的相关文章

Memcached的安装配置及将PHP的session保存在Memcached中

Memcached是一款开源.高性能.分布式内存对象缓存系统,可应用各种需要缓存的场景,其主要目的是通过降低对Database的访问来加速web应用程序.它是一个基于内存的"键值对"存储,用于存储数据库调用.API调用或页面引用结果的直接数据,如字符串.对象等. Memcached现已成为mixi.hatena.Facebook.Vox.LiveJournal等众多服务中提高Web应用扩展性的重要因素. Memcached有以特点 1. 简单key/value存储:服务器不关心数据本身

将tomcat的session信息保存在memcached中

一.简介 MSM(memcached-session-manager)支持tomcat6和tomcat7 ,利用Value(Tomcat 阀对Request进行跟踪.Request请求到来时,从memcached加载session,Request请求结束时,将tomcat session更新至memcached,以达到session共享之目的,支持sticky和 non-sticky 模式. Sticky 模式:tomcat session为主session, memcached为备sessio

实战项目memcached+tomcat+session+nginx在工作中的应用和配置

环境介绍:公司根据实际需要搭建一个购物网站,当用户购物时可以 将不同商品,放到同一个购物车中进行同时付款. 环境的搭建: 外网用户  IP地址:1.1.1.1  主机名:fanxiaohui  用户访问网站http://www.taobao.com 使用nginx实现负载均衡,由于网页是用JAVA开发的所以选用tomcat搭建网站服务,由于用户在购物时http是一个无状态的协议,不同的商品都是一个新的连接,默认不会把几个商品放到同一个购物车中,无法进行统一结账,为了能使服务器能够认识是同一个客户

[原创]java WEB学习笔记78:Hibernate学习之路---session概述,session缓存(hibernate 一级缓存),数据库的隔离级别,在 MySql 中设置隔离级别,在 Hibernate 中设置隔离级别

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

Hibernate中的Session缓存问题

1. Session 缓存: 1) . 在 Session 接口的实现中包括一系列的 Java 集合 , 这些 Java 集合构成了 Session 缓存 . 它用于存放 Session 关联的对象( Session 关联对象的方式有非常多种. 比如:session.get (Class , OID ). session.update(). session.save ()  ...). 仅仅要 Session 实例没有结束生命周期 , 且没有清理缓存.则存放在它缓存中的对象也不会结束生命周期.

高性能缓存系统Memcached在ASP.NET MVC中应用

在Memcached中实体类型未经序列化不能在Memcached中缓存,因此需要对实体类进行处理,才能缓存下来. Memcached是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度.Memcached基于一个存储键/值对的hashmap.其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信. 我们可以使用Memcached缓

22_redis缓存配置及设置把session存储在redis中

django配置redis缓存 1. 安装django-redis包 pip install -i https://pypi.douban.com/simple django-redis 2. 在settings.py 文件中,指定redis缓存 # 配置redis缓存 CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION":

分布式缓存(MemCached)

最近在为找工作做准备,就看了好多.NET基础知识,发现很多关于页面之间传值的方式,其中就有Session,但也发现Session在实际使用过程中有很多问题.最典型也最重要大的BUG就是如果IIS中同时有很多进程发生时,内存不够用那么有垃圾回收机制,就会导致Session的丢失.解决方法有:可以用Sate Server或SQL Server数据库的方式存储Session,可是这两种方式都有个缺点就是处理速度慢,无法捕获END事件.因此,我便想那么还有什么方式可以解决这一问题呢? 结果就是使用分布式

五,session数据写入memcached

1,session数据通常保存在服务器端的文件中,它的默认过期时间是1440s.我们可以将session数据保存到memcached中,设定memcached的过期时间大于session过期时间即可.这样从内存读取session数据的速度高于从文件读取session数据. 2,session数据如果写入memcached,必须在php.ini中修改session的存取方式和存取路径. 将session.save_handler = files修改为session.save_handler = m