缓存存储也是数据冗余。数据库访问数据,磁盘IO,慢;访问缓存中的数据,存储操作,速度快;数据库中的热点数据可以在缓存中冗余;先访问缓存,如果安装了,可以大大提高访问速度,减轻数据库压力;这些是缓存的核心读取加速原则。但是,一旦没有***缓存,或者一旦涉及写操作,过程就会比没有缓存复杂。这些就是今天要分享的话题。读操作,如果没有***缓存,过程是怎样的?答:如下图尝试从缓存中获取数据,结果没有***;从数据库中获取数据,从库中读取,读写分离;将数据设置到缓存中,以后可以安装缓存;读取操作的流程应该是明确的。写操作的过程是怎样的?答:写操作既需要数据库中的数据,也需要缓存中的数据。这里有两种选择:先操作数据库,再操作缓存;先操作缓存,再操作数据库;并且,希望保证两个操作的原子性,要么同时成功,要么同时失败。这已经演变成一个分布式事务问题。原子性很难保证。很可能一半的交易会成功,一半会失败。接下来,让我们看看当原子性被破坏时会发生什么。1、先操作数据库,再操作缓存,如上图所示。一般情况下:先操作数据库,成功;然后操作缓存(删除或设置),也成功;但是如果这两个动作的原子性被破坏了:第一步成功,第二步失败就会导致数据库中有新数据,缓存中有旧数据,这是业务无法接受的。画外音:如果第一步失败,可以返回调用方50X,不会出现数据不一致的情况。2、先操作缓存,再操作数据库,如上图所示。一般情况下:先操作缓存(删除或设置),成功;,不会有数据不一致。如果破坏了原子性会怎样?这里有两种情况:操作缓存使用set操作缓存使用delete使用set:第一步成功,但是第二步失败,会导致缓存中set最后的数据,数据库中之前的数据,数据不一致,业务不可接受。而且,一般来说,数据最终是受制于数据库的,写缓存成功了,算不上成功。使用delete时:第一步成功,第二步失败,会导致缓存中没有数据,数据库中有之前的数据。数据不一致,对业务没有影响。只是下次读的时候,会多一个cachemiss。画外音:此时返回来电50X即可。到底是先操作缓存,还是先操作数据库呢?答:(1)对于读请求,先读缓存。如果没有***,就读取数据库,然后设置回缓存。(2)对于写请求,先缓存,后数据库缓存,使用delete,而不是set画外音:《缓存,究竟是淘汰,还是修改?》也提到建议清除缓存或者修改缓存。希望大家有所收获,不同方案欢迎讨论。最后挖个坑:在缓存读取过程中,如果主从不同步,在第2步读取到一个旧数据,可能会导致在缓存中设置一个旧数据,最终数据库和缓存数据会不一致。【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文
