海运的博客

PHP进程间通信System V消息队列

发布时间:January 9, 2014 // 分类:PHP // No Comments

多进程:

<?php
   //生成key
   $message_queue_key = ftok(__FILE__, 'a');
   //根据生成的key新建队列,也可自定,如123456
   $message_queue = msg_get_queue($message_queue_key, 0666);

   $pids = array();
   for ($i = 0; $i < 5; $i++) {
      //创建子进程
      $pids[$i] = pcntl_fork();

      if ($pids[$i]) {
         echo "No.$i child process was created, the pid is $pids[$i]\r\n";
         pcntl_wait($status);//非阻塞的线程等待,防止僵尸进程的出现
      } elseif ($pids[$i] == 0) {
         $pid = posix_getpid();
         echo "process.$pid is writing now\r\n";
         //写队列
         msg_send($message_queue, 1, "this is process.$pid's data\r\n");
         posix_kill($pid, SIGTERM);
      }
   }

   do {
      //读队列
      msg_receive($message_queue, 0, $message_type, 1024, $message, true, MSG_IPC_NOWAIT);
      echo $message;
      //获取队列内消息数
      $a = msg_stat_queue($message_queue);
      if($a['msg_qnum'] == 0){
         break;
      }
   } while(true)
?>

父子进程:

<?php
   $message_queue_key = ftok(__FILE__, 'a');
   $message_queue = msg_get_queue($message_queue_key, 0666);
   $pid = pcntl_fork();
   if ($pid==-1) {
      die("cannot fork");
   } else if ($pid) { //父进程
      pcntl_wait($status);
      msg_receive($message_queue, 0, $message_type, 1024, $message, true, MSG_IPC_NOWAIT);
      echo $message;

   } else {
      $pid = posix_getpid(); //子进程
      msg_send($message_queue, 1, "this is process.$pid's data\r\n");
   }
?>

Tokyo Cabinet表格型数据结构

发布时间:January 8, 2014 // 分类:NoSQL // No Comments

Tokyo Cabinet支持Table数据结构,类似于SQL,可按条件查找索引,记录下:

#新建数据库,实际上类似于SQL表
tctmgr create user.tct
#key1为主健,name和passwd为字段
tctmgr put user.tct key1 "name" "u1" "passwd" "123"
#列出当前表数据
tctmgr list -pv user.tct
#按字段查找,类似于select * from where name = u1 limit 15;
tctmgr search -pv -m 15 user.tct name STREQ "u1" 
#建立索引
tctmgr setindex user.tct name

PHP接口:

<?php
   $tt = new TokyoTyrantTable("localhost", 1978);
   $query = $tt->getQuery();

   $query->addCond("name", TokyoTyrant::RDBQC_STREQ, "u1")->setLimit(5, 5);
   var_dump($query->search());
?>

Kyoto Cabinet和LevelDB实现任务队列

发布时间:January 7, 2014 // 分类:消息队列 // No Comments

根据Tokyo Tyrant自带的Lua队列脚本修改,Kyoto Cabinet和Tokyo Tyrant的API有很大不同。

kt = __kyototycoon__
db = kt.db

-- 记录日志
if kt.thid == 0 then
   kt.log("system", "the Lua script has been loaded")
end

-- 入队列
function enqueue(inmap, outmap)
   local key = inmap.key
   local value = inmap.value
   --队列值自增1,空从0开始
   local id = db:increment_double(key, 1)
   if not id then
      return kt.RVEINTERNAL 
   end 
   key = string.format("%s-%012d", key, id)
   if not db:add(key, value) then
      return kt.RVEINTERNAL
   end
   outmap[key] = "ok"
   return kt.RVSUCCESS
end

-- 出队列
function dequeue(inmap, outmap)
   local key = inmap.key
   local max = inmap.max
   max = tonumber(max)
   if not max or max < 1 then
      max = 1
   end
   key = string.format("%s-", key)
   --匹配队列前缀,返回多个匹配的key
   local keys = db:match_prefix(key, max)
   local res = ""
   for i = 1, #keys do
      local key = keys[i]
      local value = db:get(key)
      if db:remove(key) and value then
         --要返回的结果
         outmap[keys[i]] = value
      end
   end
   return kt.RVSUCCESS
end

-- 查看队列大小
function queuesize(inmap, outmap)
   local key = inmap.key
   key = string.format("%s-", key)
   local keys = db:match_prefix(key)
   outmap.size = #keys
   return kt.RVSUCCESS
