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

shz.cache.redis.RedisCache Maven / Gradle / Ivy

package shz.cache.redis;

import shz.Validator;
import shz.cache.*;
import shz.PRException;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.concurrent.CountDownLatch;
import java.util.function.Function;

public abstract class RedisCache extends CacheManager {
    @Override
    protected boolean isSelect(CacheOperate operate) {
        switch ((Jco) operate) {
            case DEL:
            case HDEL:
                return false;
            case GET:
            case HGET:
            case LRANGE:
            case SMEMBERS:
                return true;
            default:
                throw new UnsupportedOperationException();
        }
    }

    @Override
    protected final String getNullKey(CacheParam param) {
        return param.key() + ":" + ((RedisCacheParam) param).hashKey;
    }

    public final Object execute(Method method, Object[] args, Function func) {
        RedisCacheable cacheable = method.getAnnotation(RedisCacheable.class);
        //没有注解直接走目标方法,一般在方法增强时就已经指定注解
        if (cacheable == null) return func.apply(args);
        Jco operate = cacheable.operate();
        Parameter[] parameters = method.getParameters();
        //获取缓存key
        String key = Cache.generateKey(cacheable.key(), args, parameters, CacheKey.class, CacheKey::keys);
        //获取缓存参数
        RedisCacheParam cacheParam = new RedisCacheParam(operate, key, cacheable.db(), cacheable.time(), cacheable.unit(), cacheable.regexes(),
                Cache.generateKey("", args, parameters, HashKey.class, HashKey::keys)
        );

        Class returnType = method.getReturnType();
        boolean possible = false;
        Object response = null;
        //查询操作
        if (isSelect(operate)) {
            //布隆过滤器优先匹配
            if (notMatch(cacheParam)) return Validator.empty(returnType);
            cacheParam.nullKey(getNullKey(cacheParam));
            //判断是否null标识
            if (isNull(cacheParam)) return Validator.empty(returnType);
            //获取缓存
            response = get(cacheParam);
            if (!responseIsEmpty(response)) return response;
            //缓存失效或者误判,设置可能 null标识(一种中间状态),设置成功就去查数据库
            if (!(possible = setPossibleNull(cacheParam))) {
                //没有设置成功等待
                CountDownLatch latch = new CountDownLatch(1);
                try {
                    latch.await(cacheable.timeout(), cacheable.unit());
                } catch (InterruptedException ignored) {
                }
                //再次判断(上一个线程可能查完了数据库,最终可能判断这个key为null标识)
                if (isNull(cacheParam)) return Validator.empty(returnType);
                //再次获取
                response = get(cacheParam);
                if (!responseIsEmpty(response)) return response;
                //出现这种情况,可能上一个线程设置缓存失败,也可能是出现异常

                //如果是设置缓存失败,说明查询过数据库,继续执行数据库查询
                if (!(possible = setPossibleNull(cacheParam)))
                    //如果是异常,则直接返回
                    //大量放行这种查询,结果也是等不到的,反而会搞垮数据库
                    return Validator.empty(returnType);
            }
        }

        try {
            //执行目标方法
            response = func.apply(args);
            return response;
        } catch (Throwable t) {
            throw PRException.of(t);
        } finally {
            try {
                after(cacheParam, response);
            } finally {
                if (possible) {
                    try {
                        //数据库没查到,则设置null标识
                        if (responseIsEmpty(response)) setNull(cacheParam);
                    } finally {
                        //清除可能标识
                        removePossibleNull(cacheParam);
                    }
                }
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy