Cache应用/任务Mutex,用于高并发任务处理经过多个项目使用
<?php
/**
* Class Cache redis 用于报表的缓存基本存储和读写 2.0
* <pre>
* Cache::read("diamond.account",$nick);
* Cache::readSync("diamond.account",$nick);
* $finder = Cache::createFinder("diamond.account",$nick);
* $finder->read();
* $finder->readSync();
*
* Cache::save("diamond.account",$nick,$data);
* $storage = Cache::createStorage("diamond.account",$nick);
* $storage->save($data);
* $storage->save($data,7200);
* </pre>
* @category cache
* @package cache
* @author oShine <oyjqdlp@126.com>
* @version 2.0.0.0
* @copyright oShine 2015/08/07
*/
class Cache { /**
* 非安全读取的数据
* @param $key
* @param string $nick
* @return array|null
*/
public static function read($key,$nick = "sys"){
$finder = self::createFinder($key,$nick);
return $finder->read();
} /**
* 同步读取数据
* @param $key
* @param string $nick
* @return mixed
*/
public static function readSync($key,$nick = "sys"){
$finder = self::createFinder($key,$nick);
return $finder->readSync();
} /**
* 创建Finder
* @param $key
* @param string $nick
* @return Finder
*/
public static function createFinder($key,$nick = "sys"){
$key = Generate::key($key,$nick);
return new Finder($key);
} /**
* 创建Storage
* @param $key
* @param string $nick
* @return Storage
*/
public static function createStorage($key,$nick = "sys"){
$key = Generate::key($key,$nick);
return new Storage($key);
} /**
* 保存数据
* @param $key
* @param string $nick
* @param array $data
* @param int $expired
* @return bool
*/
public static function save($key,$nick = "sys",$data = array(),$expired=7200){
$storage = self::createStorage($key,$nick);
return $storage->save($data,$expired);
} /**
* @param string $nick
*/
public static function clear($nick = "sys"){
$redis = CacheFactory::create();
$redis->del($redis->keys(md5($nick).".data.*"));
} } /**
* Class Finder 数据读取
* @category cache
* @package cache
* @author oShine <oyjqdlp@126.com>
* @version 2.0.0.1
* @copyright oShine 2015/08/07
*/
class Finder { /**
* @var string $key
*/
public $key; /**
* @param string $key
*/
public function __construct($key){
$this->key = $key;
} /**
* 非安全读取数据
* @return mixed
*/
public function read(){
$data = $this->readData();
if($data->isRead === true && !$data->isExpired()) {
return json_decode(json_encode($data->data), true);
}
return null;
} /**
* @return Data
*/
protected function readData(){
$redis = CacheFactory::create();
$rptData = new Data();
$data = json_decode($redis->get($this->key));
if(false == $data){
$rptData->isRead = false;
$rptData->expiredTime = time();
$rptData->expired = 24*3600;
}else{
$rptData->expired = $data->expired;
$rptData->isRead = isset($data->isRead) && $data->isRead === true?true:false;
$rptData->expiredTime = $data->expiredTime;
$rptData->data = $data->data;
}
return $rptData;
} /**
* 同步读取数据
* @return mixed
*/
public function readSync(){
while(true){
$rptData = $this->readData();
if($rptData->isRead && !$rptData->isExpired())
return $this->read();
sleep(1);
}
}
} /**
* Class Storage 数据存储
* @category cache
* @package cache
* @author oShine <oyjqdlp@126.com>
* @version 2.0.0.0
* @copyright oShine 2015/08/07
*/
class Storage { /**
* @var string key
*/
public $key; /**
* @param string $key
*/
public function __construct($key){
$this->key = $key;
} /**
* @return bool
*/
public function flush(){
$rptData = new Data();
$rptData->data = null;
$rptData->expiredTime = time();
$rptData->isRead = false;
$rptData->expired = 1;
$redis = CacheFactory::create(); return $redis->setex($this->key, $rptData->expired,json_encode($rptData));
} /**
* 写入数据
* @param $data
* @param int $expired
* @return bool
*/
public function save($data,$expired=7200){ $rptData = new Data();
$rptData->data = $data;
$rptData->expiredTime = time();
$rptData->isRead = true;
$rptData->expired = $expired;
$redis = CacheFactory::create(); return $redis->setex($this->key, $rptData->expired,json_encode($rptData));
}
} /**
* Class Data redis存储数据实体
* @category cache
* @package cache
* @author oShine <oyjqdlp@126.com>
* @version 2.0.0.0
* @copyright oShine 2015/08/07
*/
class Data {
/**
* @var int $expired 失效间隔时长
*/
public $expired;
/**
* @var int
*/
public $expiredTime;
/**
* @var mixed 存储的具体数据
*/
public $data;
/**
* @var bool 是否可以读取
*/
public $isRead; /**
* 是否失效
* @return bool
*/
public function isExpired(){
if(time()-$this->expiredTime > $this->expired)
return true;
return false;
}
} /**
* Class Generate key生成
* @category cache
* @package cache
* @author oShine <oyjqdlp@126.com>
* @version 2.0.0.0
* @copyright oShine 2015/08/07
*/
class Generate {
/**
* @static
* @param $key
* @param $nick
* @return string
*/
public static function key($key,$nick){
return md5($nick).".data.".$key;
}
}
CacheFactory:
<?php
/**
* @category cache
* @package cache
* @author oShine <oyjqdlp@126.com>
* @version 2.0.0.0
* @copyright oShine 2015/08/07
*/
class CacheFactory { /**
* @var Redis $instance
*/
private static $instance = null; /**
* @return Redis
*/
public static function create(){ if(self::$instance == null){
self::$instance = new Redis();
self::$instance->connect(Yii::app()->params["RedisServerIP"]);
}else{
try{
if(preg_match("/PONG/",self::$instance->ping())){
return self::$instance;
}
}catch (Exception $e){
self::$instance = new Redis();
self::$instance->connect(Yii::app()->params["RedisServerIP"]);
}
}
return self::$instance; } }
Mutex:用于任务锁,辅助任务处理,使用Cache记录任务状态,告别表锁任务标记
<?php /**
* Class Mutex 用于任务锁
* @category mutex
* @package cache
* @author oShine <oyjqdlp@126.com>
* @version 2.0.0.0
* @copyright oShine 2015/08/07
* @example
* Mutex::create($nick)->init("download")->wait()
* Mutex::create($nick)->init("download")->doing()
* Mutex::create($nick)->init("download")->done()
* Mutex::create($nick)->init("download")->error()
*/
class Mutex { /**
* @var string
*/
private $nick; /**
* @param string $nick
*/
public function __construct($nick){
$this->nick = $nick;
} /**
* @param $nick
* @return Mutex
*/
public static function create($nick){
return new self($nick);
} /**
* @param $nick
*/
public static function clear($nick){
$redis = CacheFactory::create();
$redis->del($redis->keys(md5($nick).".mutex.*"));
} /**
* @param $key
* @return MutexStorage
*/
public function init($key){
$key = md5($this->nick).".mutex.".$key;
return new MutexStorage($key, CacheFactory::create());
} } /**
* Class MutexStorage
* @category mutex
* @package cache
* @author oShine <oyjqdlp@126.com>
* @version 2.0.0.0
* @copyright oShine 2015/08/07
*/
class MutexStorage { private $key; /**
* @var Redis $redis
*/
private $redis; public function __construct($key,$redis){
$this->key = $key;
$this->redis = $redis;
} /**
* @return $this
* @throws Exception
*/
public function wait(){
$this->save("WAIT");
return $this;
} /**
* @return $this
* @throws Exception
*/
public function doing(){
$this->save("DOING");
return $this;
} /**
* @return $this
* @throws Exception
*/
public function done(){
$this->save("DONE");
return $this;
} /**
* @return $this
* @throws Exception
*/
public function error(){
$this->save("ERROR");
return $this;
} /**
* @param $data
* @return $this
* @throws Exception
*/
protected function save($data){ $data = json_encode(array("status"=>$data,"date"=>date("Y-m-d"),"timestamp"=>time())); $flag = $this->redis->setex($this->key,3*24*2400,$data);
if(!$flag)
throw new Exception("SAVE Error!");
return $this;
} /**
* @return string|null
*/
protected function get(){ $data = json_decode($this->redis->get($this->key),true);
if(strtotime(date("Y-m-d")) == strtotime($data["date"])){
return $data["status"];
}
return null;
} /**
* @return bool
*/
public function isDoing(){
$data = json_decode($this->redis->get($this->key),true);
if(isset($data) && isset($data["status"]) && $data["status"] == "DOING" && isset($data["timestamp"]) && (time()-$data["timestamp"])<60)
return true;
return false;
} /**
* @return bool
*/
public function isDone(){
$status = $this->get();
if(isset($status) && $status == "DONE")
return true;
return false;
} /**
* @return bool
*/
public function isError(){
$status = $this->get();
if(isset($status) && $status == "ERROR")
return true;
return false;
}
}
Cache应用/任务Mutex,用于高并发任务处理经过多个项目使用的更多相关文章
- Memcache的mutex设计模式 -- 高并发解决方案
场景 Mutex主要用于有大量并发访问并存在cache过期的场合,如 首页top 10, 由数据库加载到memcache缓存n分钟: 微博中名人的content cache, 一旦不存在会大量请求不能 ...
- 同样是高并发,QQ/微博/12306的架构难度一样吗?
开篇 同一个用户并发扣款时,有一定概率出现数据不一致,可以使用CAS乐观锁的方式,在不降低吞吐量,保证数据的一致性: UPDATE t_yue SET money=$new_money WHERE u ...
- java-spring基于redis单机版(redisTemplate)实现的分布式锁+redis消息队列,可用于秒杀,定时器,高并发,抢购
此教程不涉及整合spring整合redis,可另行查阅资料教程. 代码: RedisLock package com.cashloan.analytics.utils; import org.slf4 ...
- Linux epoll 笔记(高并发事件处理机制)
wiki: Epoll优点: Epoll工作流程: Epoll实现机制: epollevent; Epoll源码分析: Epoll接口: epoll_create; epoll_ctl; epoll_ ...
- 高并发网络编程之epoll详解
select.poll和epoll的区别 在linux没有实现epoll事件驱动机制之前,我们一般选择用select或者poll等IO多路复用的方法来实现并发服务程序.在大数据.高并发.集群等一些名词 ...
- Springcloud 微服务 高并发(实战1):第1版秒杀
疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列之15 [博客园总入口 ] 前言 前言 疯狂创客圈(笔者尼恩创建的高并发研习社群)Springcloud 高并发系列文章,将为大家介绍三个版 ...
- java之高并发与多线程
进程和线程的区别和联系 从资源占用,切换效率,通信方式等方面解答 线程具有许多传统进程所具有的特征,故又称为轻型进程(Light—Weight Process)或进程元:而把传统的进程称为重型进程(H ...
- 一篇博客带你轻松应对java面试中的多线程与高并发
1. Java线程的创建方式 (1)继承thread类 thread类本质是实现了runnable接口的一个实例,代表线程的一个实例.启动线程的方式start方法.start是一个本地方法,执行后,执 ...
- Java高并发系列——检视阅读
Java高并发系列--检视阅读 参考 java高并发系列 liaoxuefeng Java教程 CompletableFuture AQS原理没讲,需要找资料补充. JUC中常见的集合原来没讲,比如C ...
随机推荐
- centos 正则,grep,egrep,流式编辑器 sed,awk -F 多个分隔符 通配符 特殊符号. * + ? 总结 问加星 cat -n nl 输出文件内容并加上行号 alias放~/.bash_profile 2015-4-10 第十三节课
centos 正则,grep,egrep,流式编辑器 sed,awk -F 多个分隔符 通配符 特殊符号. * + ? 总结 问加星 cat -n nl 输出文件内容并加上行号 alias放~ ...
- [py]python中__new__作用
元类metaclass 使劲搞,但是没搞清楚__new__的作用 了解Python元类 Python进阶:一步步理解Python中的元类metaclass Python中的__new__和__init ...
- HDU2426:Interesting Housing Problem(还没过,貌似入门题)
#include <iostream> #include <queue> #include <stdio.h> #include <string.h> ...
- [华为]输出单向链表中倒数第k个结点
输入一个单向链表,输出该链表中倒数第k个结点,链表的倒数第1个结点为链表的尾指针. 链表结点定义如下: struct ListNode { int m_nKey; ListNode* m_ ...
- 史上最全的MonkeyRunner自动化测试从入门到精通(3)
原文地址https://blog.csdn.net/liu_jing_hui/article/details/60956088 MonkeyRunner复杂的功能开始学习 (1)获取APK文件中ID的 ...
- 微博开源框架Motan初体验
前两天,我在开源中国的微信公众号看到新浪微博的轻量Rpc框架--Motan开源了.上网查了下,才得知这个Motan来头不小,支撑着新浪微博的千亿调用,曾经在2014年的春晚中有着千亿次的调用,对抗了春 ...
- 妙用Excel数据透视表和透视图向导,将二维数据转换为一维数据
项目中,每年都会有各种经销商的各种产品目标数据导入,经销商和产品过多,手工操作过于单调和复杂.那有没有一种方式可以将复杂的二维数据转换为一维数据呢? 有,强大的Excel就支持此功能. 常用Excel ...
- jvm之gc日志
ava GC日志可以通过 +PrintGCDetails开启 以ParallelGC为例 YoungGC日志解释如下 FullGC:
- db2,oracle,mysql ,sqlserver限制返回的行数
不同数据库限制返回的行数的关键字如下: ①db2 select * from table fetch first 10 rows only; ②oracle select * from table w ...
- Vue学习笔记之Vue的对象单体模式
0x00 对象的单体模式 为了解决箭头函数this指向的问题 推出来一种写法 对象的单体模式 var person = { name:'小马哥', age:12, fav(){ console.log ...