<?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. oracle(十一) scn

    SCN(System Chang Number)作为oracle中的一个重要机制,在数据恢复.Data Guard.Streams复制.RAC节点间的同步等各个功能中起着重要作用. 理解SCN的运作机 ...

  2. mysql 数据操作 单表查询 concat()函数 定义显示格式

    #定义显示格式 concat() 函数用于连接字符串 类似于python 格式化操作print("姓名:%s" % name)或者 用,拼接一个一个的变量print("a ...

  3. python 定义类 学习1

    此时的d1就是类Dog的实例化对象 实例化,其实就是以Dog类为模版,在内存里开辟一块空间,存上数据,赋值成一个变量名 # 定义类模板 class dog(object): # 定义类的方法功能 # ...

  4. mac 安装homobrew 报错解决

    按照官网(https://brew.sh/index_zh-cn.html)给的命令:     /usr/bin/ruby -e "$(curl -fsSL https://raw.gith ...

  5. iis6下配置支持.net4.0&发布网站[转]

    iis6配置支持.net4.0 在win2003操作系统上发布两个网站,首先配置iis: 1.下载 .net framework 4.0   差不多48MB 2.安装 3.打开iis: 开始=> ...

  6. adb shell top 命令

    原文地址https://blog.csdn.net/kittyboy0001/article/details/38562515 原文地址https://blog.csdn.net/u010503912 ...

  7. django需要了解的

    搞得差不多就去看看类和对象,看看oop是什么,多用lambda,学学md5加密. 你应当了解,django不是服务器,只提供服务.因此,学习nginx.或是apache是必要的.(IIS不了解,不过题 ...

  8. 3.6 Templates -- Binding Element Class Names(绑定元素类名)

    1. 一个HTML元素的class属性可以像其他属性一样被绑定: <div class={{priority}}> Warning! </div> 生成的HTML <di ...

  9. hdu5184 数论证明

    这题说的给了一个整数n 和一串的括号, 那么要我们计算 最后有n/2对括号的 方案数有多少. 我们可以先预先判断一些不可能组成正确括号对的情况, 然后我们可以将这个问题转化到二维平面上, 令 m = ...

  10. Python 如何判断一个函数是generator函数?

    如何判断一个函数是否是一个特殊的 generator 函数?可以利用 isgeneratorfunction 判断: >>>from inspect import isgenerat ...