下載數、點閱數、計數的累加很簡單,
若要區分總量、個別、今日,甚至排行,
redis 省掉SQL所要耗的資源。
點閱數、下載數是常見的熱門指標參考,
寫到資料庫裡的table是常見的做法,
來看看大型網站怎麼與redis做計數的結合。
以下載 ruby的gems 為例,
有兩千多種的gem,而每個gem又有不同的新舊版本,
怎樣記錄不同方面的下載數,可利用redis的特性來使用,
以下載 Sinatra 的數量為例:
sinatra的下載總量為 4,673,539,
這個 1.3.3 版本的下載量為 224,293
所以只要一執行這個下載:
http://rubygems.org/downloads/sinatra-1.3.3.gem
key的設計為:
downloads => 整個站所有gem的下載總量
downloads:today => 今日的下載統計,以sorted set的型態,可排序今日下載量
downloads:rubygem:sinatra => 所有sinatra的下載次數
downloads:version:sinatra-1.3.3 => 1.3.3版的下載次數
downloads:rubygem_daily:sinatra => 每日下載 sinatra 的hash
downloads:version_daily:sinatra-1.3.3 => 每日下事1.3.3的hash記錄
上面提到的每日下載的hash 或 sorted set 格式像這樣子:
'2012-10-24' : 111
'2012-10-25' : 222
所以當下載 /gems/sinatra-1.3.3.gem 一次的時候,
redis作這些動作:
INCR downloads
INCR downloads:rubygem:sinatra
INCR downloads:version:sinatra-1.3.3
ZINCRBY downloads:today 1 sinatra-1.3.3
每天在結束前讓cron作以下動作,
把當日各gem的下載數,寫到每日的各gem的下載統計裡:
RENAME downloads:today downloads:yesterday
keys = ZRANGE downloads:yesterday 0 -1
keys.each do |key|
version = Version.find_by_full_name(key)
downloads = ZSCORE downloads:yesterday key
HINCRBY downloads:version_daily:#{version.full_name} Date.today downloads
HINCRBY downloads:rubygem_daily:#{version.rubygem.name} Date.today downloads
end
如果要排出今天所有gem下載的前五名
ZREVRANGE downloads:today 0 4
例出每天 sinatra 的下載數:
Redis.new.zrange('downloads:rubygem_daily',0,-1,:with_scores => true)
如果網站裡沒那麼複雜的檔案版本關係,
就不需要用上面的hash的型式,而用:
INCR downlaods:sinatra:today
INCR downlaods:sinatra:2012-10-25
到時候再一週或一個月把每日的累計,
寫到另個key甚至資料庫裡。
就依著常用到的頻率,調整何時寫到何處,
而不必所有記錄一定要即時累加寫入。