springboot之项目集群生成不同的hashcode导致缓存不一致。

场景:

集群项目使用访问策略使用的随机,缓存使用的redis,自定义key当传入两个参数以上时候,使用Arrays.deepHashCode来计算缓存的key。但是由于被缓存的方法有个固定的User.class参数,不过在deepHashCode方法中这个class不同的机器生成不同的值,导致产生的hashcode不一样

发现问题:

然后出现在机器1刚访问过这个接口,redis也有缓存,访问到机器2的时候仍然走service方法,也就是没有从redis取缓存。

(从日志看是否走的缓存,在自定义key生成里面打上日志,和接口调用的service打上日志,如果走了自定义key方法两遍就是在生成缓存,如果走一遍自定义key这个方法就是取的缓存)

然后找日志,同一个接口,在访问到不同机器的时候,生成的缓存key不一样,所以导致每个机器都需要缓存一遍。

原因:生成hash key的方法为Arrays.deepHashCode看方法,没有对class类型的判断

public static int deepHashCode(Object a[]) {
        if (a == null)
            return 0;

        int result = 1;

        for (Object element : a) {
            int elementHash = 0;
            if (element instanceof Object[])
                elementHash = deepHashCode((Object[]) element);
            else if (element instanceof byte[])
                elementHash = hashCode((byte[]) element);
            else if (element instanceof short[])
                elementHash = hashCode((short[]) element);
            else if (element instanceof int[])
                elementHash = hashCode((int[]) element);
            else if (element instanceof long[])
                elementHash = hashCode((long[]) element);
            else if (element instanceof char[])
                elementHash = hashCode((char[]) element);
            else if (element instanceof float[])
                elementHash = hashCode((float[]) element);
            else if (element instanceof double[])
                elementHash = hashCode((double[]) element);
            else if (element instanceof boolean[])
                elementHash = hashCode((boolean[]) element);
            else if (element != null)
                elementHash = element.hashCode();

            result = 31 * result + elementHash;
        }

        return result;
    }

查看User.class参数生成缓存key的时候,每台机器生成的代理class内容不一样,然后导致使用这个class内容生成的缓存不一致。所以集群情况下就会导致同一接口,不同机器生成各自的缓存key。

重写一下deepHashCode,这是改好的结果

可以在集群情况下。每个机器上,相同参数的情况下,保持生成的hash key一致。

这样就可以保证,在一个机器上生成缓存,下次请求到另外一个机器,仍然可以使用这个缓存。

public static int deepHashCode(Object a[]) {
        if (a == null)
            return 0;

        int result = 1;

        for (Object element : a) {
            int elementHash = 0;
            if (element instanceof Object[])
                elementHash = deepHashCode((Object[]) element);
            else if (element instanceof byte[])
                elementHash = hashCode((byte[]) element);
            else if (element instanceof short[])
                elementHash = hashCode((short[]) element);
            else if (element instanceof int[])
                elementHash = hashCode((int[]) element);
            else if (element instanceof long[])
                elementHash = hashCode((long[]) element);
            else if (element instanceof char[])
                elementHash = hashCode((char[]) element);
            else if (element instanceof float[])
                elementHash = hashCode((float[]) element);
            else if (element instanceof double[])
                elementHash = hashCode((double[]) element);
            else if (element instanceof boolean[])
                elementHash = hashCode((boolean[]) element);
            else if (element instanceof class)
                elementHash = hashCode((element.toString());
            else if (element != null)
                elementHash = element.hashCode();

            result = 31 * result + elementHash;
        }

        return result;
    }

这一句, else if (element instanceof class)
                elementHash = hashCode((element.toString());

加上对class的判断,对class做toString就会在不同机器产生一样的calss了,所以生成的hashcode一样。缓存就不变了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值