Golang-sync.Map 高併发的神之好用方法

最近收到了一个需求
需要不断的在一个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

没有race condtionkey-value的资料结构,只要O(1)就能解决问题,还能简化资料栏位map本身就是无顺序结构,还能来拿当随机使用然后只要用一个sync.Map当作cache pool,资料失效就丢回来pool,资料生效就从pool删除

一开始的做法

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.RWMutexfunc 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


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章