$var++;
memcache_set($memcon,”var”,$var);
这样一个脚本,使用apache ab去跑,100个并发,跑10000次,然后输出缓存存取的数据,很遗憾,并不是1000,而是5000多,6000多这样的数字,中间的数字全在 get & set的过程中丢掉了。
原因,读写间隔中其他并发写入,导致数据丢失。
范例2
用memcache_increment来做这个操作,同样跑测试
会得到完整的10000,一条数据不会丢。
结论: 用increment存储队列编号,用标记+编号作为key存储队列内容。 后台基于缓存队列读取更新数据并更新数据库
基于队列读取后可以合并更新
更新合并率是重要指标
实战范例:
某论坛热门贴,前端不断有views=views+1数据更新请求。
缓存实时更新该状态
后台任务对数据库做异步更新时,假设执行周期是5分钟,那么五分钟可能会接收到这样的请求多达数十次乃至数百次,合并更新后只执行一次update即可。
类似操作还包括游戏打怪,生命和经验的变化;个人主页访问次数的变化等。 异步更新风险
前后端同时写,可能导致覆盖风险。
使用后端异步更新,则前端应用程序就不要写数据库,否则可能造成写入
冲突。一种兼容的解决方案是,前端和后端不要写相同的字段。
实战范例:
用户在线上时,后台异步更新用户状态。
管理员后台屏蔽用户是直接更新数据库。
结果管理员屏蔽某用户操作完成后,因该用户在线有操作,后台异步更新程序再次基于缓存更新用户状态,用户状态被复活,屏蔽失效。
缓存数据丢失或服务崩溃可能导致数据丢失风险。
如缓存中间出现故障,则缓存队列数据不会回写到数据库,而用户会认为
已经完成,此时会带来比较明显的用户体验问题。
一个不彻底的解决方案是,确保高安全性,高重要性数据实时数据更新,
而低安全性数据通过缓存异步回写方式完成。此外,使用相对数值操作而不是绝对数值操作更安全。
范例:支付信息,道具的购买与获得,一旦丢失会对用户造成极大的
伤害。而经验值,访问数字,如果只丢失了很少时间的内容,用户还
是可以容忍的。
范例:如果使用 Views=Views+…的操作,一旦出现数据格式错误,
从binlog中反推是可以进行数据还原,但是如果使用Views=特定值
的操作,一旦缓存中数据有错误,则直接被赋予了一个错误数据,无
法回溯!
异步更新如出现队列阻塞可能导致数据丢失风险。
异步更新通常是使用缓存队列后,在后台由cron或其他守护进程写入数