Code Monkey home page Code Monkey logo

l2cache's Introduction

L2Cache 分布式二级缓存框架

Maven Central Crates.io

一、简介

L2Cache 是一个基于内存RedisSpring Cache 实现的满足高并发场景下的分布式二级缓存框架。

L2Cache 并没有重复造轮子,它只是将目前市面上比较成熟、经得起考验的框架组合起来,封装屏蔽了复杂的缓存操作和实现原理,最终给开发者留出了一个简单易懂和易维护的分布式缓存开发工具。

二、如何使用

三、核心原理

四、重要数据

1、整体数据

  • 已在生产环境投产,目前主要应用在商品、优惠券、用户、营销等核心服务。
  • 经历过多年双十一、双十二,以及多次大促活动的流量洗礼
  • 支撑公司单月10亿GMV
  • 支撑全链路压测35W QPS
  • 支撑500w日活

2、下面提供一个【首页重构】时商品中心的压测数据,具体如下:

环境 压测维度 最高QPS 最低QPS 平均RT 配置
单POD 单接口 5k+ 2k+ 50ms内 1个pod,8c16g
集群 单接口 8w+ 1w+ 50ms内 25个pod,8c16g
集群 单链路 4.5w+ 3.5w+ 55ms内 25个pod,8c16g
集群 全链路 35w+ - 55ms内 120个pod,8c16g

特别注意:

  • 由于依赖的资源较多,上面只列出了pod的配置,未列出诸如mq/redis/db/ingress/SLB等资源的配置。
  • 不同接口的QPS不一样,因为业务复杂度和实现逻辑不一样。
  • 压测是对系统的一种整体考量,链路中的任何环节,都对压测有致命的影响。
  • 链路的压测,分为单链路和混合链路。其中,全链路是一种混合链路的压测场景。
  • 上述QPS是在系统的各个指标处于稳定状态的压测值,如果极限施压QPS会更高。

五、核心功能

  • 支持多种缓存类型: 一级缓存、二级缓存、混合缓存
  • 解决痛点问题: 缓存击穿、缓存穿透等
  • 动态缓存配置: 支持动态调整混合缓存下的缓存类型,支持热key的手动配置
  • 缓存一致性保证: 通过消息通知的方式来保证集群环境下一级缓存的一致性
  • 自动热key探测: 自动识别热key并缓存到一级缓存
  • 支持缓存批量操作: 支持分页的批量获取、批量删除等
  • 定义通用缓存层: 承上启下,简化业务开发,规整业务代码

1、同其他开源框架的对比

核心功能 JetCache(阿里) J2Cache(OSChina) L2Cache
支持的缓存类型 一级缓存
二级缓存
混合缓存
一级缓存
二级缓存
混合缓存
一级缓存
二级缓存
混合缓存
解决的痛点问题 缓存击穿
缓存穿透
缓存击穿
缓存穿透
缓存击穿
缓存穿透
缓存一致性保证 支持 支持 支持
动态缓存配置 不支持 不支持 支持
自动热key探测 不支持 不支持 支持
缓存批量操作 不支持 不支持 支持
通用缓存层 不支持 不支持 支持

说明:上面表格的对比,数据正在整理中,后续会再校对一次。

  • 从上面表格的对比可发现,L2Cache 的核心优势为三个点:自动热key探测缓存批量操作通用缓存层
  • 这三点优势是从实际业务开发中沉淀下来的能力,不仅解决了实现多级缓存的复杂性问题,还进一步屏蔽了业务维度的缓存操作的复杂性。
  • 这样一来,原本需要资深开发者才能开发的功能,现在高级和中级开发者,甚至初级开发者都能轻松、高效、高质地进行开发。
  • 如果在实际业务开发中,你也遇到开发难度高,难以维护,难以扩展的痛点问题,建议可以试试L2Cache。反正接入成本低,试试又何妨?

2、L2Cache 的二级缓存结构

1、L1:一级缓存,内存缓存,支持 CaffeineGuava Cache

2、L2:二级缓存,集中式缓存,支持 Redis

3、混合缓存,指支持同时使用一级缓存和二级缓存。

由于大量的缓存读取会导致 L2 的网络成为整个系统的瓶颈,因此 L1 的目标是降低对 L2 的读取次数。避免使用独立缓存系统所带来的网络IO开销问题。L2 可以避免应用重启后导致的 L1数据丢失的问题,同时无需担心L1会增加太多的内存消耗,因为你可以设置 L1中缓存数据的数量。

说明:

L2Cache 满足CAP定理中的AP,也就是满足可用性和分区容错性,至于C(一致性)因为缓存的特性所以无法做到强一致性,只能尽可能的去做到一致性,保证最终的一致。

3、关键点

支持根据配置缓存类型来灵活的组合使用不同的Cache。

1、支持只使用一级缓存CaffeineGuava Cache

2、支持只使用二级缓存Redis

3、支持同时使用一二级缓存Composite

4、必知

若使用缓存,则必然可能出现不一致的情况。

也就是说,无法保证强一致性,只能保证最终一致性。

六、实战问题

七、鼓励与帮助

如果 l2cache 对您有所帮助,不妨右上角点点 Star 或者任意赞赏支持。

您的 Star赞赏 将会给我带来更多动力。

最后,欢迎你 Fork PR 成为项目贡献者。

八、联系方式

微信:chenck1112

weixin

九、已知用户

按照注册顺序,欢迎更多访问公司在#26注册(仅限开源用户)。

l2cache's People

Contributors

ck-jesse avatar dependabot[bot] avatar ju19891326 avatar romeoblog avatar zikezi 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

l2cache's Issues

Spring boot version 2.7.6 java.lang.ClassNotFoundException

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'configurationPropertiesBeans' defined in class path resource [org/springframework/cloud/autoconfigure/ConfigurationPropertiesRebinderAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cloud.context.properties.ConfigurationPropertiesBeans]: Factory method 'configurationPropertiesBeans' threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) ~[spring-beans-5.3.24.jar:5.3.24]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:486) ~[spring-beans-5.3.24.jar:5.3.24]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.24.jar:5.3.24]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.24.jar:5.3.24]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.24.jar:5.3.24]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.24.jar:5.3.24]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.24.jar:5.3.24]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.24.jar:5.3.24]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.24.jar:5.3.24]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213) ~[spring-beans-5.3.24.jar:5.3.24]
at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:270) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:762) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:567) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) [spring-boot-2.7.6.jar:2.7.6]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) [spring-boot-2.7.6.jar:2.7.6]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-2.7.6.jar:2.7.6]
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:164) ~[spring-boot-2.7.6.jar:2.7.6]
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.bootstrapServiceContext(BootstrapApplicationListener.java:191) ~[spring-cloud-context-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:105) ~[spring-cloud-context-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:71) ~[spring-cloud-context-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:85) ~[spring-boot-2.7.6.jar:2.7.6]
at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:66) ~[spring-boot-2.7.6.jar:2.7.6]
at java.util.ArrayList.forEach(ArrayList.java:1259) ~[na:1.8.0_352]
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:120) ~[spring-boot-2.7.6.jar:2.7.6]
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:114) ~[spring-boot-2.7.6.jar:2.7.6]
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:65) ~[spring-boot-2.7.6.jar:2.7.6]
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:343) [spring-boot-2.7.6.jar:2.7.6]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:301) [spring-boot-2.7.6.jar:2.7.6]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) [spring-boot-2.7.6.jar:2.7.6]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) [spring-boot-2.7.6.jar:2.7.6]
at cn.zhaown.todolist2.Todolist2Application.main(Todolist2Application.java:15) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_352]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_352]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_352]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_352]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.7.6.jar:2.7.6]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cloud.context.properties.ConfigurationPropertiesBeans]: Factory method 'configurationPropertiesBeans' threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.3.24.jar:5.3.24]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.24.jar:5.3.24]
... 39 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
at org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration.configurationPropertiesBeans(ConfigurationPropertiesRebinderAutoConfiguration.java:51) ~[spring-cloud-context-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$9b4c5e86.CGLIB$configurationPropertiesBeans$1() ~[spring-cloud-context-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$9b4c5e86$$FastClassBySpringCGLIB$$d19c4827.invoke() ~[spring-cloud-context-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.3.24.jar:5.3.24]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$9b4c5e86.configurationPropertiesBeans() ~[spring-cloud-context-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_352]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_352]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_352]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_352]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.24.jar:5.3.24]
... 40 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata
at java.net.URLClassLoader.findClass(URLClassLoader.java:387) ~[na:1.8.0_352]
at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[na:1.8.0_352]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352) ~[na:1.8.0_352]
at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[na:1.8.0_352]
... 51 common frames omitted

redis 一直sendPing问题

public void run(Timeout timeout) throws Exception {
if (future != null
&& (future.cancel(false) || !future.isSuccess())) {
ctx.channel().close();
if (future.cause() != null) {
log.error("Unable to send PING command over channel: " + ctx.channel(), future.cause());
}
log.debug("channel: {} closed due to PING response timeout set in {} ms", ctx.channel(), config.getPingConnectionInterval());
} else {
sendPing(ctx);
}
}
}, config.getPingConnectionInterval(), TimeUnit.MILLISECONDS);
在这段代码中 。如果ping成功了后面会再次走else方法ping redis .如果ping失败了则会关闭session并且 5秒重连机制。请问下这个是设定如此还是代码bug。频繁ping会不会增加服务器的性能消耗

热点探测

本来以为是框架自带的,原来是接入了jd的hotkey.哈哈哈

请问是否有支持缓存双删的计划

我正在使用您的仓库,目前发现它提供了二级缓存和缓存过期时间的支持,这对于许多应用场景来说是非常有用的。

在高并发和实时性要求较高的应用中,支持缓存双删可以提供更好的数据一致性,而不依赖于固定的过期时间。并且也可以与缓存过期时间结合使用,以满足不同的需求。

我想了解您是否考虑过在未来的版本中支持缓存双删策略,或者是否可以提供一些关于如何自行实现此策略的指导?任何关于此问题的建议或信息都将对我非常有帮助。

缓存需要添加遍历KEYS的实现

1、扩展多租户机制后,keys需要进行删选,特别的是 clear 方法,会清空所有的数据,所以需要添加,遍历 keys的能力,让第三方自行扩展过滤。oschina j2cache也有keys接口输出
2、redis 使用 spring data redis的 connectionFactory 就可以了,不要自己再去新建。既然是基于SpringBoot 就应该充分利用SpringBoot自身的能力和资源

SpringCache的sync=false情况下刷新问题

从代码中看,在题中的情况下无法做到重新调用load函数从数据源最新数据。因为SpringCache源码中把加载函数抽离了,只调用get(key),该函数中并没有获取到对应的加载函数并添加进Cacheloder,导致一级缓存在refresh过程中,Cacheloader无法获取相应的加载函数,是否有方法解决这个问题?

可能出现一级缓存和二级缓存不一致

看源码中加了一个openedL1Cache变量,注释说明是为了避免缓存不一致,按这个思路发现还是存在缓存不一致的可能性(理论上)。
如下代码中,当执行put时,先更新完二级缓存,此时关闭缓存导致一级缓存未更新。当将要清除一级缓存时此时打开一级缓存配置进而跳过了清除一级缓存的操作

 public void put(Object key, Object value) {
        level2Cache.put(key, value);
        // a. 此时关闭一级缓存,一级缓存未更新
        if (ifL1Open(key)) {
            level1Cache.put(key, value);
        }
        // b. 此时打开一级缓存,
        this.ifEvictL1Cache(key);
    }    

目前支持最高的springboot版本是多少?

目前项目使用2.7.5版本的springboot
启动报错
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata
at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)

谁在使用 L2Cache?

首先,我衷心感谢每一位继续关心和使用 L2Cache 的人。为了更好地倾听用户的声音,吸引更多的人使用和参与,我们期待您提交评论,包括:

  • 您的公司、学校或组织
  • 您所在的城市和国家
  • 您的联系方式:微博、电子邮件、微信(至少一个)
  • 您使用l2cache用于哪些业务场景
  • 您可以参考以下示例来提供您的信息

公司:xxx
网址:https://github.com/ck-jesse/l2cache
地点:**广州
联系方式:[email protected]
场景:电商平台首页、商品详情页缓存

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.