扫盲: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

[root@testtools]# tar xf libevent-2.0.21-stable.tar.gz 

[root@testtools]# cd libevent-2.0.21-stable

[root@testlibevent-2.0.21-stable]# ./configure --prefix=/usr/local/memcached--with-libevent=/usr/local/libevent

[root@testlibevent-2.0.21-stable]# make && make install

安装memcached

[root@testtools]#cd memcached-1.4.15

[root@testmemcached-1.4.15]# ./configure --prefix=/usr/local/memcached--with-libevent=/usr/local/libevent && make && make install

 

启动memcached

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

关键参数说明

[root@node1bin]# ./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

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

[root@testbin]# /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 表示一共有多少个空闲空间可用

 

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

[root@testbin]# /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 class98chunk size1048576 perslab1

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

 

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

[root@testbin]# /usr/local/memcached/bin/memcached -m 128 -n 20 -f 1.1-u nobody -d

查看监听端口

[root@testbin]#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

[root@testbin]# 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

[root@testtools]# tar xf memcache-2.2.6.tgz

[root@test tools]# cd memcache-2.2.6

[root@testmemcache-2.2.6]# /usr/local/php/bin/phpize

Configuringfor:

PHP ApiVersion:20100412

ZendModule Api No:20100525

ZendExtension Api No:220100525

[root@testmemcache-2.2.6]# ./configure --with-php-config=/usr/local/php/bin/php-config--enable-memcache

[root@testmemcache-2.2.6]# make && make install

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

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

查看模块是否存在

[root@testmemcache-2.2.6]#ls/usr/local/php/lib/php/extensions/no-debug-non-zts-20100525/

memcache.so

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

[root@testmemcache-2.2.6]# echo'extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20100525/memcache.so'>/etc/php.d/memcache.ini

重启fastcgi

[root@testmemcache-2.2.6]# /etc/init.d/php-fpm restart

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

wKiom1NvQFbzGoI5AAGeblkTK6E176.jpg

 

对memcached功能进行测试

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

[root@node1htdocs]# 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.";    

?>

访问测试:

wKioL1NvQETAHriaAAC0cd5vZuc179.jpg

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

[root@testhtdocs]#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使用的是公网服务器的话最好使用其公网地址

保存退出并重启服务

[root@testhtdocs]# /etc/init.d/php-fpm restart

Gracefullyshutting down php-fpm . done

Startingphp-fpmdone

创建测试页setsession.php

[root@testhtdocs]# 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:

[root@testhtdocs]# 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

wKioL1NvQGGDh61cAACaddedWVg504.jpg

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

 

获取session

wKiom1NvQKvTZZ99AACHnmI4r1g629.jpg

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

 

总结

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

感谢各位。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/461335.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用juniversalchardet做字符编码识别

为什么80%的码农都做不了架构师&#xff1f;>>> 在抓取网站的页面的时候最烦人的一件事情之一就是识别原站点的编码&#xff0c;通常来说只有GBK&#xff08;GB2312&#xff09;和UTF8两种&#xff0c;不过依旧需要读取大量Http头信息来识别&#xff0c;有些网站则…

获取系统信息1——linux系统中的时间

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、关于时间的概念 1、GMT时间 GMT是格林尼治时间&#xff0c;即格林尼治地区的当地时间。用格林尼治的当地时间作为全球国际时间&#xff0c;用以描述全球性的事件的时间&#xff0c;方便大家记忆…

判断一个字符串是否为回文-链队(新建,进队,出队),链栈(新建,进栈,出栈)...

回文&#xff1a;字符对称排列的字符串&#xff0c;例如ABCBA 思路&#xff1a;根据队&#xff1a;先进先出和栈: 先进后出的原则&#xff0c;进行比较出队和出栈的字符是否相等。如果相等&#xff0c;则为回文。 创建控制台应用程序。 1 #region 字符节点类 2 …

句法依存分析_复旦大学邱锡鹏教授:词法、句法分析研究进展综述

本文为第十六届自然语言处理青年学者研讨会 YSSNLP2019 报告《词法、句法分析研究进展综述》的简要文字整理&#xff0c;本报告主要回顾词法、句法领域的最新研究进展。 关于报告人&#xff1a;邱锡鹏&#xff0c;复旦大学计算机科学技术学院副教授&#xff0c;博士生导师。于复…

获取系统信息3——proc文件系统介绍和使用

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、proc文件系统介绍 1、操作系统级别的调试一般很困难 简单的程序可以单步调试&#xff1b;复杂一点的程序可以printf、cout等打印信息调试&#xff08;即输出信息到控制台&#xff09;&#xff0…

阻止函数源码在控制台输出

这是一个很贱的技能&#xff0c;我在谷歌控制台源码里看到的。相信大家都知道&#xff0c;在控制台里只输入函数名&#xff0c;不输入 () 然后按回车&#xff0c;就可以输出源码。 都不会陌生吧&#xff0c;这也有助于我们调试&#xff0c;是个很棒的技巧。不过系统内置的就会输…

值不值得入手_iPhone11现在还值不值得入手?真实用户说出心里话

iPhone11作为苹果走量的一款机型&#xff0c;自发布以来就备受争议&#xff0c;有的朋友说真香&#xff0c;A13iOS只卖4000多&#xff0c;还有的朋友吐槽大黑边、828P的屏幕、信号不好还有充电太慢&#xff0c;特别是现在同价位能买到的安卓旗舰&#xff0c;要5G有5G、要高刷新…

