本文目录
一、J2Cache简介
二、数据读取
三、使用方法及实际示例
3.1 引用 Maven
3.2 准备配置
3.3 编写代码
3.3.1 Demo示例
3.3.2 实际案例
四、常见问题
4.1 J2Cache 的使用场景是什么?
4.2 为什么不能在程序中设置缓存的有效期
4.3 如何使用 memcached 作为二级缓存
4.4 使用何种 Redis 的存储模式最佳? generic 还是 hash ?
一、J2Cache简介
J2Cache 是 OSChina 目前正在使用的两级缓存框架(要求至少 Java 8)。第一级缓存使用内存(同时支持 Ehcache 2.x、Ehcache 3.x 和 Caffeine),第二级缓存使用 Redis(推荐)/Memcached 。 由于大量的缓存读取会导致 L2 的网络成为整个系统的瓶颈,因此 L1 的目标是降低对 L2 的读取次数。 该缓存框架主要用于集群环境中。单机也可使用,用于避免应用重启导致的缓存冷启动后对后端业务的冲击。
J2Cache 从 1.3.0 版本开始支持 JGroups 和 Redis Pub/Sub 两种方式进行缓存事件的通知。在某些云平台上可能无法使用 JGroups 组播方式,可以采用 Redis 发布订阅的方式。详情请看 j2cache.properties 配置文件的说明。
视频介绍:http://v.youku.com/v_show/id_XNzAzMTY5MjUy.html
J2Cache 的两级缓存结构
L1: 进程内缓存(caffeine\ehcache)
L2: Redis/Memcached 集中式缓存
二、数据读取
- 读取顺序 -> L1 -> L2 -> DB
- 数据更新
1 从数据库中读取最新数据,依次更新 L1 -> L2 ,发送广播清除某个缓存信息
2 接收到广播(手工清除缓存 & 一级缓存自动失效),从 L1 中清除指定的缓存信息
三、使用方法及实际示例
J2Cache 默认使用 Caffeine 作为一级缓存,使用 Redis 作为二级缓存。你还可以选择 Ehcache2 和 Ehcache3 作为一级缓存。
以下实际的使用示例是以Springboot 项目为基础集成 J2Cache 的。
3.1 引用 Maven
以下是我从中央仓库查看的2.8.x的版本
<!--
<dependency>
<groupId>net.oschina.j2cache</groupId>
<artifactId>j2cache-core</artifactId>
<version>2.8.2-release</version>
</dependency>
3.2 准备配置
拷贝 j2cache.properties
和 caffeine.properties
到你项目的源码目录,并确保这些文件会被编译到项目的 classpath 中。如果你选择了 ehcache 作为一级缓存,需要拷贝 ehcache.xml
或者 ehcache3.xml
到源码目录(后者对应的是 Ehcache 3.x 版本),这些配置文件的模板可以从 https://gitee.com/ld/J2Cache/tree/master/core/resources 这里获取。
使用你喜欢的文本编辑器打开 j2cache.properties
并找到 redis.hosts
项,将其信息改成你的 Redis 服务器所在的地址和端口。
我们建议缓存在使用之前都需要预先设定好缓存大小及有效时间,使用文本编辑器打开 caffeine.properties 进行缓存配置,配置方法请参考文件中的注释内容。
例如:default = 1000,30m #定义缓存名 default ,对象大小 1000,缓存数据有效时间 30 分钟。 你可以定义多个不同名称的缓存。
自己代码中实际的配置文件已上传至资源中心,方便查看:
J2Cache 使用Ceffien作为一级缓存,使用Redis作为二级缓存时的配置
3.3 编写代码
3.3.1 Demo示例
public static void main(String[] args) {
CacheChannel cache = J2Cache.getChannel();
// 缓存操作
cache.set("default", "1", "Hello J2Cache");
System.out.println(cache.get("default", "1"));
// 清除缓存
cache.evict("default", "1");
System.out.println(cache.get("default", "1"));
// 请注意 cache.close() 方法只需在程序退出时调用
cache.close();
}
3.3.2 实际案例
/**
* 获取摄像头的uuid
*
* @param sn 家庭的sn
* @param deviceId 像头的设备id
* @return 摄像头的uuid
*/
private String getUuid(String sn, Integer deviceId) {
log.info("E|CameraShoutHandler|getUuid()|根据sn和摄像头的设备id调用设备云服务查询摄像头详情开始!");
long startTime = System.currentTimeMillis();
// 格式 dev225:132
String key = sn + StrUtil.COLON + deviceId;
CacheChannel channel = J2Cache.getChannel();
// 先从缓存中取出摄像头的UUID(首先从内存中读取,内存中如果没有再从Redis中读取,如果Redis还是没有,那么就再去数据库或者调用第三方服务获取数据)
CacheObject cacheObject = channel.get(SystemConstant.APPLICATION_NAME, key);
String uuid = (String) cacheObject.getValue();
// 如果两级缓存中没有摄像头的uuid,则去调用设备云服务查询摄像头的详情,查询出之后再存入缓存
if (Objects.isNull(uuid)) {
log.info("**************** 缓存中的UUID为空,调用设备云服务查询摄像头的uuid *************");
CommResponse cameraDetailInfo = cameraDetailInfoRpc.getCameraDetailInfo(sn, deviceId);
CameraDetailInfoDTO cameraDetailInfoDTO = (CameraDetailInfoDTO) cameraDetailInfo.getData();
// 存入缓存
channel.set(SystemConstant.APPLICATION_NAME, key, cameraDetailInfoDTO.getUuid());
}
log.info("E|CameraShoutHandler|getUuid()|根据sn和摄像头的设备id调用设备云服务查询摄像头详情结束!------------ 耗时:【{}】毫秒!", System.currentTimeMillis() - startTime);
return uuid;
}
可以从Redis客户端工具里查看,Redis中已经有这个数据了。
四、常见问题
4.1 J2Cache 的使用场景是什么?
首先你的应用是运行在集群环境,使用 J2Cache 可以有效降低节点间的数据传输量;其次单节点使用 J2Cache 可以避免应用重启后对后端业务系统的冲击
4.2 为什么不能在程序中设置缓存的有效期
在程序中定义缓存数据的有效期会导致缓存不可控,一旦数据出问题无从查起,因此 J2Cache 的所有缓存的有效期都必须在 一级缓存
的配置中预设好再使用
4.3 如何使用 memcached 作为二级缓存
首先修改 j2cache.properties
中的 j2cache.L2.provider_class
为 memcached,然后在 j2cache.properties 中配置 memcached.xxx 相关信息。
需要在项目中引入对 memcached 的支持:
<dependency>
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>
<version>2.4.5</version>
</dependency>
4.4 使用何种 Redis 的存储模式最佳? generic 还是 hash ?
我们推荐使用 generic 存储模式,这也是 J2Cache 默认的存储模式,hash 模式最大的问题是无法单独对 key 进行 expire 设置。
参考资料:J2Cache —— 基于内存和 Redis 的两级 Java 缓存框架
完结!
标签:缓存,Java,Redis,j2cache,使用,J2Cache,摄像头 From: https://blog.51cto.com/no8g/6445902