概述

缓存框架我们有ehcache 和 redis 分别是 本地内存缓存和 分布式缓存框架。在实际情况下如果单台机器 使用ehcache 就可以满足需求了,速度快效率高,有些数据如果需要多台机器共享这个时候怎么办呢,我们需要通过redis,将缓存存放到redis上面。

这也会导致一个问题,因为所有的请求都会到redis读取,当大量的读取会导致大量的网络流量,因此网络流量会成为访问的瓶颈。

J2CACHE就是解决这个问题而生的,缓存分为两级

L1: 进程内缓存(caffeine\ehcache)

L2: Redis/Memcached 集中式缓存

数据读取流程

读取顺序 -> L1 -> L2

缓存先读取L1 ,不存在则读取L2

数据更新

1 从数据库中读取最新数据,依次更新 L1 -> L2 ,发送广播清除某个缓存信息
2 接收到广播(手工清除缓存 & 一级缓存自动失效),从 L1 中清除指定的缓存信息

测试J2CACHE

创建一个maven 项目

引入

<dependency><!-- Ehcache 3.x //-->
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.4.0</version>
</dependency> <dependency>
<groupId>net.oschina.j2cache</groupId>
<artifactId>j2cache-core</artifactId>
<version>2.7.7-release</version>
</dependency>

引入配置文件

ehcache3.xml

j2cache.properties

这个配置文件配置如下:

#J2Cache configuration

#########################################
# Cache Broadcast Method
# values:
# jgroups -> use jgroups's multicast
# redis -> use redis publish/subscribe mechanism (using jedis)
# lettuce -> use redis publish/subscribe mechanism (using lettuce, Recommend)
# rabbitmq -> use RabbitMQ publisher/consumer mechanism
# rocketmq -> use RocketMQ publisher/consumer mechanism
# none -> don't notify the other nodes in cluster
# xx.xxxx.xxxx.Xxxxx your own cache broadcast policy classname that implement net.oschina.j2cache.cluster.ClusterPolicy
######################################### j2cache.broadcast = redis #########################################
# Level 1&2 provider
# values:
# none -> disable this level cache
# ehcache -> use ehcache2 as level 1 cache
# ehcache3 -> use ehcache3 as level 1 cache
# caffeine -> use caffeine as level 1 cache(only in memory)
# redis -> use redis as level 2 cache (using jedis)
# lettuce -> use redis as level 2 cache (using lettuce)
# readonly-redis -> use redis as level 2 cache ,but never write data to it. if use this provider, you must uncomment `j2cache.L2.config_section` to make the redis configurations available.
# memcached -> use memcached as level 2 cache (xmemcached),
# [classname] -> use custom provider
######################################### j2cache.L1.provider_class = ehcache3
j2cache.L2.provider_class = redis # When L2 provider isn't `redis`, using `L2.config_section = redis` to read redis configurations
# j2cache.L2.config_section = redis # Enable/Disable ttl in redis cache data (if disabled, the object in redis will never expire, default:true)
# NOTICE: redis hash mode (redis.storage = hash) do not support this feature)
j2cache.sync_ttl_to_redis = true # Whether to cache null objects by default (default false)
j2cache.default_cache_null_object = true #########################################
# Cache Serialization Provider
# values:
# fst -> using fast-serialization (recommend)
# kyro -> using kyro serialization
# json -> using fst's json serialization (testing)
# fastjson -> using fastjson serialization (embed non-static class not support)
# java -> java standard
# [classname implements Serializer]
######################################### j2cache.serialization = fst
#json.map.person = net.oschina.j2cache.demo.Person #########################################
# Ehcache configuration
######################################### # ehcache.configXml = /ehcache.xml # ehcache3.configXml = /ehcache3.xml
# ehcache3.defaultHeapSize = 1000 #########################################
# Redis connection configuration
######################################### #########################################
# Redis Cluster Mode
#
# single -> single redis server
# sentinel -> master-slaves servers
# cluster -> cluster servers (\u93c1\u7248\u5d41\u6434\u64bb\u53a4\u7f03\ue1bd\u68e4\u93c1\u582c\u7d1d\u6d63\u8de8\u6564 database = 0\u951b\ufffd
# sharded -> sharded servers (\u7035\u55d9\u721c\u9286\u4f79\u669f\u93b9\ue1bc\u7c31\u8e47\u5474\u300f\u9366\ufffd hosts \u6d93\ue15f\u5bda\u7039\u6c3e\u7d1d\u6d93\u65c7\u7e5b\u93ba\u30e6\u775c\u95b0\u5d87\u7586\u93c3\u72b3\u6665 ; redis://user:password@127.0.0.1:6379/0\u951b\ufffd
#
######################################### redis.mode = sentinel #redis storage mode (generic|hash)
redis.storage = generic ## redis pub/sub channel name
redis.channel = j2cache
## redis pub/sub server (using redis.hosts when empty)
redis.channel.host = #cluster name just for sharded
redis.cluster_name = mymaster ## redis cache namespace optional, default[empty]
redis.namespace = ## connection
# Separate multiple redis nodes with commas, such as 192.168.0.10:6379,192.168.0.11:6379,192.168.0.12:6379 redis.hosts = 202.10.79.170:16001,202.10.79.170:16002,202.10.79.170:16003
redis.timeout = 10000
redis.password =
redis.database = 0 ## redis pool properties
redis.maxTotal = 100
redis.maxIdle = 10
redis.maxWaitMillis = 5000
redis.minEvictableIdleTimeMillis = 60000
redis.minIdle = 1
redis.numTestsPerEvictionRun = 10
redis.lifo = false
redis.softMinEvictableIdleTimeMillis = 10
redis.testOnBorrow = true
redis.testOnReturn = false
redis.testWhileIdle = true
redis.timeBetweenEvictionRunsMillis = 300000
redis.blockWhenExhausted = false
redis.jmxEnabled = false

