天天看點

途牛原創|無線中心營運研發Redis酷實踐

Redis-簡介

Redis是一個開源的使用ANSI C語言編寫、支援網絡、可基于記憶體亦可持久化的日志型、Key-Value資料庫,并提供多種語言的API。從2010年3月15日起,Redis的開發工作由VMware主持。從2013年5月開始,Redis的開發由Pivotal(Redis作者目前就職)贊助。

資料類型

  • String(字元串)
  • List(清單)
  • Set(集合)
  • Sort Set(有序集合)
  • Hash(哈希)

Redis-應用場景

Redis作者antirez描述了Redis比較适合的一些應用場景,NoSQLFan簡單列舉在這裡,供大家一覽:

  • 取最新N個資料的操作
  • 排行榜應用,取TOP N操作
  • 需要精準設定過期時間的應用
  • 計數器應用
  • Uniq操作,擷取某段時間所有資料排重值
  • 實時系統,反垃圾系統
  • Pub/Sub建構實時消息系統
  • 建構隊列系統
  • 緩存

營運研發-場景

無線營運研發部,作為無線營運側的兵工廠,成功打造了CMS,位置管理,權限中心,RBZ等營運支撐工具。

武器一覽

  • CMS:無線營運播種機
  • RBZ:EAV模型(動态表單+屬性中心+标簽系統)
  • 權限中心:RBAC3模型
  • 位置管理:一切皆位置

^^^^^^^ 回到主題,下面就為大家詳細介紹下,我們如何玩耍Redis。

場景包括CMS頁面緩存、API限速器、頁面性能分析、API狀态統計、CMS智能提醒-異常線路。尤其頁面性能分析、API狀态統計、CMS智能提醒等應用簡直X爆了,将頁面和接口性能看闆化、智能化,技術應用一目了然、一覽無餘。

場景字段的一些說明
  • 應用場景:屬于哪一類應用範疇
  • 資料類型:使用的資料類型
  • 代碼說明:PHP,擴充phpredis

CMS頁面緩存

基于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);
}

           

API限速器

基于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);

           

API狀态統計

綜合運用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智能提醒-異常線路

綜合運用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 (樓層提醒):
    途牛原創|無線中心營運研發Redis酷實踐
  • CMS異常樓層統計(實時計算):
頁面ID 城市Code 異常樓層
1992 上海 4
1992 廣州 7
1992 成都 6
1949 北京 6
!顯然,Redis的應用場景遠甚于此。=)

學習指南

Redis固然很贊,切記**當你手上有一把錘子的時候,看所有的東西都是釘子**,了解他,用好他。

  • Try Redis
  • Redis官網
  • Redis設計與實作

版權聲明:本文為CSDN部落客「weixin_33912638」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。

原文連結:https://blog.csdn.net/weixin_33912638/article/details/91942716