<?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,用于高并发任务处理经过多个项目使用的更多相关文章

  1. Memcache的mutex设计模式 -- 高并发解决方案

    场景 Mutex主要用于有大量并发访问并存在cache过期的场合,如 首页top 10, 由数据库加载到memcache缓存n分钟: 微博中名人的content cache, 一旦不存在会大量请求不能 ...

  2. 同样是高并发,QQ/微博/12306的架构难度一样吗?

    开篇 同一个用户并发扣款时,有一定概率出现数据不一致,可以使用CAS乐观锁的方式,在不降低吞吐量,保证数据的一致性: UPDATE t_yue SET money=$new_money WHERE u ...

  3. java-spring基于redis单机版(redisTemplate)实现的分布式锁+redis消息队列,可用于秒杀,定时器,高并发,抢购

    此教程不涉及整合spring整合redis,可另行查阅资料教程. 代码: RedisLock package com.cashloan.analytics.utils; import org.slf4 ...

  4. Linux epoll 笔记(高并发事件处理机制)

    wiki: Epoll优点: Epoll工作流程: Epoll实现机制: epollevent; Epoll源码分析: Epoll接口: epoll_create; epoll_ctl; epoll_ ...

  5. 高并发网络编程之epoll详解

    select.poll和epoll的区别 在linux没有实现epoll事件驱动机制之前,我们一般选择用select或者poll等IO多路复用的方法来实现并发服务程序.在大数据.高并发.集群等一些名词 ...

  6. Springcloud 微服务 高并发(实战1):第1版秒杀

    疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列之15 [博客园总入口 ] 前言 前言 疯狂创客圈(笔者尼恩创建的高并发研习社群)Springcloud 高并发系列文章,将为大家介绍三个版 ...

  7. java之高并发与多线程

    进程和线程的区别和联系 从资源占用,切换效率,通信方式等方面解答 线程具有许多传统进程所具有的特征,故又称为轻型进程(Light—Weight Process)或进程元:而把传统的进程称为重型进程(H ...

  8. 一篇博客带你轻松应对java面试中的多线程与高并发

    1. Java线程的创建方式 (1)继承thread类 thread类本质是实现了runnable接口的一个实例,代表线程的一个实例.启动线程的方式start方法.start是一个本地方法,执行后,执 ...

  9. Java高并发系列——检视阅读

    Java高并发系列--检视阅读 参考 java高并发系列 liaoxuefeng Java教程 CompletableFuture AQS原理没讲,需要找资料补充. JUC中常见的集合原来没讲,比如C ...

随机推荐

  1. 利用CombineFileInputFormat把netflix data set 导入到Hbase里

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/xiewenbo/article/details/25637931 package com.mr.te ...

  2. 解决FlexPaper分页分段加载问题(转)

    FlexPaper是一个开源的PDF文档在线查看控件.用户查看PDF文档不需要安装Acrobat Reader,但需要利用像SwfTools这样的工具预先将PDF文档转成SWF格式的文件.FlexPa ...

  3. git相关使用技巧和问题

    本地有修改和提交,如何强制用远程的库更新更新.我尝试过用git pull -f,总是提示 You have not concluded your merge. (MERGE_HEAD exists). ...

  4. Redis 监控方案

    一.概述 近些天,遇到Redis监控的应用场景,从网上搜罗了一些文章,做了整理. 二.工具列表 2.1 redis-faina 见参考文章1 2.2 redis-live 见参考文章1 2.3 red ...

  5. 497. Random Point in Non-overlapping Rectangles

    1. 问题 给定一系列不重叠的矩形,在这些矩形中随机采样一个整数点. 2. 思路 (1)一个矩形的可采样点个数就相当于它的面积,可以先依次对每个矩形的面积累加存起来(相当于概率分布中的分布累积函数CD ...

  6. PHP curl模拟浏览器采集阿里巴巴的实现代码

    <?php set_time_limit(0); function _rand() { $length=26; $chars = "0123456789abcdefghijklmnop ...

  7. STM32时钟树

    STM32的时钟系统 相较于51单片机,stm32的时钟系统可以说是非常复杂了,我们现在看下面的一张图: 上图说明了时钟的走向,是从左至右的从时钟源一步步的分配给外设时钟.需要注意的是,上图左侧一共有 ...

  8. ubuntu16.04更新源的时候显示:由于没有公钥,无法验证下列签名: NO_PUBKEY 3D5919B448457EE0【学习笔记】

    平台:ubuntu16.04 作者:庄泽彬(欢迎转载,请注明作者) 在添加了bazel的源之后执行sudo apt-get update出现下面的错误 echo "deb [arch=amd ...

  9. ubuntu 18.04 64bit没有声音如何解决

    一.背景 1.1 笔者的机器有两张声卡,使用aplay -l可以列举出来,一张是内置声卡,另一张是显卡自带的声卡,说明声卡驱动是ok的 1.2 笔者是在浏览器中播放视频无声音 二.尝试 2.1 尝试使 ...

  10. Ubuntu16.04 国内更新源

    在修改source.list之前要先备份 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak 替换内容到source.list中 阿里云源: ...