使用Redis Zset來處理活動經常使用排行榜(精確排行)

嚴格的排行榜

一個嚴格的排行榜,必需要知足每一個人的排序都是有實際意義的,簡單來講就是即便兩我的的分數同樣,那麼也要分出前後來。
活動週期在92天之內的話,那麼咱們就可使用200w加活動結束時間做爲數字A來保證排行榜的順序正確php

在很大的活動中,好比獎項很大,第10名和第11名,可能獎金的額度相差了幾萬、幾千。這個時候咱們在作處理的時候就要當心了。咱們要維護一個公平的排行榜。爲了知足這樣一個排行榜,咱們須要在score的後面添加一個時間戳相關的係數。舉個例子:redis

用戶a 100 分 14:00 最後加分
用戶b 100 分 14:20 最後加分

那麼按照排行榜的規定來算,用戶a要排在用戶b以前。
可是咱們在進行排行的時候,不能將時間直接加到分數後面,不然就排序反了,這個時候咱們要用一個足夠大的數A來減去時間戳,而且要保證位數在整個活動期間不變。

首先咱們要理解一個redis的排序,redis的zset中的score值爲double類型,精度只有16位,事實上在存儲9999999999999999 16位整數的時候,會變爲17位的10000000000000000,超過17位會變爲科學計數法1e+17code

在活動中,咱們要保證用戶的分數不能丟失,因此必須保證在16位之內,一個用戶最多的粉絲是5000w若是一個活動期間能保證全部的用戶給他刷分,那麼多是億級別的,可是實際上按照以前的活動量來看,最多能到千萬級別。排序

這個時候咱們按照1億來算,長度要保證在9位,而後剩下的排重用的時間戳的精度,要保證在7位,也就是說咱們要保證整個活動期間足夠大的數減去時間戳的開始時間和結束時間都是7位數。class

首先保證數字A-結束時間爲一個7位數 ,那麼咱們要給這個結束時間+1000000 (一百萬) 獲得數字A,這樣能最低限度保證活動結束以前時間戳係數的位數不變爲7位數。
而後咱們要保證數字A-活動開始時間也是一個七位數,也就是說開始時間和結束時間之間的跨度只能是900w,一旦超過900w,那麼數字A減去開始時間就會獲得一個8位數。時間戳

可是100w是一個臨界點,咱們100w和結束時間相加獲得數字A,可能會由於活動結束時間的延長致使效果變成了爲結束時間+99w 獲得數字A,這個時候,活動最後結束的分數係數的位數就變爲了6位,這簡直就是個災難。di

因此咱們將100w擴大爲200w,這樣相應的就給活動的結束時間增長了(100w/3600/24 = 11)天的時間。可是獲得的效果將 活動的跨度週期減少到了800w秒,也就是(8000000/86400=92)天。因此說,若是活動週期在92天之內的話,那麼咱們就可使用200w加活動結束時間做爲數字A來保證排行榜的順序正確。時間

相關文章
相關標籤/搜索