设为首页 收藏本站
查看: 524|回复: 0

[经验分享] PHP共享内存的应用shmop系列

[复制链接]

尚未签到

发表于 2017-4-3 07:20:13 | 显示全部楼层 |阅读模式
  简单的说明
  可能很少情况会使用PHP来操控共享内存,一方面在内存的控制上,MC已经提供了一套很好的方式,另一方面,自己来操控内存的难度较大,内存的读写与转存,包括后面可能会用到的存储策略,要是没有一定计算机组成原理的基础,想做这些不是一件容易的事情。那为什么还要使用它呢?如果我想进行管道通信,为其它的应用服务准备数据;我想建立自己的数据缓存体系,使用MC有点大炮打苍蝇的感觉。那么shmop会是一个选择,当然,在操作内存前,一定要谨慎。
  系统要求
  shmop系列函数只是在unix/Linux下可用,可以通过命令:
  ipcs -m
DSC0000.gif

  来查看当前的共享内存使用情况。其中,各个部分解释如下:
  key :共享内存的唯一的key值,共享内存通过该key来判断你读取的是哪一块内存。
  shmid:当使用key来获取内存时,你获得的是这个id的值。它作为你操作内存块的标识。
  owner:创建该共享内存块的用户
  perms:该共享内存的读写权限,8禁止,可以是777,与文件的读写权限一致。
  bytes:该内存块的大小
  nattch:连接该内存块的进程数
  status:当前状态,如:dest,即将删除等。
  使用示例
  具体的使用说明,在PHP手册中有详细介绍,这里不进行赘述。这里将写一些简单的操作例子。
  写入
  <?php/*** SHMOP共享内存操作示例* @author monkee**/$key = 0x4337b700;$size = 4096;$shmid = @shmop_open($key, 'c', 0644, $size);if($shmid === FALSE){exit('shmop_open error!');}$data = '世界,你好!我将写入很多的数据,你能罩得住么?';$length = shmop_write($shmid, pack('a*',$data), 0);if($length === FALSE){exit('shmop_write error!');}@shmop_close($shmid);exit('succ');?>
  

读取  <?php/*** SHMOP共享内存操作示例* @author monkee**/$key = 0x4337b700;$size = 256;$shmid = @shmop_open($key, 'c', 0644, $size);if($shmid === FALSE){exit('shmop_open error!');}$data = unpack('a*', shmop_read($shmid, 0, 256));if($data === FALSE){exit('shmop_read error!');}@shmop_close($shmid);exit($data[1]);?>
这里使用到了函数:pack() 这个函数用来将内存里的内容转化为二进制内容,具体请查看手册内容。
  多服务器内存同步
  已经在本地做好了这个服务,现在需要在多台服务器上进行内存数据同步。虽然这个时候可以放弃共享内存的方式来处理数据了,然而你被要求需要这么做。于是,同步我想不是问题,做好“主-从”的架构,我同步好的内存及时推送过去就可以了。然而,我是不是需要在从机上做一个监听程序呢?这样的代价有点大,好的一点是,从机上有apache。也就是说可以使用HTTP协议来进行通信了。
  同步策略
  如何同步?看似无聊的问题,却又产生了疑惑。同步数据呗,但是同步什么数据!一种方式是主机的内存改变后,程序读取所有内存数据然后发送到从机进行同步;如果我只是更改一些简单的操作位的话,那么小的更新却要引起整个内存块的同步,似乎有些浪费。还有一种,是更新变化。将变化进行更新。这种比较复杂,因为你需要定义每一种操作的处理。幸运的是,你需要操作的数据并不多,还有,你要定义的操作也不多:write,delete(read可以不要,因为你很少会从从机上读取数据)。那么好了,我们选择其中一种来做吧。
  主机发送
  <?php/** * 共享内存操作,支持远程内存同步。* @author hufeng@* @since 2011-08-10**/define('PSHMOP_HOST', '192.168.0.1'); define('PSHMOP_SEPE', "\r\n----------CKSJFIOWKJDFOCKJVNBBSDF----------\r\n");class Pshmop {static private $data = array();static public function write($key, $offset, $data, $size = 0){ $h = array('key' => $key, 'offset' => $offset, 'size' => $size, 'ac' => 'write'); return self::add($h, $data); } static public function del($key){ $h = array('key' => $key, 'ac' => 'delete'); return self::add($h); }static private function add($dataheader, $databody=''){self::$data[] = serialize($dataheader)."\n".$databody; }static private function send(){ $d = & self::$data;if(count($d) == 0){return ; }$http_entity_body = join(PSHMOP_SEPE, $d);$http_entity_length = strlen($http_entity_body);$fp = fsockopen(PSHMOP_HOST, 80, $errno, $error); if(!$fp){ return -1; } fputs($fp, "PUT /pshmop.php HTTP/1.1\r\n"); fputs($fp, 'Host: '.PSHMOP_HOST."\r\n"); fputs($fp, "Content-Type: application/x-www-form-urlencoded\r\n"); fputs($fp, "Content-Length: {$http_entity_length}\r\n"); fputs($fp, "Connection: close\r\n\r\n"); fputs($fp, $http_entity_body . "\r\n\r\n"); $d = ''; while(!feof($fp)){ $d .= fgets($fp, 4096); } fclose($fp); return $d; } }