end

-- 重置队列ID从0开始 
function queuereset(inmap, outmap)
   local key = inmap.key
   if not key then
      return kt.RVEINVALID
   end
   if not db:remove(key) then
      local err = db:error()
      if err:code() == kt.Error.NOREC then
         return kt.RVELOGIC
      end
      return kt.RVEINTERNAL
   end
   return kt.RVSUCCESS
end

使用:

ktremotemgr script -host 192.168.1.3 -port 1978 enqueue key queue value value1
ktremotemgr script -host 192.168.1.3 -port 1978 dequeue key queue max 10
curl "http://192.168.1.3:1978/rpc/play_script?name=enqueue&_key=queue&_value=value1"
curl "http://192.168.1.3:1978/rpc/play_script?name=dequeue&_key=queue&_max=10"

Tokyo Tyrant和Tokyo Cabinet实现任务队列

发布时间:January 7, 2014 // 分类:消息队列 // No Comments

Tokyo Tyrant官方提供的Lua脚本扩展:

-- 入队列
function enqueue(key, value)
   --通过队列名为key记录入队列的尾部,自加1为当次入队列的起始ID
   local id = _adddouble(key, 1)
   if not id then
      return nil
   end
   --队列key格式为队列名称\t加12位数字
   key = string.format("%s\t%012d", key, id)
   if not _putkeep(key, value) then
      return nil
   end
   return "ok"
end

-- 出队列
function dequeue(key, max)
   max = tonumber(max)
   if not max or max < 1 then
      max = 1
   end
   key = string.format("%s\t", key)
   --匹配队列前缀,返回匹配的多个key
   local keys = _fwmkeys(key, max)
   local res = ""
   for i = 1, #keys do
      local key = keys[i]
      local value = _get(key)
      --删除要出队列的key并返回队列值
      if _out(key) and value then
         res = res .. value .. "\n"
      end
   end
   return res
end

-- 查看队列大小
function queuesize(key)
   key = string.format("%s\t", key)
   local keys = _fwmkeys(key)
   //队列数组大小
   return #keys
end
tcrmgr ext -port 1978 127.0.0.1 enqueue myqueue value1
tcrmgr ext -port 1978 127.0.0.1 dequeue myqueue 10

通过TT入队列:

<?php
   function dequeue(){
      $tt = new TokyoTyrant("localhost", '1978');   
      $content = $tt -> ext('dequeue', '0', 'queue', 10);
      $content = preg_split('/\n/', $content, -1, PREG_SPLIT_NO_EMPTY);
      return $content;
   }
   //队列名称
   $file = 'file.csv';
   $queuename = 'queue';
   $tt = new TokyoTyrant("localhost", '1978');   
   $content = file_get_contents($file);
   $content = preg_split('/\n/', $content, -1, PREG_SPLIT_NO_EMPTY); //分割字符串为数组
   //队列开始ID
   //print_r($content);
   foreach($content as $key => $value)  
   {
      if ($key !== '')  
      {
         $tmpvalue = explode(',',$value);
         preg_match_all("/[0-9]{1}/", $tmpvalue[0], $arrNum, PREG_SET_ORDER);
         if (count($arrNum) > 8)
         {
            $tt->ext('enqueue','0', $queuename, $value );
            //echo $value."\n";
         }
      }
   }
?>

大数据通过TC PHP扩展入队列:

<?php
   //队列名称
   $file = 'file.txt';
   $queuename = 'queue';
   $db = new TCHDB();
   $db->open('/var/queue/db.tch', TCHDB::OWRITER | TCHDB::OCREAT);
   $content = file_get_contents($file);
   $content = preg_split('/\n/', $content, -1, PREG_SPLIT_NO_EMPTY); //分割字符串为数组
   //队列开始ID
   $id = 1;
   //print_r($content);
   foreach($content as $key => $value)  
   {
      if ($key !== '')  
      {
         $id = sprintf('%012d', $id);
         //echo $key.$value."\n";
         $db->put("$queuename-$id", $value);
         $id++;
      }
   }
   $db->out($queuename);
?>

NoSQL持久化存储之Kyoto Cabinet

发布时间:January 6, 2014 // 分类:NoSQL // No Comments

安装Kyoto Cabinet:

