描述两个场景
1、为了反作弊,我们需要实时的统计某个用户访问某个url的次数,每次用户访问这个url,访问次数就会增加,如果这个用户访问的url次数超过一定的数量限制,就挑选出这样的用户,认为这个用户有作弊的可能
2、现在有很多跑步软件,可以记录你步行的轨迹,实时的记录你的位置,类似这样的试试的在地图上标注你位置的应用,都需要实时通过GPS记录经纬度,从而知道你在什么位置,离目的地还有多远
这两个场景有一个共同点,就是都需要实时的计算某个值,然后保存在缓存中,其实就是一个map(key和value)
但是会出现一个问题,因为一个应用可能存在大量的用户同时访问,这样就会产生高并发的场景,假设有大量的用户同时访问了map,map就成了争用的资源(临界资源),为了解决这种冲突,传统的做法就是对这个map加锁,如下:
读
read_lock(map)
read_map(map)
un_read_lock(map)
写
write_lock(map)
write_map(map)
un_write_lock(map)
由于加锁,消耗资源高,访问map就成了应用或者系统的性能瓶颈怎么解决这种问题呢?
想到了三种方法:
1、map分段加锁
分段map加锁,大致机理类似concurrenthashmap,不做过多介绍,大家可以自己了解,可以一定程度上缓解问题,但是还是对map加锁
2、按记录加锁
把map转变为数组,数组的索引就是用户id,对每条记录加锁,这样虽然性能得到了大幅的提高,但是锁资源消耗严重,不适合高并发
3、无锁缓存(重点介绍)
对数据进行签名验证,例如类似数据库版本控制,这种情况要通过数据库辅助解决cache miss的情况