Java_缓存_Guava

Java_缓存_Guava

  • 简介
  • 限流
  • 缓存

简介

适用于单节点,不适用分布式

限流

1、引入依赖


     com.google.guava
     guava
     25.1-jre

2、自定义注解

/**
 * 自定义注解  限流
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public  @interface ServiceLimit {

    /**
     * 描述
     */
    String description()  default "";

    /**
     * key
     */
    String key() default "";

    /**
     * 类型
     */
    LimitType limitType() default LimitType.CUSTOMER;
   
    enum LimitType {
        /**
         * 自定义key
         */
        CUSTOMER,

        /**
         * 根据请求者IP
         */
        IP
    }
}

3、逻辑代码

/**

*限流AOP

*/

@Aspect
@Configuration
public class LimitAspect {

    //根据IP分不同的令牌桶, 每天自动清理缓存
    private static LoadingCache caches = CacheBuilder.newBuilder()
            .maximumSize(1000)
            .expireAfterWrite(1, TimeUnit.DAYS)
            .build(new CacheLoader() {
                @Override
                public RateLimiter load(String key){
                   // 新的IP初始化 每秒只发出5个令牌
                    return RateLimiter.create(5);
                }
            });


    //Service层切点  限流
    @Pointcut("@annotation(com.itstyle.blog.common.limit.ServiceLimit)")
    public void ServiceAspect() {
    }

    @Around("ServiceAspect()")
    public  Object around(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        ServiceLimit limitAnnotation = method.getAnnotation(ServiceLimit.class);
        ServiceLimit.LimitType limitType = limitAnnotation.limitType();
        String key = limitAnnotation.key();
        Object obj;
        try {
            if(limitType.equals(ServiceLimit.LimitType.IP)){
                key = IPUtils.getIpAddr();
            }
            RateLimiter rateLimiter = caches.get(key);
            Boolean flag = rateLimiter.tryAcquire();
            if(flag){
                obj = joinPoint.proceed();
            }else{
                throw new RrException("小同志,你访问的太频繁了");
            }

        } catch (Throwable e) {
            throw new RrException("小同志,你访问的太频繁了");
        }
        return obj;
    }
}

缓存

1、引入依赖


	com.google.guava
	guava
	20.0

2、逻辑代码

import com.google.common.cache.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**    
* @Description: google guava cache工具  
* @author vander
* @Date: Create in 2017/7/12 15:06    
*/
public class LoadingCacheUtils {

	//缓存接口这里是LoadingCache,LoadingCache在缓存项不存在时可以自动加载缓存
	public static LoadingCache cache =
			//CacheBuilder的构造函数是私有的,只能通过其静态方法newBuilder()来获得CacheBuilder的实例
			CacheBuilder.newBuilder()

			//设置并发级别为8,并发级别是指可以同时写缓存的线程数
			.concurrencyLevel(8)

			//设置写缓存后30分钟过期
			.expireAfterWrite(30, TimeUnit.MINUTES)

			//设置缓存容器的初始容量为10
			.initialCapacity(10)

			//设置缓存最大容量为100,超过100之后就会按照LRU最近虽少使用算法来移除缓存项
			.maximumSize(100)

			//设置要统计缓存的命中率
			.recordStats()

			//设置缓存的移除通知
			.removalListener(new RemovalListener() {
				public void onRemoval(RemovalNotification notification) {
				System.out.println(notification+"was removed, cause is "+ notification.getCause());
			}
		})
			//build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存
			.build(new CacheLoader() {
				public String load(String str) throws Exception {
					return str;
				};
			}
	);


	/**
	* ImmutableMap getAllPresent(Iterable keys) 一次获得多个键的缓存值
	put和putAll方法向缓存中添加一个或者多个缓存项
	invalidate 和 invalidateAll方法从缓存中移除缓存项
	asMap()方法获得缓存数据的ConcurrentMap快照
	cleanUp()清空缓存
	refresh(Key) 刷新缓存,即重新取缓存数据,更新缓存
	* @param args
	* @throws ExecutionException
	*/
	public static void main(String[] args) throws ExecutionException {
		// System.out.println(LoadingCacheUtils.cache.get("key"));
		// cache.invalidateAll();
		// cache.put("key","val");
		String val = cache.get("key");
		System.out.println(val);
		System.out.println(cache.stats().toString());//命中率等 情况
	}
}

你可能感兴趣的:(Java)