使用缓存cache 的大坑

Posted Mr_Smile2014

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用缓存cache 的大坑相关的知识,希望对你有一定的参考价值。

 这段时间发现系统取数据过程中,偶尔出现取数据错乱的问题,按逻辑应该取出A数据,结果取出了B数据。仔细检查了代码,

发现代码逻辑没有问题,瞬间就蒙了,是哪里出现问题了呢。仔细想了一下,以前都没出现问题,自从加了缓存之后就偶尔出现了问

题,那肯定问题是缓存有问题。


仔细研究了缓存的源码,原来问题出现在DefaultKeyGenerator生成key上面。代码如下:


 public class DefaultKeyGenerator implements KeyGenerator {

	public static final int NO_PARAM_KEY = 0;
	public static final int NULL_PARAM_KEY = 53;

	public Object generate(Object target, Method method, Object... params) {
		if (params.length == 1) {
			return (params[0] == null ? NULL_PARAM_KEY : params[0]);
		}
		if (params.length == 0) {
			return NO_PARAM_KEY;
		}
		int hashCode = 17;
		for (Object object : params) {
			hashCode = 31 * hashCode + (object == null ? NULL_PARAM_KEY : object.hashCode());
		}
		return Integer.valueOf(hashCode);
	}

}


从源码中我们发现,当参数:params有一个或0的时候,直接返回NULL_PARAM_KEY或者参数params[0],假如params参数大于1

的时候返回的是各个参数的hash值相加的值+31*17。这样就出现问题了,虽然取A数据与取B数据的各个参数的值不一样,但是有可能它们

参数的hashcode值是一样的,那么就可能出现取A数据把B数据取出来了。(cache中就像map一样,有key和value,根据key来取value值)。


比如下面代码,虽然参数值不一样但是key是相同的。


public static void main(String argv[])
	{
		DefaultKeyGenerator g  = new DefaultKeyGenerator();
		Integer param0 = 1000000759;
		String param1 = "11";
		System.out.println(" param0="+param0+", param1="+param1+"  generate key: "+g.generate(null,null,param0,param1));
		Integer param01 = 1000000757;
		String param11 = "31";
		System.out.println("param01="+param01+",param11="+param11+"  generate key: "+g.generate(null,null,param01,param11));
	}


运行结果如下:




---------------------------------------------------------------------------版权声明------------------------------------------------------------------------------------------

版权声明:本文为博主原创文章,未经博主允许不得转载。博客地址:http://blog.csdn.net/mr_smile2014





以上是关于使用缓存cache 的大坑的主要内容,如果未能解决你的问题,请参考以下文章

如何使控制台中的视图缓存片段过期?

在每个用户的Rails中使用片段缓存

如何在 Django 中显式重置模板片段缓存?

phalcon: 缓存片段,文件缓存,memcache缓存

Apollo 可以从缓存中读取部分片段吗?

Rails:旧数据与新数据不匹配时如何更新片段缓存