月初面試惶楼,碰到了一個(gè)比較實(shí)際的問題:
在Mysql數(shù)據(jù)庫(kù)中屁魏,每天都會(huì)生成10w條數(shù)據(jù)滔以,但是,由于內(nèi)存限制氓拼,導(dǎo)致了Redis中只能存儲(chǔ)最多1W條的數(shù)據(jù)信息你画,如何確保這1w條數(shù)據(jù)是最熱門的數(shù)據(jù)抵碟?
個(gè)人解決方案:
-
數(shù)據(jù)存儲(chǔ)方案:
既然熱門數(shù)據(jù),那么就需要有排序坏匪,使用redis中的zset數(shù)據(jù)類型是很自然的想法拟逮。數(shù)據(jù)中的某個(gè)唯一字段作為zset中的value,而點(diǎn)擊次數(shù)作為score适滓,記為click_zset敦迄。這樣就可選出最熱門的數(shù)據(jù)。而數(shù)據(jù)凭迹,則直接用HashMap存儲(chǔ)罚屋。
時(shí)效的問題:
既然只能存1w條數(shù)據(jù)且需要是熱門數(shù)據(jù),那么嗅绸,點(diǎn)擊次數(shù)是一方面脾猛,時(shí)效性也是一方面,如何保證鱼鸠?可以另起一個(gè)zset猛拴,數(shù)據(jù)的字段為value,而每次點(diǎn)擊時(shí)更新當(dāng)前時(shí)間戳為其score蚀狰,記為time_zset這樣愉昆,就可以記錄時(shí)間。在后臺(tái)跑一個(gè)任務(wù)麻蹋,間隔一定時(shí)間段刪除兩個(gè)zset中長(zhǎng)時(shí)間沒有發(fā)生點(diǎn)擊事件的鍵撼唾,并刪除hash數(shù)據(jù),為產(chǎn)生的新數(shù)據(jù)騰出數(shù)據(jù)空間哥蔚。新數(shù)據(jù)產(chǎn)生怎么辦?
如果有空間蛛蒙,則保存到自己的hashmap糙箍,并將key存到兩個(gè)zset中。
而沒有空間時(shí)牵祟,就應(yīng)該在click_zset中取出點(diǎn)擊次數(shù)排在最前第1w位后面的鍵深夯,刪除對(duì)應(yīng)的hash數(shù)據(jù)。然后看這1w個(gè)score的值诺苹,然后把key放入兩個(gè)zset中即可咕晋。點(diǎn)擊事件產(chǎn)生了怎么辦?
點(diǎn)擊事件發(fā)生時(shí)收奔,讓其在click_zset中的score加1掌呜,然后看其在不在前1w個(gè)key中,如果在坪哄,首先要看該數(shù)據(jù)是否已經(jīng)存在redis中质蕉,有的話就不用做什么工作势篡,沒有的話則需要取出第1W個(gè)點(diǎn)擊次數(shù)最大的key10000,然后刪除key10000所對(duì)應(yīng)的數(shù)據(jù)模暗,把當(dāng)前key對(duì)應(yīng)的數(shù)據(jù)取出存入redis中禁悠。
邏輯有點(diǎn)混亂,大致意思是這樣兑宇,請(qǐng)大家指點(diǎn)碍侦。