1. 程式人生 > 程式設計 >redis統計APP線上人數的例項

redis統計APP線上人數的例項

最近有個需求,需要統計APP的線上人數,其實以前也統計過,採取的是上線傳送一個請求$this->cache->incr()加1,下線的時候$this->cache->decr()減1,可是這樣做的後果是,發現線上人數錯的離譜,幾千人同是線上。

why?原來APP端如果解除安裝的時候,那麼就不會發請求,還有如果非正常終止的時候,也不會發送下線請求?

於是乎找一個準備的統計方式

1:客戶端十分鐘傳送一次請求,帶上序列號,伺服器端set('字首.序列號',過期時間),然後伺服器端統計 keys 字首*

可是你看keys之後的資料格式:

var_dump(); 

array (size=2)
 0 => string 'c_001dddddddddddddddddddddddddddddddd' (length=37)
 1 => string 'c_001ddddddddddddddddddddddddddddddddd' (length=38)
 print_r();
 Array( [0] => c_001dddddddddddddddddddddddddddddddd [1] => c_001ddddddddddddddddddddddddddddddddd)

資料keys *之後資料格式亂糟糟的,不是陣列,根本沒有辦法處理。也許可以把他看成一個檔案,然後正則匹配,再出處理,可是這樣有多慢呢,keys *本來就有些慢,還存入檔案,正則匹配,然後迴圈,獲取陣列長度,就更加慢了。

keys *之後出來是列表吧,更本不是數字,redis也沒有這種獲取某個特殊的鍵字首的數量的函式。

如果APP就一個的話,大家可以把這個鍵值儲存到一個庫裡面,然後用dbsize()直接獲取庫數量,這個庫不儲存其他的鍵值。

可是現在我要統計六個APP的線上情況,不可能一個APP儲存一個庫吧

2:利用序列,

$date = date("Ymdh",time()); $this->_cache->sadd($date.$head,$client,7200);

獲取當前時間,之後加上客戶端型別字首,作為鍵,存入序列,本次方法是一個小時存取一次,就是一個小時之內的都算線上人數,具體多久算線上人數,大家可以自我把握。

存的時候:

$date = date("Ymdh",time());

$this->_cache->sadd($date.$head,7200);//存入集合 1個小時存入一次

取數量的時候

$date = date("Ymdh",time());//當前時間
$hour = date("Ymdh",time()-3600);//上一個小時時間
$score = date("i",time());//當前時間分數
$datedata= $this->_cache->scard($date.$head);//這個小時數量
$hourdata= $this->_cache->scard($hour.$head);//上個小時數量
if($score == '00'){
 $online = $hourdata;//如果當前時間是整點,那麼一個小時人數,就是上個小時人數
}else{
 $online = intval(((60-$score)/60)*$hourdata)+ $datedata;//如果不是整點,那麼計算當前多少分鐘,當前的數量,加上上個小時比例數量 湊夠一個小時數量
}

$online就是線上數量

補充知識:redis命中率計算

redis提供了INFO這個命令,能夠隨時監控伺服器的狀態,只用telnet到對應伺服器的埠,執行命令即可:

telnet localhost 6379

info

在輸出的資訊裡面有這幾項和快取的狀態比較有關係:

keyspace_hits:14414110
keyspace_misses:3228654
used_memory:433264648
expired_keys:1333536
evicted_keys:1547380

通過計算hits和miss,我們可以得到快取的命中率:14414110 / (14414110 + 3228654) = 81% ,一個快取失效機制,和過期時間設計良好的系統,命中率可以做到95%以上

有個ruby gem叫redis-stat,它利用INFO命令展現出更直觀的資訊報表,推薦:

https://github.com/junegunn/redis-stat

以上這篇redis統計APP線上人數的例項就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。