使用的时候,进行:
  Pshmop::write();Pshmop::write();Pshmop::write();Pshmop::send();
PS:为了支持多个更新一次传递的原则,以上便是举例。
  从机监听
  <?php/*** 共享内存远程处理类* 对从远端传输到的数据进行处理、内存同步更新* @author hufeng@* @since 2011-08-11**/define('RSHMOP_SEPE', "\r\n----------CKSJFIOWKJDFOCKJVNBBSDF----------\r\n");class Rshmop{static public function run($data){$items = @explode(RSHMOP_SEPE, $data);if($items === NULL){return -1;}$result = array('succ' => 0, 'error' => 0);foreach($items as $k => $i){self::op($i) === 0 ? $result['succ']++ : $result['error']++;unset($items[$k]);}return $result;}static public function op($str){$p = strpos($str, "\n");$header = @unserialize(substr($str, 0, $p));if($header === FALSE){return 'Data Format Error!';}$body = substr($str, $p+1);$shmid = null;if($header['size'] > 0){$shmid = @shmop_open($header['key'], 'c', 0644, $header['size']);}if(!$shmid){$cmd = "ipcs -m | grep '{$header['key']}'";$em = exec($cmd);$em = preg_replace('/ +/', ' ', $em);$ems = explode(' ', $em);$header['size'] = intval($ems[4]);if($header['size'] == 0){if($headerreturn ['ac'] == 'delete'){return 0;}else{return 'Param `size` required!';}}$shmid = @shmop_open($header['key'], 'c', 0644, $header['size']);}if($header['ac'] == 'write'){shmop_write($shmid, $body, $header['offset']);}if($header['ac'] == 'delete'){shmop_delete($shmid);}shmop_close($shmid);return 0;}}
如果遇到主机有而从机未有的数据块(可能由网络问题造成,也可以有其它解决办法),可以选择delete然后再进行其它操作。
  缓存使用的策略
  觉得使用MC代价有点高,可以自己来控制内存和使用。当然,小部分的数据可以容易使用,但是当数据多的时候,决定哪部分数据进入内存,哪部分数据进入硬盘都是值得商榷的。这也就是为什么要提策略。
  常见的策略无非是 FIFO,LUR,LAR等,但并不是说这些策略就是好的。实际情况中,根据具体的业务需求,来组织相应的策略。最常见的,我们是将从数据库查询时间长的、获取数据耗时(从其它机器上获取)、计算耗时的、需要及时使用的放入内存中。
  这部分的代码就不写了,希望有所帮助。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-359334-1-1.html 上篇帖子: 轻松理解PHP JAVA MVC 设计模式 下篇帖子: 初学PHP时的知识积累
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表