redis高并发下的处理考勤打卡数据
背景
最近公司用户量上来了,因此,对考勤打卡的瓶颈也就越发明显。每到打卡高峰期,公司APP就打开很慢,甚至服务开挂。针对这些问题,检查服务器发现,原来是考勤接口并发上来不停请求数据库导致的CPU剧增。因此,升级了服务器,提升了配置,但是还是不能抗住压力。因此,自己百度发现redis是个好东西,可以做缓存数据库,缓解mysql压力。因此,写下这篇文章。
主要运用
- 1.redis:hset,del,hKeys...
- 2.定时任务
- 3.注意:设计时,是以每天为单位,异步同步redis缓存数据到mysql。
代码模块
- 1.redis基础封装
<?php
/*** Created by PhpStorm.* User: FengYun* Date: 2019/12/6* Time: 9:47*/namespace App\Services\Sign;use App\Services\ComService;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Redis;class RedisBaseService extends ComService
{private $config;private $redis;protected function __construct(){$this->redis = app('redis.connection');}private function _getEnable(){$conf = $this->config;return $conf['enable'];}/*** 查询key* @param $key* @return mixed*/public function keys($key){return $this->redis->keys($key);}/*** 设置位图* @param $key* @param $offset* @param bool $value* @param int $time*/public function setBit($key, $offset,$value,$time=0){$result = $this->redis->setbit($key,$offset,$value);if($time>0){$this->redis->expire($key,$time);}return $result;}/*** 获取位图* @param $key* @param $offset* @return mixed*/public function getBit($key,$offset){return $this->redis->getBit($key,$offset);}/*** 统计位图* @param $key* @return mixed*/public function bitCount($key){if(!$this->_getEnable()){return null;}return $this->redis->bitCount($key);}/*** 位图操作* @param $operation* @param $reKey* @param array ...$key* @return mixed*/public function bitOp($operation,$reKey,...$key){if(!$this->_getEnable()){return null;}return $this->redis->bitOp($operation,$reKey,$key);}/*** 计算在某段位图中 1或0第一次出现的位置* @param $key* @param $bit 1/0* @param $start* @param null $end* @return mixed*/public function bitPos($key,$bit,$start,$end=null){if(!$this->_getEnable()){return null;}return $this->redis->bitPos($key,$bit,$start,$end);}/*** 删除位图* @param $key* @return mixed*/public function del($key){return $this->redis->del($key);}/*** 写入* @param $key* @param $hashKey* @param $value* @return bool*/public function hSet($key, $hashKey, $value ){return $this->redis->hset($key,$hashKey,$value);}/*** 批量获取* @param $key* @return bool*/public function hGetAll($key){return $this->redis->hGetAll($key);}/*** @param $key* @param $hashKey* @return bool*/public function hExists($key,$hashKey){return $this->redis->hExists($key,$hashKey);}/*** @param $key* @return bool*/public function hKeys($key){return $this->redis->hKeys($key);}/*** @param $key* @return bool*/public function hLen($key){return $this->redis->hLen($key);}/*** 管道技术批量入库* @param $key* @param $value*/public function setPipe($key,$value){$this->redis->multi();$this->redis->set('sign_'.$key,$value);$this->redis->get('sign_'.$key);$replies=$this->redis->exec();print_r($replies);}
}
- 2.打卡封装(根据需要而定,可省略)
<?php
/*** Created by PhpStorm.* User: FengYun* Date: 2019/12/6* Time: 10:13*/namespace App\Services\Sign;class RedisSignService extends RedisBaseService
{private $keySign= 'sign_';//签到记录keyprivate $key = 0;public function __construct($keySign){parent::__construct();//格式:前缀_2019_10_11:265|E234FD|20191206101112|1 =>1/0}}
- 3.打卡数据组装封装
<?php
/*** Created by PhpStorm.* User: Moer* Date: 2019/12/6* Time: 9:46*/namespace App\Services\Sign;class SignService
{public static function userSignIn($params){$sign_date = $params['sign_date'];$sign_time = $params['sign_time'];$company_id = $params['company_id'];$uuid = $params['uuid'];$sign_type = $params['sign_type'];$sign_date = date('Ymd',strtotime($sign_date));$keySign = 'sign_' . $sign_date .':'. $company_id .'|'. $uuid .'|'. date('YmhHis') .'|'. $sign_type;$signLogModel = new RedisSignService($keySign);try{/*格式:前缀_打卡日期:公司id|员工id|打卡时间|打卡方式sign_20191011:265|125043|20191206101112|1*/$key = 'sign_' . $sign_date ; //sign_20191011$hashKey = $uuid .'|'. date('His',strtotime($sign_time)); //125043|143705$value = $company_id . '|' . $uuid .'|'. date('H:i:s',strtotime($sign_time)) .'|' .$sign_type;//公司|用户uuid|打卡时间|打卡类型 265|125043|20191206101112|1//写入redis数据$res = $signLogModel->hSet($key,$hashKey,$value);if(!$res){return false;}}catch (\Exception $e){return ['msg'=>$e->getMessage(),'code'=> $e->getCode()];}}
}
- 4.模拟并发情况
<?phpnamespace App\Http\Controllers\Order;use App\Model\OrderSpikeModel;
use App\Services\Order\OrderService;
use App\Services\Sign\CronSignLogService;
use App\Services\Sign\SignService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Redis;class OrderController extends Controller
{public function signIn(Request $request){$params['sign_date'] = date('Y-m-d',time());$params['sign_time'] = date('YmdHis',time());$params['company_id'] = rand(100,200);$params['uuid'] = '10000001';$params['sign_type'] = 1;
// SignService::userSignIn($params);$start = microtime(true);for ($i=0;$i<10000;$i++){
// sleep(1);$params['sign_date'] = date('Y-m-d',time());$params['sign_time'] = date('Y-m-d H:i:s',time());$params['company_id'] = rand(1,2000);$params['uuid'] = $i ;$params['sign_type'] = 1;try{SignService::userSignIn($params);}catch (\Exception $e){return ['msg'=>$e->getMessage(),'status'=>false];}}$end = microtime(true);echo '耗时'.round($end-$start,3)."秒<br/>";echo '内存(Now memory_get_usage): ' . memory_get_usage() . "<br />";return true;}
}
- 5.定时同步到mysql
<?php
/*** 定时任务入库* Created by PhpStorm.* User: FengYun* Date: 2019/12/6* Time: 10:50*/namespace App\Services\Sign;use App\Model\OrderSpikeModel;
use App\Services\ComService;class CronSignLogService extends ComService
{public function __construct(){}public static function addUserSignLogToMysql(){$data = [];//获取需要同步的日期或者年月日$day = '20191210';$sign_type = self::SIGN_TYPE_APP;//APP打开$uuid = 0;$company_id = 0;$signLogModel = new RedisSignService($uuid,$company_id,$day,$sign_type);//格式:前缀_20191209:192|10000001|20191201014803|1//$keys = $signLogModel->keys('sign_'. $day .':*');$sign_key = 'sign_'.$day;$keys = $signLogModel->hGetAll($sign_key);$today = date('Y-m-d',time()) .' ';foreach ($keys as $key){//公司|用户uuid|打卡时间|打卡类型$userArr = explode('|',$key);//获取用户信息 公司id,用户id,签到时间,签到类型$data[] = ['company_id'=> $userArr[0],'uuid'=> $userArr[1],'sign_time'=> $today . $userArr[2],'sign_type'=> $userArr[3],];}
// var_dump($data);die;try{$is_success = false;if($data){//数据入库$insert_res = OrderSpikeModel::insert($data);//入库成功后,删除入库数据if($insert_res){$isExist = $signLogModel->hLen($sign_key);if($isExist > 0){$is_success = $signLogModel->del($sign_key);}}}return $is_success;}catch (\Exception $e){return ['msg'=> '操作入库失败,error:'. $e->getMessage(),'code'=> $e->getCode(),'status'=>false];}}
}注:定时同步redis数据到mysql数据库。这里同步数据时,可以采用队列异步同步到msyql,根据自己喜欢而定。
总结
高并发下缓存数据库不为是一个很好的抗压工具,建议多使用,切勿滥用!
redis高并发下的处理考勤打卡数据相关推荐
- php 频繁插库处理队列,PHP+Redis 消息队列 实现高并发下注册人数统计的实例
前言 现在越来越多的网站开始注重统计和用户行为分析,作为网站经常使用的功能,如何让统计性能更加高,这也是我们需要考虑的事情.本篇通过Redis来优化统计功能(以注册人数统计为例). 传统的统计功能都是 ...
- 【钉钉-场景化能力包】考勤打卡
需求场景 员工到岗通知:企业通过设置自定义考勤规则,员工打开钉钉后实现快速打卡,打卡结果即时通知到部门主管处,方便主管查看人员到岗情况. 员工绩效计算:员工通过钉钉快速上下班考勤,企业随时可获取到员工 ...
- PHP redis秒杀返回结果,php结合redis实现高并发下的抢购、秒杀功能
抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个: 1 高并发对数据库产生的压力 2 竞争状态下如何解决库存的正确减少("超卖"问题) 对于第一个问题,已经很容易想到 ...
- php结合redis实现高并发下的抢购、秒杀功能
抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个: 1 高并发对数据库产生的压力 2 竞争状态下如何解决库存的正确减少("超卖"问题) 对于第一个问题,已经很容易想到 ...
- php生成 sku_高并发下,php与redis实现的抢购、秒杀功能
抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个: 1 高并发对数据库产生的压力 2 竞争状态下如何解决库存的正确减少("超卖"问题) 对于第一个问题,已经很容易想到 ...
- 1000+Redis实例,100+集群,Redis 在海量数据和高并发下的优化实践
墨墨导读:Redis 对于从事互联网技术工程师来说并不陌生,几乎所有的大中型企业都在使用 Redis 作为缓存数据库. 但是对于绝大多数企业来说只会用到它的最基础的 KV 缓存功能,还有很多 Redi ...
- PHP 结合redis实现高并发下抢购、秒杀
抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个: 1 高并发对数据库产生的压力 2 竞争状态下如何解决库存的正确减少("超卖"问题) 对于第一个问题,已经很容易想到 ...
- 简单实现redis实现高并发下的抢购/秒杀功能
简述 抢购/秒杀是如今很常见的一个应用场景,那么高并发竞争下如何解决超抢(或超卖库存不足为负数的问题)呢? 常规写法: 查询出对应商品的库存,看是否大于0,然后执行生成订单等操作,但是在判断库存是否大 ...
- 钱文品 | 《Redis在海量数据和高并发下的优化实践》主题分享
原文:http://www.enmotech.com/web/detail/1/750/1.html 导读:Redis 对于从事互联网技术工程师来说并不陌生,几乎所有的大中型企业都在使用 Redis ...
最新文章
- java api 框架_java常用对象API之集合框架
- 【高级数据结构】并查集
- 【转帖】详解CSS网页布局中默认字体样式
- cnblogs第一篇
- 初等数论--原根--怎么判断a是不是模m的原根
- Linux的unlink
- 【Demo】配置重试和超时策略
- 【渝粤教育】10259k2_经济学基础_21秋考试
- LeetCode第14题:最长公共前缀
- html输入支付密码样式,基于JS实现类似支付宝支付密码输入框
- 学会这个绝招,让 C++ 崩溃无处可逃!
- 为什么黑客都用python-为什么大多数黑客都使用Python!
- [Win/Mac]下载工具推荐及使用
- ubuntu设置python3.7为默认(python版本切换)
- matlab中三种原油问题,基于MATLAB联合站原油加热模糊控制(程序)
- 深度学习面试题100题
- 山东计算机设计大赛,山东大学控制学院本科生获中国大学生计算机设计大赛国家级二等奖...
- 如何使用命令行从图像中提取文本
- JavaSE 多线程
- 解决 Vmware 虚拟机安装linux系统无法联网的的问题
热门文章
- 视频教程-PPT吸金大法 20+万年薪工作总结不用愁-Office/WPS
- matlab gain使用,matlabgain模块
- 微信小程序电商实战项目
- AI遮天传 DL-CNN
- 14.Unity2D 横版 粒子系统特效 飙血粒子+高处落地粒子+对象池管理所有粒子
- 【C#】WPF实现经典纸牌游戏,适合新手入门
- Vue的大坑 input手动赋值后无法修改问题
- OOALV中字段设置ALV中下拉列表列的实现
- L1-040. 最佳情侣身高差 java
- zlt尼玛银行,深度学习Redis(一) 关系型与非关系型数据库使用方式的转变过程