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 ...
随机推荐
- vsftpd文件服务器安装与配置
-d<登入目录>:指定用户登入时的启始目录:. -s<shell>:指定用户登入后所使用的shell: /sbin/nologin指的是不允许login当前Linux系统.当用 ...
- 日志汇总:logging、logger
目录 1.日志输出到文件 2.日志输出到屏幕 3.设置输出等级 4.设置多个日志输出对象 5.日志的配置 6.记录异常 7.设置日志输出样式 1.日志输出到文件basicConfig()提供了非常便捷 ...
- Jenkins的持续集成
持续集成:不需要人工干预,持久化.重复的运行一个任务.将代码自动的更新到最新,然后自动运行. 新建项目之前要再Jenkins的全局工具配置里面把git的路径设置好.[全局工具配置]-->[Git ...
- Mybatis怎么在mapper中用多个参数
原文地址:https://github.com/mybatis/mybatis-3/wiki/FAQ How do I use multiple parameters in a mapper? Jav ...
- HDU1757:A Simple Math Problem(矩阵快速幂)
http://acm.hdu.edu.cn/showproblem.php?pid=1757 Problem Description Lele now is thinking about a simp ...
- 19重定向管道与popen模型
重定向 dup2 int dup(int fd) 重定向文件描述符 int newFd = dup(STDOUT_FILENO) newFd 指向 stdout int dup2(int fd1, ...
- python webdriver 测试框架-数据驱动json文件驱动的方式
数据驱动json文件的方式 test_data_list.json: [ "邓肯||蒂姆", "乔丹||迈克尔", "库里||斯蒂芬", & ...
- bzoj1606 / P2925 [USACO08DEC]干草出售Hay For Sale(01背包)
P2925 [USACO08DEC]干草出售Hay For Sale 简化版01背包(连价值都免了) 直接逆推解决 #include<iostream> #include<cstdi ...
- 使用索贝尔(Sobel)进行梯度运算时的数学意义和代码实现研究
对于做图像处理的工程师来说,Sobel非常熟悉且常用.但是当我们需要使用Sobel进行梯度运算,且希望得到“数学结果”(作为下一步运算的基础)而不是“图片效果”的时候,就必须深入了解Sobel的知识原 ...
- 模块的封装之C语言类的继承和派生
[交流][微知识]模块的封装(二):C语言的继承和派生 在模块的封装(一):C语言的封装中,我们介绍了如何使用C语言的结构体来实现一个类的封装,并通过掩码结构体的方式实 现了类成员的保护.这一部分,我 ...