yum install gcc gcc-c++ zlib-devel bzip2-devel
wget http://fallabs.com/kyotocabinet/pkg/kyotocabinet-1.2.76.tar.gz
tar zxvf kyotocabinet-1.2.76.tar.gz 
cd kyotocabinet-1.2.76
./configure --prefix=/usr/local/kyotocabinet-1.2.76
make && make install
echo "/usr/local/kyotocabinet-1.2.76/lib/" >> /etc/ld.so.conf.d/kyoto.conf 
ldconfig

安装Lua Kyoto Cabinet扩展:

yum install lua-devel
wget http://fallabs.com/kyotocabinet/luapkg/kyotocabinet-lua-1.28.tar.gz
tar zxvf kyotocabinet-lua-1.28.tar.gz 
cd kyotocabinet-lua-1.28
./configure --with-kc=/usr/local/kyotocabinet-1.2.76/
make && make install

安装Kyoto Tycoon:

wget http://fallabs.com/kyototycoon/pkg/kyototycoon-0.9.56.tar.gz
tar zxvf kyototycoon-0.9.56.tar.gz 
cd kyototycoon-0.9.56
./configure --prefix=/usr/local/kyototycoon-0.9.56 --with-kc=/usr/local/kyotocabinet-1.2.76/ --enable-lua
make && make install
mkdir /etc/ktserver/
cp example/*.lua /etc/ktserver/
echo "/usr/local/kyototycoon-0.9.56/lib/" >> /etc/ld.so.conf.d/kyoto.conf 
ldconfig

使用Kyoto Tycoon为前端管理LevelDB,先安装LevelD存储:然后安装Kyoto Tycoon插件支持LevelDB:

cd lab/leveldb/
export CPLUS_INCLUDE_PATH=/usr/local/kyotocabinet-1.2.76/include/
export LIBRARY_PATH=/usr/local/kyotocabinet-1.2.76/lib
make
cp ktplugdblevel.so /usr/local/kyototycoon-0.9.56/lib/

启动:

ktserver -th 4 -scr /etc/ktserver/ktscrex.lua -pldb /usr/local/kyototycoon-0.9.56/lib/ktplugdblevel.so \
/tmp/leveldb/#ktopts=p

使用HTTP协议管理:

curl "http://192.168.1.3:1978/rpc/set?key=japan&value=tokyo" 
curl "http://192.168.1.3:1978/rpc/get?key=japan" 
curl "http://192.168.1.3:1978/rpc/remove?key=japan" 

使用客户端管理:

ktremotemgr set -host 192.168.1.3 -port 1978 key value
ktremotemgr get -host 192.168.1.3 -port 1978 key
ktremotemgr list -host 192.168.1.3 -port 1978 -pv

使用Kyoto Tycoon管理LevelDB兼容于直接使用LevelDB PHP扩展设置的数据库,启动时添加参数:

#ktopts=p

使用Kyoto Tycoon Lua脚本,API:http://fallabs.com/kyototycoon/luadoc/modules/kyototycoon.html

ktremotemgr script -host 192.168.1.3 -port 1978 set key key1 value value1
ktremotemgr script -host 192.168.1.3 -port 1978 get key key1
curl "http://192.168.1.3:1978/rpc/play_script?name=set&_key=key1&_value=value1"
curl "http://192.168.1.3:1978/rpc/play_script?name=get&_key=key1"
分类
最新文章
最近回复
  • opnfense: 谢谢博主!!!解决问题了!!!我之前一直以为内置的odhcp6就是唯一管理ipv6的方式
  • liyk: 这个方法获取的IPv6大概20分钟之后就会失效,默认路由先消失,然后Global IPV6再消失
  • 海运: 不好意思,没有。
  • zongboa: 您好,請問一下有immortalwrt設定guest Wi-Fi的GUI教學嗎?感謝您。
  • 海运: 恩山有很多。
  • swsend: 大佬可以分享一下固件吗,谢谢。
  • Jimmy: 方法一 nghtp3步骤需要改成如下才能编译成功: git clone https://git...
  • 海运: 地址格式和udpxy一样,udpxy和msd_lite能用这个就能用。
  • 1: 怎么用 编译后的程序在家里路由器内任意一台设备上运行就可以吗?比如笔记本电脑 m参数是笔记本的...
  • 孤狼: ups_status_set: seems that UPS [BK650M2-CH] is ...
归档