MyBatis与Memcached集成后缓存数据不一致问题
Posted 程序员的未来是写程序
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis与Memcached集成后缓存数据不一致问题相关的知识,希望对你有一定的参考价值。
缓存数据生成到memcache的过程如下:
一、查询数据:
1、根据执行的sql语句转换为缓存的sqlKey值
2、根据sqlKey值查询memcache的缓存数据
3、如果查询到缓存数据返回缓存数据
4、如果查询不到缓存数据则执行sql查询
5、根据执行的sql语句转换为缓存的sqlKey值
6、根据 mapper namespace 生成 groupKey
7、sql查询结果放入缓存,数据结构【sqlKey(sql语句转换为的缓存sqlKey值),object(sql查询结果)】
8、根据groupKey查询sqlKey的集合
9、sql语句转换为的缓存sqlKey值关联到groupKey,数据结构【groupKey,[sqlKey1,sqlKey2,sqlKey3,...](set结果集)】
二、增加、删除、修改数据:
1、执行插入、删除或更新sql
2、根据 mapper namespace 生成 groupKey
3、根据groupKey查询sqlKey
4、根据sqlKey集合大小循环删除sqlKey缓存数据
5、最后删除groupKey缓存数据
以上是MyBatis与Memcache集成后缓存生成与清除的过程,但是使用源码在生产环境出现并发导致数据库和缓存数据不一致问题。具体原因经过查看源码发现以下两个问题:
一、并发查询导致不一致分析
1、 A、B两个用户分别点击查询数据页面,系统执行sql-A和sql-B。
2、 同时执行以上查询逻辑的第8步:根据groupKey查询sqlKey的集合
3、写入memcache的缓存源码如下:
1 public void putObject(Object key, Object value, String id) { 2 String keyString = toKeyString(key); 3 String groupKey = toKeyString(id); 4 5 if (log.isDebugEnabled()) { 6 log.debug("Putting object (" 7 + keyString 8 + ", " 9 + value 10 + ")"); 11 } 12 13 storeInMemcached(keyString, value); 14 15 // add namespace key into memcached 16 Set<String> group = getGroup(groupKey); 17 if (group == null) { 18 group = new HashSet<String>(); 19 } 20 group.add(keyString); 21 22 if (log.isDebugEnabled()) { 23 log.debug("Insert/Updating object (" 24 + groupKey 25 + ", " 26 + group 27 + ")"); 28 } 29 30 storeInMemcached(groupKey, group); 31 }
以上是关于MyBatis与Memcached集成后缓存数据不一致问题的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot 2.0:Spring Boot 集成 Memcached