广播方式使用redis

j2cache.broadcast = redis
L1,L2 缓存实现方法
j2cache.L1.provider_class = ehcache3
j2cache.L2.provider_class = redis
redis 使用哨兵模式进行配置。

使用代码进行测试

编写测试代码如下:

读取缓存

public static void main(String[] args) throws InterruptedException {

        CacheChannel cache = J2Cache.getChannel();
while(true){
System.out.println(cache.get("user", "name"));
Thread.sleep(2000);
}
}

这个代码会一直读取 user:name 的缓存。

我们需要测试的是,当一个客户端设置一个 user:name 的缓存时,这个代码能反映缓存的变化。

设置缓存:

public static void main(String[] args) {

        CacheChannel cache = J2Cache.getChannel();
cache.set("user", "name", "A");
cache.close();
}

首先设置一个A的缓存。

我们可以看到第一个代码返回的是如下情况

[user,name,L2]=>A
[user,name,L1]=>A
[user,name,L1]=>A

它会先从 redis读取,在读取本地。

我们在设置一次:

public static void main(String[] args) {

        CacheChannel cache = J2Cache.getChannel();
cache.set("user", "name", "B");
cache.close();
}

第二次我们这个name 为 B,这个时候我们可以发现:

[user,name,L2]=>B
[user,name,L1]=>B
[user,name,L1]=>B

缓存变成了B ,而且是先读取 REDIS ,在读取 EHCACHE缓存,即先读取 L2 再读取L1。

这样我们的缓存就既能保证性能,有可以保证缓存及时被更新。

