途牛原创|无线中心运营研发Redis酷实践

Redis-简介

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal(Redis作者目前就职)赞助。

数据类型

  1. String(字符串)

  2. List(列表)

  3. Set(集合)

  4. Sort Set(有序集合)

  5. Hash(哈希)

Redis-应用场景

Redis作者antirez描述了Redis比较适合的一些应用场景,NoSQLFan简单列举在这里,供大家一览:

  1. 取最新N个数据的操作

  2. 排行榜应用,取TOP N操作

  3. 需要精准设定过期时间的应用

  4. 计数器应用

  5. Uniq操作,获取某段时间所有数据排重值

  6. 实时系统,反垃圾系统

  7. Pub/Sub构建实时消息系统

  8. 构建队列系统

  9. 缓存

运营研发-场景

无线运营研发部,作为无线运营侧的兵工厂,成功打造了CMS,位置管理,权限中心,RBZ等运营支撑工具。

武器一览

  1. CMS:无线运营播种机

  2. RBZ:EAV模型(动态表单+属性中心+标签系统)

  3. 权限中心:RBAC3模型

  4. 位置管理:一切皆位置

^^^^^^^ 回到主题,下面就为大家详细介绍下,我们如何玩耍Redis。

场景包括CMS页面缓存、API限速器、页面性能分析、API状态统计、CMS智能提醒-异常线路。尤其页面性能分析、API状态统计、CMS智能提醒等应用简直X爆了,将页面和接口性能看板化、智能化,技术应用一目了然、一览无余。

场景字段的一些说明

  1. 应用场景:属于哪一类应用范畴

  2. 数据类型:使用的数据类型

  3. 代码说明:PHP,扩展phpredis

CMS页面缓存

基于Redis的字符串数据类型,用来存储CMS静态页面数据,提高CMS相关页面访问速度,缓冲mysql的压力。

  1. 数据类型:String

  2. 应用场景:缓存

  3. 代码:

$staticHtml = Yii::app()->redis->get($cmsCacheKey);

if (! $staticHtml || $this->clearcache) {
$staticHtml = CmsTools::getStaticHtml($pageId, $cityCode);
Yii::app()->redis->setex($cmsCacheKey, 3600, $staticHtml);
}

API限速器

基于Redis的字符串数据类型,用来控制API访问频率,一段时间内某一个IP针对某一个请求的访问控制,官方用例

  1. 数据类型:String

  2. 应用场景:计数器

  3. 代码:

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 

性能分析

基于Redis的有序集合数据类型,分析页面执行性能

  1. 数据类型:Sort Set

  2. 应用场景:排行榜

  3. 代码:

//基于城市,记录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);

API状态统计

综合运用Redis数据类型,汇总API的调用,监控API的实时请求,分析超时请求

  1. 数据类型:String,List,Sort Set

  2. 应用场景:计数器,排行榜

  3. 代码(有点长):

/

  • 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}

}

  1. API-Status:

CMS智能提醒-异常线路

综合运用Redis数据类型,准实时汇总CMS所有楼层的线路呈现情况,精确的定位异常线路楼层,易于运营人员更好的开展工作。

  1. 数据类型:String,List,Sort Set

  2. 应用场景:队列,排行榜,缓存

  3. 代码(有点绕):

//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. 图示1 (楼层提醒):

  2. CMS异常楼层统计(实时计算):

页面ID
城市Code
异常楼层

1992
上海
4

1992
广州
7

1992
成都
6

1949
北京
6

!显然,Redis的应用场景远甚于此。=)

学习指南

Redis固然很赞,切记当你手上有一把锤子的时候,看所有的东西都是钉子,理解他,用好他。

  1. Try Redis

  2. Redis官网

  3. Redis设计与实现

关键字:redis, php, yii

版权声明

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部