Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工做由VMware主持。从2013年5月开始,Redis的开发由Pivotal(Redis做者目前就任)赞助。php
String(字符串)html
List(列表)mysql
Set(集合)git
Sort Set(有序集合)github
Hash(哈希)web
Redis做者antirez描述了Redis比较适合的一些应用场景,NoSQLFan简单列举在这里,供你们一览:redis
取最新N个数据的操做sql
排行榜应用,取TOP N操做数据库
须要精准设定过时时间的应用json
计数器应用
Uniq操做,获取某段时间全部数据排重值
实时系统,反垃圾系统
Pub/Sub构建实时消息系统
构建队列系统
缓存
无线运营研发部,做为无线运营侧的兵工厂,成功打造了CMS,位置管理,权限中心,RBZ等运营支撑工具。
CMS:无线运营播种机
RBZ:EAV模型(动态表单+属性中心+标签系统)
权限中心:RBAC3模型
位置管理:一切皆位置
^^^^^^^ 回到主题,下面就为你们详细介绍下,咱们如何玩耍Redis。
场景包括CMS页面缓存、API限速器、页面性能分析、API状态统计、CMS智能提醒-异常线路。尤为页面性能分析、API状态统计、CMS智能提醒等应用简直X爆了,将页面和接口性能看板化、智能化,技术应用一目了然、尽收眼底。
场景字段的一些说明
应用场景:属于哪一类应用范畴
数据类型:使用的数据类型
代码说明:PHP,扩展phpredis
基于Redis的字符串数据类型,用来存储CMS静态页面数据,提升CMS相关页面访问速度,缓冲mysql的压力。
数据类型:String
应用场景:缓存
代码:
$staticHtml = Yii::app()->redis->get($cmsCacheKey); if (! $staticHtml || $this->clearcache) { $staticHtml = CmsTools::getStaticHtml($pageId, $cityCode); Yii::app()->redis->setex($cmsCacheKey, 3600, $staticHtml); }
基于Redis的字符串数据类型,用来控制API访问频率,一段时间内某一个IP针对某一个请求的访问控制,官方用例
数据类型:String
应用场景:计数器
代码:
public static function rateLimit($apiKey = null) { //Redis键值 $apiRunCountKey = Yii::app()->request->userHostAddress . '-' . $apiKey; //初始化接口访问频次 if (Yii::app()->redis->get($apiRunCountKey) === false) { Yii::app()->redis->setex( $apiRunCountKey, self::$RateLimitTime, self::$RateLimitCount ); } //获取当前可执行的频次 $currentApiCount = Yii::app()->redis->decr($apiRunCountKey); if ($currentApiCount < 0) { Yii::log($apiRunCountKey, 'info', 'webadmin.cms.api.rate'); return false; } return true; } //CMS页面-重置频率控制 return PowerApiService::rateLimit('cms-refresh-page-' . $pageId) && CmsTool::refreshStaticPage($pageId);
基于Redis的有序集合数据类型,分析页面执行性能。
数据类型:Sort Set
应用场景:排行榜
代码:
//基于城市,记录PC首页生成时间 Yii::app()->redis->zAdd( 'homepage-cache-profile', round($endTime - $startTime, 2), $this->letter ); //汇总PC首页性能数据 Yii::app()->redis->zRange('homepage-cache-profile', 0, -1, true); //基于页面,记录CMS页面重置时间 Yii::app()->redis->zAdd( 'cms-refresh-page-profile', round($pageEndTime - $pageStartTime, 2), $pageId ); //获取CMS,0-30s性能的页面 Yii::app()->redis->zRangeByScore('cms-refresh-page-profile', 0, 30); //获取CMS,>30s性能的页面 Yii::app()->redis->zRangeByScore('cms-refresh-page-profile', 30, 900);
综合运用Redis数据类型,汇总API的调用,监控API的实时请求,分析超时请求。
数据类型:String,List,Sort Set
应用场景:计数器,排行榜
代码(有点长):
/** * Webadmin-API-Status */ public static $webApiList200 = 'web:api:list:200'; public static $webApiList500 = 'web:api:list:500'; public static $webApiListTimeOut = 'web:api:list:timeout'; public static $webApiListCache = 'web:api:list:cache'; public static $webApiListLatest = 'web:api:List:latest'; public static function collectApiStatus(ApiStatus $apiStatus) { $apiAction = array( 'n' => $apiStatus->name, //接口名 'p' => $apiStatus->params, //接口参数 'c' => $apiStatus->client, //客户端 'e' => $apiStatus->elapsed(), //响应时长 't' => time() //时间戳 ); //最新请求-数据录入 Yii::app()->redis->lPush(self::$webApiListLatest, json_encode($apiAction)); Yii::app()->redis->ltrim(self::$webApiListLatest, 0, 29); //最新请求-前台渲染 //$apiLatest = Yii::app()->redis->lGetRange(self::$webApiListLatest, 0, 29); //收集缓存 if ($apiStatus->cache) { self::collectApiResponseCache($apiStatus->name); //zIncrBy } //收集状态 if ($apiStatus->status == 200) { self::collectApiResponse200($apiStatus->name); //zIncrBy } else if ($apiStatus->status == 500) { self::collectApiResponse500($apiStatus->name); //zIncrBy } else { // } //收集超时 if ($apiStatus->elapsed() > 2000) { self::collectApiResponseTimeOut($apiAction); //zIncrBy } }
API-Status:
综合运用Redis数据类型,准实时汇总CMS全部楼层的线路呈现状况,精确的定位异常线路楼层,易于运营人员更好的开展工做。
数据类型:String,List,Sort Set
应用场景:队列,排行榜,缓存
代码(有点绕):
//Redis键值 $cmsCheckPrdKey = "cms:{$pageId}:{$cityCode}"; //CMS-页面ID-预约城市 //推送CMS楼层线路信息 PowerApiService::push( $cmsCheckPrdKey, array( 'pid' => $pageId, //页面ID 'code' => $cityCode, //城市Code 'mid' => $moduleId, //产品模块ID 'i' => $preRouteIds, //运营配置线路 't' => time() //时间戳 ) ); /** * Worker-计算CMS中的异常产品 */ public static function cmsCheckPrd($item = array()) { $pid = $item['pid']; //页面ID $code = $item['code']; //城市Code $mid = $item['mid']; //产品模块ID $i = $item['i']; //待计算的线路 $t = $item['t']; //请求时间戳 //时间戳,用于判断队列的实效性,此处代码省略 //经过搜索接口,判断线路有效性 $solr = new PowerSolrService(); $recommend = new ror_service_recommend(); $recommend->ids = $i; $recommend->queryFields = array("productId"); $o = $solr->recommendQueryOrigin($recommend); //有效的线路 //数据差集=异常线路 $diff = array_diff($i, $o); if ($diff) { //经过有序集合的特性,模块的异常线路=score Yii::app()->redis->zAdd($cmsCheckPrdKey, $mid, $mid . ':' . implode(',', $diff)); //数据有效性=1day Yii::app()->redis->expire($cmsCheckPrdKey, 86400); } //获取CMS页面模块信息 //Yii::app()->redis->zRange($cmsCheckPrdKey, 0, -1); //切割数据,获取模块对应的异常线路 //list($moduleID, $modulePrd) = explode(':', $checkString); }
图示1 (楼层提醒):
CMS异常楼层统计(实时计算):
页面ID | 城市Code | 异常楼层 |
---|---|---|
1992 | 上海 | 4 |
1992 | 广州 | 7 |
1992 | 成都 | 6 |
1949 | 北京 | 6 |
!显然,Redis的应用场景远甚于此。=)
Redis当然很赞,切记当你手上有一把锤子的时候,看全部的东西都是钉子,理解他,用好他。