最近收到了一個需求
需要不斷的在一個data pool隨機找到資料後,給前端顯示新value
剛開始的做法是把資料全部存在DB內
然後再根據flag做where,之後再更新flag
但如此一來
DB雖說沒被吃垮,但假設資料量持續增長,DB鐵定會因為頻繁的update給搞到爆掉
而且從目前評估起來,DB一分鐘內高峰時會做到800-1000次update
聽起來就不太妙XD
於是只把資料Load一次,改用本地cache去做操作
但也出現了一個問題
資料有n筆,我在本地也要做O(n)次搜尋,然後再去改flag
最棒的是這個handler有複數個routing在執行,在加上API也會操作到
從一般的Lock改用RWLock,API還是一樣會hang在那邊到timeout
但直到最後我想到了sync.Map
func SelectDataBaseData(){}
func HandleRandomPickData(){
// Do random pick data from SelectDataBaseData()
for index:=range afterPickData{
UpdateDataStatus()
}
}
func HandleTimeOutData(){
for index:=range afterPickData{
UpdateDataStatus()
}
}
func UpdateDataStatus(){
// Do data update status to database
}
var datas []DataStructure{}
var mux sync.RWMutex
func InitializeCacheData(){
selectData:=SelectDataBaseData()
for _,data:=range selectData{
datas = append(datas,data)
}
}
func HandleRandomPickData(){
// Do random pick data from datas
for i:=range afterPickData{
for j:=range datas{
if datas[j].key == afterPickData[i].key{
mux.Lock()
datas[j].status = 1
mux.Unlock
}
}
}
}
func HandleTimeOutData(){
// Do random and pick data
for i:=range afterPickData{
for j:=range datas{
if datas[j].key == afterPickData[i].key{
mux.Lock()
datas[j].status = 0
mux.Unlock
}
}
}
}
var mp sync.Map{}
func InitializeCacheData(){
datas:=SelectDataBaseData()
for _,data:=range datas {
mp.Store(data.key,data.value)
}
}
func HandleRandomPickData(){
count:= 0
mp.Range(func(key interface{}, value interface{}) bool {
if count == 10 {
return false
}
PickKey:=key.(T)
PickValue:=value.(T)
mp.Delete(key.(T))
count++
return true
})
}
func HandleTimeOutData(){
data:=GetTimeOutValue()
for index:=ramge data{
mp.Store(data[i].Key,data[i].Value)
}
}
在閒閒沒事的時候總是會靈光一閃
想到一個做pool的辦法直接解決所有問題
還能利用資料結構的特性帶來時間上的優勢
加上package還有改良過對race condition的影響
只有最好用沒有更好用XD