All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.kould.core.impl.BaseCacheHandler Maven / Gradle / Ivy

package com.kould.core.impl;

import com.kould.api.Kache;
import com.kould.entity.Status;
import com.kould.core.CacheHandler;
import com.kould.entity.NullValue;
import com.kould.exception.KacheAsyncWriteException;
import com.kould.function.KeyFunction;
import com.kould.function.ReadFunction;
import com.kould.function.WriteFunction;
import com.kould.listener.ListenerHandler;
import com.kould.entity.MethodPoint;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

public class BaseCacheHandler extends CacheHandler {

    private static final Map> FUTURE_INDEX = new ConcurrentHashMap<>();

    @Override
    public Object load(MethodPoint point, boolean listenerEnable, ReadFunction readFunction
            , WriteFunction writeFunction, KeyFunction keyFunction , String types, Status methodStatus) throws Exception {
        Method daoMethod = point.getMethod();
        String methodName = daoMethod.getName() ;
        //该PO领域的初始化
        //需要使用types表示其所涉及的缓存Bean的Class
        String key = keyFunction.encode(point, methodName, types, methodStatus);
        //对types进行处理,获取其主缓存Bean的Class名传入
        String mainType = types.split(Kache.SPLIT_TAG, 2)[0];
        //key拼接命名空间前缀
        Object[] daoArgs = point.getArgs();
        //以PO类型进行不同持久类领域的划分并拼接参数与方法作为幂等凭据
        String lockKey = (mainType + methodName + Arrays.hashCode(daoArgs));
        //获取缓存
        Object result = readFunction.read(key , mainType);
        if (result == null) {
            // 通过新建Future进行异步写入,FUTURE_INDEX保证线程安全避免重复写入
            // 避免纵向(单一节点)击穿,而允许横向(分布式)击穿
            CompletableFuture completableFuture = FUTURE_INDEX.computeIfAbsent(lockKey, k -> CompletableFuture.supplyAsync(() -> {
                try {
                    ListenerHandler.notHit(key, methodName, daoArgs, mainType, listenerEnable);
                    return writeFunction.write(key , point, mainType);
                } catch (Exception e) {
                    throw new KacheAsyncWriteException(e.getMessage(),e);
                }
            }));
            // 堵塞读取,聚集该击穿至写入时间内的线程统一获取数据并解除堵塞
            result = completableFuture.get();
            // 该次击穿结束,移除该Future帧避免下次击穿获取脏值
            FUTURE_INDEX.remove(lockKey);
        } else {
            ListenerHandler.hit(key, methodName, daoArgs, mainType, listenerEnable);
        }
        //空值替换
        if (result instanceof NullValue) {
            result = null ;
        }
        return result;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy