Giter Site home page Giter Site logo

jetcache's Introduction

Java CI with Maven Coverage Status GitHub release License Project Map

Introduction

JetCache is a Java cache abstraction which provides uniform usage for different caching solutions. It provides more powerful annotations than those in Spring Cache. The annotations in JetCache supports native TTL, two level caching, and automatically refresh in distrubuted environments, also you can manipulate Cache instance by your code. Currently, there are four implementations: RedisCache, TairCache(not open source on github), CaffeineCache (in memory) and a simple LinkedHashMapCache (in memory). Full features of JetCache:

  • Manipulate cache through uniform Cache API.
  • Declarative method caching using annotations with TTL(Time To Live) and two level caching support
  • Create & configure Cache instance with cache manager
  • Automatically collect access statistics for Cache instance and method level cache
  • The strategy of key generation and value serialization can be customized
  • Cache key convertor supported: fastjson/fastjson2/jackson; Value convertor supported: java/kryo/kryo5
  • Distributed cache auto refresh and distributed lock. (2.2+)
  • Asynchronous access using Cache API (2.2+, with redis lettuce client)
  • Invalidate local caches (in all JVM process) after updates (2.7+)
  • Spring Boot support

requirements:

  • JDK1.8
  • Spring Framework4.0.8+ (optional, with annotation support),jetcache 2.7 need 5.2.4+
  • Spring Boot1.1.9+ (optional), jetcache 2.7 need 2.2.5+

Visit docs for more details.

Getting started

Method cache

Declare method cache using @Cached annotation.
expire = 3600 indicates that the elements will expire in 3600 seconds after being set. JetCache automatically generates the cache key with all the parameters.

public interface UserService {
    @Cached(expire = 3600, cacheType = CacheType.REMOTE)
    User getUserById(long userId);
}

Using key attribute to specify cache key using SpEL script.

public interface UserService {
    @Cached(name="userCache-", key="#userId", expire = 3600)
    User getUserById(long userId);

    @CacheUpdate(name="userCache-", key="#user.userId", value="#user")
    void updateUser(User user);

    @CacheInvalidate(name="userCache-", key="#userId")
    void deleteUser(long userId);
}

In order to use parameter name such as key="#userId", you javac compiler target must be 1.8 and above, and the -parameters should be set. Otherwise, use index to access parameters like key="args[0]"

Auto refreshment:

public interface SummaryService{
    @Cached(expire = 3600, cacheType = CacheType.REMOTE)
    @CacheRefresh(refresh = 1800, stopRefreshAfterLastAccess = 3600, timeUnit = TimeUnit.SECONDS)
    @CachePenetrationProtect
    BigDecimal summaryOfToday(long categoryId);
}

CachePenetrationProtect annotation indicates that the cache will be loaded synchronously in multi-thread environment.

Cache API

Create a Cache instance with CacheManager:

@Autowired
private CacheManager cacheManager;
private Cache<String, UserDO> userCache;

@PostConstruct
public void init() {
    QuickConfig qc = QuickConfig.newBuilder("userCache")
        .expire(Duration.ofSeconds(100))
        .cacheType(CacheType.BOTH) // two level cache
        .localLimit(50)
        .syncLocal(true) // invalidate local cache in all jvm process after update
        .build();
    userCache = cacheManager.getOrCreateCache(qc);
}

The code above create a Cache instance. cacheType = CacheType.BOTH define a two level cache (a local in-memory-cache and a remote cache system) with local elements limited upper to 50(LRU based evict). You can use it like a map:

UserDO user = userCache.get(12345L);
userCache.put(12345L, loadUserFromDataBase(12345L));
userCache.remove(12345L);

userCache.computeIfAbsent(1234567L, (key) -> loadUserFromDataBase(1234567L));

Advanced API

Asynchronous API:

CacheGetResult r = cache.GET(userId);
CompletionStage<ResultData> future = r.future();
future.thenRun(() -> {
    if(r.isSuccess()){
        System.out.println(r.getValue());
    }
});

Distributed lock:

cache.tryLockAndRun("key", 60, TimeUnit.SECONDS, () -> heavyDatabaseOperation());

Read through and auto refresh:

@Autowired
private CacheManager cacheManager;
private Cache<String, Long> orderSumCache;

@PostConstruct
public void init() {
    QuickConfig qc = QuickConfig.newBuilder("userCache")
        .expire(Duration.ofSeconds(3600))
        .loader(this::loadOrderSumFromDatabase)
        .refreshPolicy(RefreshPolicy.newPolicy(60, TimeUnit.SECONDS).stopRefreshAfterLastAccess(100, TimeUnit.SECONDS))
        .penetrationProtect(true)
        .build();
    orderSumCache = cacheManager.getOrCreateCache(qc);
}

Configuration with Spring Boot

pom:

<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-starter-redis</artifactId>
    <version>${jetcache.latest.version}</version>
</dependency>

App class:

@SpringBootApplication
@EnableMethodCache(basePackages = "com.company.mypackage")
@EnableCreateCacheAnnotation // deprecated in jetcache 2.7, can be removed if @CreateCache is not used
public class MySpringBootApp {
    public static void main(String[] args) {
        SpringApplication.run(MySpringBootApp.class);
    }
}

spring boot application.yml config:

jetcache:
  statIntervalMinutes: 15
  areaInCacheName: false
  local:
    default:
      type: linkedhashmap #other choose:caffeine
      keyConvertor: fastjson2 #other choose:fastjson/jackson
      limit: 100
  remote:
    default:
      type: redis
      keyConvertor: fastjson2 #other choose:fastjson/jackson
      broadcastChannel: projectA
      valueEncoder: java #other choose:kryo/kryo5
      valueDecoder: java #other choose:kryo/kryo5
      poolConfig:
        minIdle: 5
        maxIdle: 20
        maxTotal: 50
      host: ${redis.host}
      port: ${redis.port}

Visit detail configuration for more instructions

More docs

Visit docs for more details.

For upgrade see changelog and compatibility notes.

jetcache's People

Contributors

alexkarezin avatar amjad1210 avatar areyouok avatar awei2020 avatar blindpirate avatar celebrate-future avatar charlesvhe avatar chenchi2038 avatar chunmenglu avatar codejam-cn avatar cpugputpu avatar darknesstm avatar dependabot[bot] avatar devefx avatar dylan-tao avatar hhhhhhgggggg avatar ivan97 avatar javalover123 avatar jeasonyoung avatar kenvifire avatar magestacks avatar pthariensflame avatar roiocam avatar rotbor avatar sao-broken-legs avatar scolia avatar w-a-n-g-s-h-u-n avatar xiaolongyuan avatar xiezheng-xd avatar zt9788 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jetcache's Issues

完成打包和集成

JetCache 2.1.2的代码已经在github上了,这个版本在内部发布过,是可用的。

现在还没有部署到**仓库,当第一次部署到**仓库的时候,版本号应该是2.1.3。

此外,持续集成工具travis-ci和codecov也应该集成进来。travis-ci现在已经ok了,但是codecov还没有完全搞好。实际上JetCache的单元测试覆盖率还是挺高的(在IDEA里面看),但因为它使用了一个专门的工程来放单元测试(为了共享一些测试类和资源),导致现在跑出来的覆盖率结果非常不体面,我甚至怀疑还能不能搞好。

当这些完成以后,readme需要做相关修改。最后再完成发布。

缓存自动刷新对二级缓存不起作用

    @Cached(name = ":message", key = "#id", expire = 2, cacheType = CacheType.BOTH)
    @CacheRefresh(refresh = 1, stopRefreshAfterLastAccess = 1800)
    public String getMessage(int id) {
        log.info("get message {}", id);
        return String.format("message %d is %s", id, System.currentTimeMillis());
    }

缓存类型设置为local或者remote的时候,自动刷新都能起作用,但是设置为both的时候,缓存就没有自动刷新了,是不支持么?

Redis集群支持

目前JetCache使用jedis作为连接redis的客户端,配置一个redis.clients.util.Pool就可以(可以是它的子类JedisPool、JedisSentinelPool)。这样可以连基于Sentinel的主备Redis。

jedis自身声称对于Redis cluster specification的支持是“still under development”。连接集群需要使用JedisCluster,目前JetCache还没有对此进行支持。

做起来应该不麻烦,但是目前还没有这样的案例。

java.lang.ClassCastException: com.liuhaozzu.spring.data.investigation.entity.Customer cannot be cast to com.liuhaozzu.spring.data.investigation.entity.Customer

affected Version: 2.4.4

java.lang.ClassCastException: com.liuhaozzu.spring.data.investigation.entity.Customer cannot be cast to com.liuhaozzu.spring.data.investigation.entity.Customer
at com.sun.proxy.$Proxy129.getCustomer(Unknown Source) at com.liuhaozzu.spring.data.investigation.controller.ItemController.getCustomer(ItemController.java:37) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [05-08 00:37:38 577 DEBUG] [http-nio-8080-exec-4] factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.EndpointWebMvcHypermediaManagementContextConfiguration$ActuatorEndpointLinksAdvice' [05-08 00:37:38 577 DEBUG] [http-nio-8080-exec-4] web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling [05-08 00:37:38 577 DEBUG] [http-nio-8080-exec-4] jpa.support.OpenEntityManagerInViewInterceptor - Closing JPA EntityManager in OpenEntityManagerInViewInterceptor [05-08 00:37:38 577 DEBUG] [http-nio-8080-exec-4] orm.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager [05-08 00:37:38 577 DEBUG] [http-nio-8080-exec-4] web.servlet.DispatcherServlet - Successfully completed request [05-08 00:37:38 577 DEBUG] [http-nio-8080-exec-4] web.filter.OrderedRequestContextFilter - Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@7de37eaf at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745)

jetcache是否支持二级key?

redis支持field,即:key/value中的value可以是HashMap,且支持HashMapvalue的TTL管理。

我看了上一个issue #10 中你的回复,你有提到jetcache定位是一个多级cache的集合组件,但这样势必会舍弃一些noSQL数据库本身的特性。
冒犯问一下,未来jetcache还会有哪些改进呢?我个人对jetcache项目比较感兴趣哈!

KeyGenerator

Hi,

I'm moving over from Spring cache to Jetcache but can't seem to figure out the best way to specify a global key generator.

In spring cache this was achieved by the code below:

    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return (o, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(method.getDeclaringClass().getSimpleName());
            sb.append("_");
            sb.append(method.getName());
            for (Object param : params) {
                sb.append("_");
                sb.append(param.toString());
            }
            return sb.toString();
        };
    }

The reason i need this is because i have some subclasses which need to have a different cache name hence the usage of method.getDeclaringClass().getSimpleName().

Can you maybe tell me what the easiest way to achieve this in Jetcache would be?

Thanks

Roadmap

  • golang version: implements jetcache core api
  • python version: implements jetcache core api
  • (2.X) java version: interoperable with golang and python version
  • (3.X) java version: enhance Cache API and implement jsr-107 specification

降低缓存失效时刻对数据库的压力

当缓存失效时,后端数据库的压力会比较大。

在JetCache的上个版本中,两级缓存的失效时间是不严格的,本地和远程可能不会在同一时刻失效,但这样超时时间就不是很精确,在2.0以后的版本中对此进行了矫正。

所以如果访问量特别大,现在就更加容易引起雪崩效应。需要有个机制来进行一下缓解,针对同一个key,至少一个jvm里面应该只有一个线程去加载。

方法缓存和Cache接口的computeIfAbsent都需要支持它。

ClassCastException cacheType=BOTH后,有时候会报错.

java.lang.ClassCastException: java.util.ArrayList cannot be cast to com.alicp.jetcache.CacheValueHolder
at com.alicp.jetcache.MultiLevelCache.do_GET(MultiLevelCache.java:57)
at com.alicp.jetcache.AbstractCache.GET(AbstractCache.java:58)
at com.alicp.jetcache.RefreshCache.GET(RefreshCache.java:107)
at com.alicp.jetcache.anno.method.CacheHandler.invokeWithCache(CacheHandler.java:131)
at com.alicp.jetcache.anno.method.CacheHandler.doInvoke(CacheHandler.java:106)
at com.alicp.jetcache.anno.method.CacheHandler.invoke(CacheHandler.java:99)
at com.alicp.jetcache.anno.aop.JetCacheInterceptor.invoke(JetCacheInterceptor.java:69)

@Autowired方式拿不到JedisPool

如果需要直接操作JedisPool,可以通过以下方式获取

@bean(name = "defaultPool")
@dependsOn(RedisAutoConfiguration.AUTO_INIT_BEAN_NAME)
public JedisPoolFactory defaultPool() {
return new JedisPoolFactory("remote.default");
}
然后可以直接使用

@Autowired
private JedisPool defaultPool;

报错:
Field defaultPool in com.alicp.jetcache.autoconfigure.StarterTest required a bean of type 'redis.clients.jedis.JedisPool' that could not be found.

估计容器里,只有JedisPoolFactory 没有JedisPool

整合spring boot1.4.2报错

刚开始以为一直是commons-pool和commons-pool2版本的冲突,排除掉jar后还是不行


org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisAutoInit': Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: redis.clients.jedis.JedisPool.<init>(Lorg/apache/commons/pool2/impl/GenericObjectPoolConfig;Ljava/lang/String;IILjava/lang/String;ILjava/lang/String;Z)V
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:408) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1575) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:751) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861) ~[spring-context-4.3.3.RELEASE.jar:4.3.3.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541) ~[spring-context-4.3.3.RELEASE.jar:4.3.3.RELEASE]
	at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.4.1.RELEASE.jar:1.4.1.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:761) ~[spring-boot-1.4.1.RELEASE.jar:1.4.1.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:371) ~[spring-boot-1.4.1.RELEASE.jar:1.4.1.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-1.4.1.RELEASE.jar:1.4.1.RELEASE]
	at com.cxytiandi.Application.main(Application.java:28) [classes/:na]
Caused by: java.lang.NoSuchMethodError: redis.clients.jedis.JedisPool.<init>(Lorg/apache/commons/pool2/impl/GenericObjectPoolConfig;Ljava/lang/String;IILjava/lang/String;ILjava/lang/String;Z)V
	at com.alicp.jetcache.autoconfigure.RedisAutoConfiguration$RedisAutoInit.initCache(RedisAutoConfiguration.java:79) ~[jetcache-autoconfigure-2.2.0.Beta4.jar:na]
	at com.alicp.jetcache.autoconfigure.AbstractCacheAutoInit.process(AbstractCacheAutoInit.java:73) ~[jetcache-autoconfigure-2.2.0.Beta4.jar:na]
	at com.alicp.jetcache.autoconfigure.AbstractCacheAutoInit.init(AbstractCacheAutoInit.java:55) ~[jetcache-autoconfigure-2.2.0.Beta4.jar:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45]
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_45]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_45]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_45]
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:365) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:310) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
	... 16 common frames omitted


@Cached注解支持在class上使用

目前@Cached@@CacheRefresh注解都只能在方法上使用,如果一个class中有很多方法需要缓存,它们的缓存配置基本都大致相同,比如area、name、cacheType、refresh等,这些配置在每个方法上都要写一遍,比较繁琐。
希望这两个注解也可以写在class上,作为class内各个方法缓存参数的默认值,method上的缓存参数优先级较高,可以覆盖class上设置的参数。

value identity number配置

现在value做序列化的时候,在前面先写了4个字节作为标识符,昨天的一个提交使得decoder能够自动按标识符解码。

不过,如果需要使用jetcache和其他的程序同时读写一个key,就不应该写入identity number。这应该做成一个配置。

lettuce5 support

  • support lettuce5 in JetCache 2.3.
  • rename current lettuce 4 support artifact jetcache-redis-luttece, jetcache-starter-redis-luttece to jetcache-redis-lettuce4, jetcache-starter-redis-lettuce4.

lettuce 5 changed maven groupId and java package name, so lettuce 4 and lettuce 5 support can both exists.

@Cached能否预防缓存击穿 和多级缓存设置不同的expire

@areyouok
首先这是个非常好的项目,解决了一些缓存使用过程中的痛点,并且封装的很易用。
提两个需求,看看是否合理

  1. @cached注解目前不能预防缓存击穿,并发访问时,会造成并发加载,能否做到至少在一个JVM中的缓存加载的锁控制
  2. 目前多级缓存(本地+redis)在@cached中设置的expire是相同的,是否可以在@cached中直接设置不同的expire呢?常规来说本地缓存有效期应该比远程缓存要短很多才合理

MultiLevelCache报"cannot be cast to com.alicp.jetcache.CacheValueHolder"

import com.alicp.jetcache.Cache;
import com.alicp.jetcache.MultiLevelCacheBuilder;
import com.alicp.jetcache.embedded.LinkedHashMapCacheBuilder;

import java.util.concurrent.TimeUnit;

/**
 * Created by eros on 2017/9/9.
 */
public class MultiCacheTest {

    public static void main(String args[]){
        String s = multiLevelCache.get(1001L);
        System.out.println(s);
    }

    static String loadFromDb(Long key) {
        return "hahaha";
    }

    static Cache<Long, String> l1Cache = LinkedHashMapCacheBuilder.createLinkedHashMapCacheBuilder()
            .limit(100)
            .expireAfterWrite(200, TimeUnit.SECONDS)
            // 这边调用的时候, 必须要使用强转
            .loader(key -> loadFromDb((Long)key))
            .buildCache();

    static Cache<Long, String> l2Cache = LinkedHashMapCacheBuilder.createLinkedHashMapCacheBuilder()
            .limit(100)
            .expireAfterWrite(200, TimeUnit.SECONDS)
            .loader(key -> loadFromDb((Long)key))
            .buildCache();

    static Cache<Long, String> multiLevelCache = MultiLevelCacheBuilder.createMultiLevelCacheBuilder()
            .addCache(l1Cache, l2Cache)
            .expireAfterWrite(100, TimeUnit.SECONDS)
            .buildCache();
}

跑main函数的时候, 会报错

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to com.alicp.jetcache.CacheValueHolder
	at com.alicp.jetcache.MultiLevelCache.do_GET(MultiLevelCache.java:57)
	at com.alicp.jetcache.AbstractCache.GET(AbstractCache.java:58)
	at com.alicp.jetcache.Cache.get(Cache.java:34)
	at io.terminus.parana.category.service.MultiCacheTest.main(MultiCacheTest.java:15)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

json value序列化器

jetcache老版本中是有三个序列化器的:java、kryo、fastjson。

但是fastjson做序列化兼容性不是特别好,某次升级以后单元测试就无法通过了,最后把它废弃了。
现在默认的序列化器是性能最差,但是兼容性最好,大家也最熟悉的java序列化器。

我一直在想要不要找个json的序列化器回来,毕竟json可读性是最好的。

是否考虑支持下移除缓存?

spring cache没有支持ttl确实很不方便,但没有移除缓存更不方便。请问当缓存的对象发生了变化,怎么处理呢?

解析容器名+端口形式配置错误

jetcache:
areaInCacheName: false
remote:
default:
type: redis.lettuce
keyConvertor: fastjson
uri:
- redis://grokzen__redis-cluster:7000
- redis://grokzen__redis-cluster:7001
- redis://grokzen__redis-cluster:7002

我的配置如图,在CI中redis集群地址为这种形式,但是在解析过程中出错,报错如下:

Suppressed: io.lettuce.core.RedisConnectionException: Unable to connect to grokzen__redis-cluster:7002:6379

应该是RedisLettuceAutoConfiguration中的RedisURI.create(URI.create(k.toString()))这个地方,URI解析出错,能有什么解决办法吗,谢谢

是否可以使用jetcache的"自动刷新缓存"做应用的数据闭环?

比如商品详情页的依赖卖家数据(需要展示卖家信息), 而商品中心往往和卖家中心是两个独立的中心层服务. 我目前的想法通过jetcache把卖家的全量信息(数据量不大, 大概10w)都缓存到商品中心的本地内存中. 通过RefreshPolicy保证每十分钟和卖家中心同步. 这样即便卖家中心挂掉, 也不会导致商品详情页数据缺失(即便挂掉可以使用老的卖家数据).

从文档中, 我只看到用"自动刷新缓存"来避免缓存雪崩, 不知道贵司是否也有用jetcache解决数据闭环的问题?

懒加载属性,读取缓存后执行序列化产生异常

当实体中存在懒加载属性的时候,读取缓存的对象后,进行序列化操作,会产生异常。
属性定义:

@OneToMany(mappedBy="topic",fetch = FetchType.LAZY)
	public List<TopicTags> getTopicTags() {
		return topicTags;
	}

序列化操作:
```
@OverRide
public void serialize(Result value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {

	jgen.writeStartObject();
	jgen.writeStringField("result", value.getResult().toString());
	jgen.writeNumberField("code", value.getCode());
	jgen.writeStringField("reason", value.getReason());		
	jgen.writeFieldName("content");
	jgen.writeStartArray();
	for (Object obj : value.getContent()) {
		objectWriter.writeValue(jgen, obj);
	}
	jgen.writeEndArray();
	jgen.writeEndObject();

}
异常信息:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.my.wxcop.entity.topic.Topic.topicTags, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:576)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:215)
at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:156)
at org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:278)
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:101)
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:24)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:693)
at com.fasterxml.jackson.databind.ser.impl.FilteredBeanPropertyWriter$SingleView.serializeAsField(FilteredBeanPropertyWriter.java:67)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:675)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1387)
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:889)
at com.my.common.editor.ResultSerializer.serialize(ResultSerializer.java:59)
at com.my.common.editor.ResultSerializer.serialize(ResultSerializer.java:17)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1387)
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:889)

@Cached name use complex parameters

方法缓存支持复杂的参数类型,也支持多参数,它使用keyConvertor将参数数组转换成底层缓存可以支持的key类型,当前唯一可用的keyConvertor是fastjson。fastjson使用getter/setter来分析类,因此复杂的参数类型也需要是一个javabean。

能不能给个例子?? 像下面这样写, 感觉不是使用json解析的,请给个例子吧...
aaaa是一个List入参
@cached(expire = 1000, name = "#aaaa", keyConvertor = KeyConvertor.FASTJSON)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.