簽到功能,用 MySQL 還是 Redis ?

今天看下簽到功能怎么選擇?

現(xiàn)在的網(wǎng)站和app開(kāi)發(fā)中,簽到是一個(gè)很常見(jiàn)的功能,如微博簽到送積分,簽到排行榜

微博簽到

如移動(dòng)app ,簽到送流量等活動(dòng),

移動(dòng)app簽到

用戶簽到是提高用戶粘性的有效手段,用的好能事半功倍!

更多java干貨技能全在微信:YDT939里面,更多面試專題、筆記、資料免費(fèi)領(lǐng)取

下面我們從技術(shù)方面看看常用的實(shí)現(xiàn)手段:

一. 方案1

直接存到數(shù)據(jù)庫(kù)MySQL

用戶表如下:

last_checkin_time 上次簽到時(shí)間

checkin_count 連續(xù)簽到次數(shù)

記錄每個(gè)用戶簽到信息

簽到流程

1.用戶第一次簽到

last_checkin_time?=?time()

checkin_count=1

2.用戶非第一次簽到,且當(dāng)天已簽到

什么也不做,返回已簽到。

3.用戶非第一次簽到,且當(dāng)天還未簽到

a.昨天也有簽到

last_checkin_time?=?time()

checkin_count=?checkin_count+1

b.昨天沒(méi)有簽到

last_checkin_time?=?time()

checkin_count=1

使用yii實(shí)現(xiàn)的代碼如下:

//0點(diǎn)

$today_0=?strtotime(date('y-m-d'));

//昨天0點(diǎn)

$yesterday_0=$today_0-24*60*60;

$last_checkin_time=$model->last_checkin_time;if(empty($last_checkin_time)){

//first?checkin

$model->last_checkin_time?=?time();

$model->checkin_count?=?1;

}else{

if($today_0<$last_checkin_time){

//checkin?ed?當(dāng)天已簽到過(guò)

returnjson_encode(['code'=>?0,'msg'=>'已簽到成功']);

}?//昨天簽到過(guò)if($last_checkin_time<$today_0&&$last_checkin_time>$yesterday_0){

$model->last_checkin_time?=?time();

$model->checkin_count?=$model->checkin_count?+?1;

}else{

//昨天沒(méi)簽到過(guò),重新計(jì)數(shù)

$model->last_checkin_time?=?time();

$model->checkin_count?=?1;

}}$rs=$model->save();

二. 方案2

redis實(shí)現(xiàn)方案,使用bitmap來(lái)實(shí)現(xiàn),bitmap是redis 2.2版本開(kāi)始支持的功能,一般用于標(biāo)識(shí)狀態(tài),

另外 ,用bitmap進(jìn)行當(dāng)天有多少人簽到非常的方便,使用bitcount

redis->BITCOUNT($key);

簽到流程

設(shè)置兩個(gè)bitmap ,

一個(gè)以每天日期為key ,每個(gè)uid為偏移量

一個(gè)以用戶uid為key ,當(dāng)天在一年中的索引為偏移量,

這樣記錄一個(gè)用戶一年的簽到情況僅需要365*1bit

以下是簽到代碼

//每天一個(gè)key

$key='checkin_'.?date('ymd');

if($redis->getbit($key,$uid)){

//已簽到returnjson_encode(['code'=>?0,'msg'=>'已簽到成功']);

}else{

//簽到$redis->setbit($key,$uid,?1);

$redis->setbit('checkin_'.$uid,?date('z'),?1);

}

以下是用戶連續(xù)簽到計(jì)算

public?staticfunctiongetUserCheckinCount($uid){

$key='checkin_'.$uid;

$index=?date('z');

$n=?0;

for($i=$index;$i>=0;$i--){

$bit=?Yii::$app->redis->getbit($key,$i);if($bit==?0)break;

$n++;??}return$n;

}

以下是計(jì)算一天簽到用戶數(shù)

$key='checkin_'.?date('ymd');

$redis=?Yii::$app->redis;$count=$redis->BITCOUNT($key);

還有什么需求呢?可以自己試著去實(shí)現(xiàn)

三. 優(yōu)缺點(diǎn)比較

1.直接MySQL

思路簡(jiǎn)單,容易實(shí)現(xiàn);

缺點(diǎn):占用空間大,表更新比較多,影響性能,數(shù)據(jù)量大時(shí)需要用cache輔助;

2.Redis bitmap

優(yōu)點(diǎn)是:

占用空間很小,純內(nèi)存操作,速度快;

缺點(diǎn)是 :

記錄的信息有限,只有一個(gè)標(biāo)識(shí)位;

偏移量不能大于2^32,512M;大概可以標(biāo)識(shí)5億個(gè)bit位,絕大多數(shù)的應(yīng)用都是夠用的啦;

偏移量很大的時(shí)候可能造成 Redis 服務(wù)器被阻塞;所以要考慮切分。

好啦,兩種方式介紹完了,各有利弊,你喜歡哪種方式呢?

歡迎討論!

更多java干貨技能全在微信:YDT939里面,更多面試專題、筆記、資料免費(fèi)領(lǐng)取

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容