试想如果取消缓存机制,每秒几万、几十万的数据访问都会请求数据库。会造成数据库连接不够用的情况,系统性能会大大降低。服务器的压力会瞬间上升。
具体场景是:系统正在运行时,由于某种原因,需要修改某项配置数据,并且要求立即生效。
MC给我们带来了方便,但是对于一个庞大的MC集群,可能多达几十个memcached节点,总容量达上百GB。如果快速更新缓存中的旧数据呢。
MC本身提供了遍历下面的item的功能,但在这里显然不适用,因为我们的数据太多了。
原来系统的做法是:将每一个Key保存起来,当系统发出更新指令的时候,将保存起来的key对应的Item从MC中逐个删除。显然这不是一个好方法。因为MC保存的对象不能太大(最大是1MB),如果保存key的集合太大、就会存不进MC,连之前保存的也一起丢失了。最后只能将整个MC集群flushAll掉。
flushAll可能不是我们希望的,比如我们同事在MC集群中保存了A地区的配置数据、B地区的、C地区的数据。而我们现在只想更新A地区的数据,这个时候就不能使用flushAll了。
我的做法是通过一套异步的 发布-订阅 方式,利用公共容器MC或者数据库来实现MC数据更新。
图示如下:
通过WebService将更新指令送入MC,分布式的各个应用程序中的守护线程会定期扫描MC,获取最新的指令,和上一个版本比对,如果发现不一样就将当前的缓存版本号更新成最新的——McVersion={newVersion}。
应用程序中从缓存查取数据,会先生成一个key。
key = 参数信息 + 地区信息 +McVersion;
此时,McVersion已经被更新了,所以生成的key也就和之前的不一样了。
这样就能达到更新缓存的目的了。
这种方法最大的优点是高效,而且可以将各地区的数据在逻辑上分离。因为key中加入了地区信息。
如: 北京地区的某个配置信息可能是 key = offerSpec_123_010_version0.1
上海地区的对应的配置信息就是 key = offerSpec_123_021_version0.1
如果此时应用中缓存版本发生变化,从version0.1 变成 version0.2
那么北京和上海地区的 原来对应的key就会变成:
offerSpec_123_010_version0.2
offerSpec_123_025_version0.2
你不必担心原来的旧数据会留在MC中,挥之不去。其实不然,你只需要在存数据到缓存的时候,加上一个失效时间久可以了。MC会到期将一些无用的或者过期的数据清除掉。