J2CACHE 两级缓存框架的更多相关文章

  1. Spring+ehcache+redis两级缓存

    问题描述 场景:我们的应用系统是分布式集群的,可横向扩展的.应用中某个接口操作满足以下一个或多个条件: 1. 接口运行复杂代价大, 2. 接口返回数据量大, 3. 接口的数据基本不会更改, 4. 接口 ...

  2. 用guava快速打造两级缓存能力

    首先,咱们都有一共识,即可以使用缓存来提升系统的访问速度! 现如今,分布式缓存这么强大,所以,大部分时候,我们可能都不会去关注本地缓存了! 而在一起高并发的场景,如果我们一味使用nosql式的缓存,如 ...

  3. Redis+Caffeine两级缓存,让访问速度纵享丝滑

    原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 在高性能的服务架构设计中,缓存是一个不可或缺的环节.在实际的项目中,我们通常会将一些热点数据存储到Redis或MemCache这类缓存中间件中, ...

  4. 基于Spring接口,集成Caffeine+Redis两级缓存

    原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 在上一篇文章Redis+Caffeine两级缓存,让访问速度纵享丝滑中,我们介绍了3种整合Caffeine和Redis作为两级缓存使用的方法,虽 ...

  5. J2Cache 和普通缓存框架有何不同,它解决了什么问题?

    不少人看到 J2Cache 第一眼时,会认为这就是一个普普通通的缓存框架,和例如 Ehcache.Caffeine .Spring Cache 之类的项目没什么区别,无非是造了一个新的轮子而已.事实上 ...

  6. springboot中使用自定义两级缓存

    工作中用到了springboot的缓存,使用起来挺方便的,直接引入redis或者ehcache这些缓存依赖包和相关缓存的starter依赖包,然后在启动类中加入@EnableCaching注解,然后在 ...

  7. mybatis两级缓存原理剖析

    https://blog.csdn.net/zhurhyme/article/details/81064108 对于mybatis的缓存认识一直有一个误区,所以今天写一篇文章帮自己订正一下.mybat ...

  8. 阿里开源的缓存框架JetCache

    之前一直在用Spring Cache进行接口数据的缓存,主要是Spring Cache在对具体key缓存失效时间的设置不是很方法,还要自己去扩展,无意中发现了阿里的JetCache.大部分的需求都能满 ...

  9. 数据库历险记(三) | 缓存框架的连环炮 数据库历险记(二) | Redis 和 Mecached 到底哪个好? 数据库历险记(一) | MySQL这么好,为什么还有人用Oracle? 面对海量请求,缓存设计还应该考虑哪些问题?

    数据库历险记(三) | 缓存框架的连环炮   文章首发于微信公众号「陈树义」,专注于 Java 技术分享的社区.点击链接扫描二维码,与500位小伙伴一起共同进步.微信公众号二维码 http://p3n ...

随机推荐

  1. [图文教程]VS2017搭建opencv & C++ 开发环境

    首先从官网下载OpenCV最新版本 截至我写这文章,4.0已经发布预览版了,不过在这是没有的,只能用3.4.2: https://opencv.org/releases.html 一:安装 安装过程不 ...

  2. activate-power-mode效果实验(未完全成功)

    原产地: Atom 支持版本一览 https://github.com/codeinthedark/awesome-power-mode 1.安装Atom:[ AtomSetup-x64.exe] 百 ...

  3. linux中 bashrc文件的alias添加快捷命令

    alias (为了简化命令操作,节省时间) 进入 /home下的用户,假设为 web 执行命令 ls -alh   找到 .bashrc 隐藏文件,如果没有则新建 通过  vi .bashrc  在里 ...

  4. python 的序列化和反序列化

    什么是序列化?简单来说就是将数据存储到物理内存上的过程叫序列化. 什么是反序列化?将数据从物理内存存储到程序内存的过程叫做反序列化. 下面来看一下python中使用json进行序列化和反序列化的实例d ...

  5. 字符串String的API

      字符串的理解 1. 字符串的属性 str.length 2. 字符串的方法 charAt() charCodeAt() indexOf() lastIndexOf() slice() substr ...

  6. Vim 命令、操作、快捷键

    打开单个文件:vim file 同时打开多个文件:vim file1 file2 file3 ... 在vim窗口中打开一个新文件 :  :open file 在新窗口中打开文件: :split fi ...

  7. JAVA 类的三大特性,封装,继承,多态 的一些发现总结

    < 一 > 封装 < 二 > 继承 1,关于父类中的私有属性和方法,子类能不能访问的问题 1.1,子类不能通过继承拥有父类的私有属性和方法 1.2,子类可以从父类继承下来的 方 ...

  8. 使用appium做自动化测试时,send_keyss只能输入字母数字,无法输入中文

    解决方案: driver中增加以下2行配置: "unicodeKeyboard":True, #unicode编码输入 "resetKeyboard":True ...

  9. Gitlab安装与备份恢复

    GitHub是2008年由Ruby on Rails编写而成,与业界闻名的Github类似;但要将代码上传到GitHub上面,而且将项目设为私有还要收费.GitLab是一个用于仓库管理系统的开源项目, ...

  10. python,关于用户登录与注册问题

    tag=Truecount=1while tag: name = input('请输入用户名>>:').strip() password = input('请输入密码>>:') ...