设备驱动,字符设备驱动、(总线)设备驱动模型、sysfs文件系统、平台设备驱动

以下内容转载于微信公众号&#xff1a;嵌入式企鹅圈。如有侵权&#xff0c;请告知删除。 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动、平台设备驱动、设备驱动模型和sysfs等相关概念和技术。 对于初学者来说会非常困惑&#xff0c;甚至对Linux有一定基础的工程师而言…

对于局部变量_对于SQL常用查询优化方法的整理

查询进行优化&#xff0c;应尽量避免全表扫描&#xff0c;首先应考虑在where 及order by 涉及的列上建立索引:尝试下面的技巧以避免优化器错选了表扫描&#xff1a;使用ANALYZE TABLE tbl_name为扫描的表更新关键字分布。对扫描的表使用FORCE INDEX告知MySQL&#xff0c;相对于…

黄聪:如何使用CodeSmith批量生成代码(原创系列教程)

在上一篇我们已经用PowerDesigner创建好了需要的测试数据库,下面就可以开始用它完成批量代码生成的工作啦. 下面我会一步步的解释如何用CodeSmith实现预期的结果的,事先声明一下,在此只做一个简单的Demo,并不详细的讲解CodeSmith各个强大的功能,有兴趣的朋友可以打开CodeSmith的…

c语音异或运算符_C语言中的按位异或运算符有什么用处?

原标题&#xff1a;C语言中的按位异或运算符有什么用处&#xff1f;想知道C语言中的按位异、运算符有什么用处&#xff0c;首先C语言中^为按位异或运算符&#xff0c;若两个二进制位相同&#xff0c;则结果为0&#xff0c;不同为1例&#xff1a;#include "stdio.h"ma…

HDU2201

水&#xff5e; 分析&#xff1a;n&#xff0c;m。对于第一个人不抽到m号座位概率为&#xff08;n-1&#xff09;/n&#xff0c;第二个人为&#xff08;n-2&#xff09;/&#xff08;n-1&#xff09;.。。。第m个人为1/&#xff08;n-m1&#xff09;.。。。 相乘之后则为 1/n V…

字符设备驱动基础1——简单的驱动源代码分析

以下内容源于朱有鹏嵌入式课程的学习&#xff0c;如有侵权请告知删除。 参考博客&#xff1a;linux驱动开发&#xff08;一&#xff09; - biaohc - 博客园 一、驱动源代码示例 /********module_test.c代码*********/#include <linux/module.h> // module_init module…

字符设备驱动基础3——使用register_chrdev()函数注册字符设备

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、系统工作原理 1、工作流程 系统的整体工作流程是&#xff1a;应用层—>API—>设备驱动—>硬件。 操作系统提供的API包括open、read、write、close等函数&#xff0c;它们只是一种操作逻…

win7在未关闭vmware情况下直接关机,导致虚拟机无法克隆

今天有点小激动啊&#xff0c;着急关机&#xff0c;结果发现重启之后的虚拟机不能进行克隆操作。系统提示如下&#xff1a;the Specific Virtual Disk Needs Repair .查询“度娘”&#xff0c;突然看到一篇文章说&#xff0c;删除这啊&#xff0c;修改那的....特别复杂&#xf…

hdu 1159(最长公共子序列)

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1159 思路&#xff1a;dp[i][j]表示s1从0~i-1,s2从0~j-1的最长公共子序列&#xff1b; 递推方程为&#xff1a;dp[i][j](s1[i-1]s2[j-1])?d[i-1][j-1]1:max(dp[i-1][j],dp[i][j-1]); View Code 1 #include<…

mysql applier_MySQL推出Applier,可实时复制数据到Hadoop-阿里云开发者社区

http://labs.mysql.comMySQL复制操作可以将数据从一个MySQL服务器(主)复制到其他的一个或多个MySQL服务器(从)。试想一下&#xff0c;如果从服务器不再局限为一个MySQL服务器&#xff0c;而是其他任何数据库服务器或平台&#xff0c;并且复制事件要求实时进行&#xff0c;是否可…

字符设备驱动基础4——读写接口的操作实践

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、细节提要 1、与用户与内核数据交换有关的函数 &#xff08;1&#xff09;copy_from_user()函数 该将数据从用户空间复制到内核空间。 如果成功复制则返回0&#xff0c;如果不成功复制则返回尚未…

mysql分区表mycat_MySQL 中间件之Mycat垂直分表配置

垂直分表就是将一个库下的多个表拆分到多个MySQL实例&#xff0c;实现库压力分流。通过GTID模式复制&#xff0c;db01与db02之间不进行任何连接与复制当前环境&#xff1a;mycat --> db01与db02db01 --> db03db02 --> db04当前垂直分表架构&#xff1a;后端数据库创建…

深入浅出mysql gtid_深入理解MySQL GTID

GTID的概念何为GITDGTID(global transaction identifier)是全局事务标识符&#xff0c;在MySQL5.6版本中作为一个超级特性被推出。事务标识不仅对于Master(起源)的服务器来说是惟一的&#xff0c;而且在整个复制拓扑架构来说&#xff0c;也是全局唯一的。1.GTID的格式GTID sou…