# RCache
**Repository Path**: mosangshen/rcache
## Basic Information
- **Project Name**: RCache
- **Description**: Rcache是一个缓存框架,其核心设计目的是为了让我们可以更加灵活的去配置缓存,其学习简单、轻量级、易扩展开箱即用。
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2022-05-26
- **Last Updated**: 2025-09-17
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 介绍|Introduce
Rcache是一个缓存框架,其核心设计目的是为了让我们可以更加灵活的去配置缓存,其学习简单、轻量级、易扩展开箱即用。
## 河北软件职业技术学院2020级JavaPlus
**作者**:高增源、钱国鹏、李佳成、贺建豪
**指导教师**:王彦辉
# 特性|Speciality
1. 轻量级:RCache最简包仅仅依赖log4j
2. 模块化:RCache将分布式策略、连接持久层框架代码进行了分离,用时导入插件包即可,即插即用
3. 灵活性:
- CacheManager管理的为动态代理的RCache可以很简单的对其进行功能增强
- 增加了MultipleCache策略,可以灵活搭配RCache食用
4. 持久化:ALWAYS(每新增一个缓存元素就进行一次缓存)、SIZE(根据缓存元素数量设定阈值,达到阈值进行持久化)、TIME(根据用户设定的时间定时缓存)持久化异步进行
5. 邮件报警:在缓存元素数量达到预警阈值会异步发送邮件报警、分布式环境客户机掉线、重新选举后会异步发送邮件报警
6. 分布式:目前支持Netty分布式策略异步通信(后面会更新NIO分布式策略)
7. 可用性:可连接mybatis与hibernate持久化框架、模块化拆分即插即用
# 架构图|Structure Chart(简版|Simple)

# 快速开始|Quick Start
**添加依赖**
**添加最简包:**[RabbitCache_Simple.jar](https://gitee.com/mosangshen/rcache/raw/master/%E6%9C%AC%E9%A1%B9%E7%9B%AE%E6%89%93%E5%8C%85%E7%9A%84jar%E5%8C%85/RabbitCache_Simple.jar)
**配置文件示例**
在资源根目录创建 rcache.properties 文件
```properties
# cache名称
CacheName=cache1
# 淘汰策略 可配置 FIFO、LRU、LFU、Multiple 默认FIFO
cache1.cacheStrategy=LFU
################## 生命周期配置 ##################
# 最大存活时间 eternal为false时生效 10000(十秒)
cache1.maxTimeToLive=10000
# 最大空闲时间 eternal为false时生效 默认2000(两秒)
cache1.maxTimeToIdle=2000
# 是否永不过期 默认为false
cache1.eternal=false
################## 持久化配置 ##################
# 是否开启持久化
cache1.diskCache=true
# 持久化路径
cache1.diskCachePath=D:/cache
# 持久化策略 可配置:TIME、SIZE、ALWAYS 默认always
cache1.diskCacheStrategy=TIME
# TIME持久化策略配置 定时时间 默认10秒,在持久化策略为SIZE时生效
cache1.diskCacheTime=10000
# SIZE持久化策略配置 阈值 默认达到15个元素存储一次,在持久化策略为TIME时生效
cache1.diskCacheSize=15
################## 容量限制配置 ##################
# 初始容量
cache1.initElements=2
# 最大元素数量
cache1.maxElements=1000
################## 邮件预警配置 ##################
# 容量预警阈值
cache1.warningElements=7
# 是否开启邮件预警
cache1.warning=true
# 预警信息发送的邮箱账号
cache1.managerEmail=mosangshen@163.com
################## 分布式缓存配置 ##################
# 是否开始分布式
cache1.distribute=true
# master IP
cache1.distributeIP=192.168.119.1
# master Port
cache1.distributePort=8888
```
## 整合Hibernate篇
### 添加依赖
**Hibernate3:**[RabbitCache_Hibernate3.jar](https://gitee.com/mosangshen/rcache/raw/master/%E6%9C%AC%E9%A1%B9%E7%9B%AE%E6%89%93%E5%8C%85%E7%9A%84jar%E5%8C%85/RabbitCache_Hibernate3.jar)
**Hibernate4:**[RabbitCache_Hibernate4.jar](https://gitee.com/mosangshen/rcache/raw/master/%E6%9C%AC%E9%A1%B9%E7%9B%AE%E6%89%93%E5%8C%85%E7%9A%84jar%E5%8C%85/RabbitCache_Hibernate4.jar)
### **配置**
在资源根目录创建 rcache.properties 、hibernate.cfg.xml、User.hbm.xml文件
**hibernate.cfg.xml**
```xml
org.hibernate.dialect.MySQLDialect
jdbc:mysql://localhost:3308/testmybatis?useUnicode=true&characterEncoding=utf-8
root
root
com.mysql.jdbc.Driver
true
false
update
thread
true
true
com.hibernate.rcache.RcacheRegionFactory
```
**User.hbm.xml**
```xml
```
### **测试示例**
```java
public class Test {
public static void main(String[] args) throws ConfigurationException {
// 1.加载配置文件
Configuration config = new Configuration().configure();
// 2.创建session工厂
SessionFactory sessionFactory = config.buildSessionFactory();
// 3.获取session
Session session = sessionFactory.openSession();
// 4.开启事务
Transaction transaction = session.beginTransaction();
// 5.进行持久化操作(CRUD)
//第一次查询 查询缓存--->未命中--->查询数据库
User user2 = (User) session.get(User.class, "1");
System.out.println(user2.getName());
//第二次查询 查询缓存--->命中
user2 = (User) session.get(User.class, "1");
System.out.println(user2.getName());
//验证是否存入缓存
CacheManager cacheManager = CacheManager.newInstance();
System.out.println("CacheNames:"+cacheManager.getCacheNames());
Map map = cacheManager.getCache("entity.User").toMap();
for ( Object key:map.keySet()){
System.out.println("element: "+map.get(key));
}
user2 = (User) session.get(User.class, "1");//从数据库获取
// 6.提交事务
transaction.commit();
// 7.关闭连接
session.close();
}
}
```
## 整合Mybatis篇
### 添加依赖
[RabbitCache_Mybatis.jar](https://gitee.com/mosangshen/rcache/raw/master/%E6%9C%AC%E9%A1%B9%E7%9B%AE%E6%89%93%E5%8C%85%E7%9A%84jar%E5%8C%85/RabbitCache_Mybatis.jar)
### 配置
在资源根目录创建 rcache.properties 、mybatis-config.xml、UserMapper.xml文件
**mybatis-config.xml**
```xml
```
**UserMapper.xml**
```java
```
### 测试示例
```java
public class Test01 {
public static void main(String[] args) throws IOException, ConfigurationException, InterruptedException {
for (int i = 0; i < 2; i++) {
System.err.println("第"+i+"次查询………………");
String config="mybatis-config.xml";
Reader reader = Resources.getResourceAsReader(config);
SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sessionFactory.openSession();
//1.查询全部
session.selectList("queryAll");
//获取cacheManager
CacheManager cacheManager= CacheManager.newInstance();
System.out.println(cacheManager.getCacheNames());
//得到Rcache对象
Rcache cache = cacheManager.getCache("default");
System.out.println("cache.KeySet()"+cache.KeySet());
session.close();
System.out.println("cache.KeySet():"+cache.KeySet());
System.out.println("\n\n\n");
}
}
}
```
## RCache分布式篇
### 添加依赖
[RabbitCache_Netty4.jar](https://gitee.com/mosangshen/rcache/raw/master/%E6%9C%AC%E9%A1%B9%E7%9B%AE%E6%89%93%E5%8C%85%E7%9A%84jar%E5%8C%85/RabbitCache_Netty4.jar)
### 配置
在资源根目录创建 rcache.properties 文件
```properties
# cache名称
CacheName=cache1
################## 分布式缓存配置 ##################
# 是否开始分布式
cache1.distribute=true
# master IP
cache1.distributeIP=192.168.119.1
# master Port
cache1.distributePort=8888
```
**使用分布式方法**
put(key,value,true);
update(key,value,true);
delete(key,true);
### 测试示例
```java
public class Test {
private static Rcache cache;
public static void main(String[] args) throws Exception {
ICacheManager cacheManager = CacheManager.newInstance("classpath:rcache.properties");
//使用cache1缓存池
cache= cacheManager.getCache("cache1");
System.out.println(cacheManager.getCacheNames());
Thread.sleep(2000);
cs();
}
/**
* @desc 测试缓存
*/
private static void cs() {
//获取扫描器对象
String inStr;
Scanner s=new Scanner(System.in);
while (true){
System.out.println("-----控制台测试阶段-----");
System.out.println("进行添加操作,请输入 put");
System.out.println("进行修改操作,请输入 update");
System.out.println("进行删除操作,请输入 delete");
System.out.println("进行查询操作,请输入 query");
inStr = s.nextLine();
if (inStr.equals("put")){
System.out.println("-----进入添加操作-----");
System.out.println("-----请输入key值-----");
String key = s.nextLine();
System.out.println("-----请输入value值-----");
String value = s.nextLine();
put(key,value,true);
}else if (inStr.equals("update")){
System.out.println("-----进入修改操作-----");
System.out.println("-----请输入key值-----");
String key = s.nextLine();
System.out.println("-----请输入value值-----");
String value = s.nextLine();
update(key,value,true);
}else if (inStr.equals("delete")){
System.out.println("-----进入删除操作-----");
System.out.println("-----请输入key值-----");
String key = s.nextLine();
delete(key,true);
}else if (inStr.equals("query")){
System.out.println("-----进入查询操作-----");
System.out.println("-----请输入key值-----");
String key = s.nextLine();
query(key);
}else if (inStr.equals("quit")){
System.exit(0);
}
}
}
private static void update(String key, String value, boolean b) {
cache.replace(key,value,b);
}
private static void delete(String key, boolean b) {
cache.remove(key,b);
}
private static void put(String key, String value, boolean b) {
cache.put(key,value,b);
}
private static void query(String key) {
Object value = cache.get(key);
System.out.println(key+" 对应的值为:"+value);
}
}
```
## MultipleCache使用案例
### 配置
在资源根目录创建 rcache.properties 文件
```properties
# cache名称
CacheName=cache_duoduo,cache1,cache2
###### cache1 ######
# 是否永不过期 默认为false
cache1.eternal=true
# 淘汰策略 默认fifo
cache1.cacheStrategy=LFU
###### cache2 ######
# 是否永不过期 默认为false
cache2.eternal=true
# 淘汰策略 默认fifo
cache2.cacheStrategy=LRU
###### cache2 ######
# 淘汰策略 设置为Multiple
cache_duoduo.cacheStrategy=Multiple
# 配置缓存策略:(可灵活搭配,根据业务场景配置缓存提高命中率)将cache1充当L1,cache2充当L2,在L1中淘汰后进入L2……直到最后一层删除缓存元素
cache_duoduo.cacheNames=cache1,cache2……
```
### 测试示例
```java
public class Test {
private static Rcache cache;
public static void main(String[] args) throws Exception {
ICacheManager cacheManager = CacheManager.newInstance("classpath:rcache.properties");
//使用cache_duoduo缓存池
cache= cacheManager.getCache("cache_duoduo");
System.out.println(cacheManager.getCacheNames());
Thread.sleep(2000);
cs();
}
/**
* @desc 测试缓存
*/
private static void cs() {
//获取扫描器对象
String inStr;
Scanner s=new Scanner(System.in);
while (true){
System.out.println("-----控制台测试阶段-----");
System.out.println("进行添加操作,请输入 put");
System.out.println("进行修改操作,请输入 update");
System.out.println("进行删除操作,请输入 delete");
System.out.println("进行查询操作,请输入 query");
inStr = s.nextLine();
if (inStr.equals("put")){
System.out.println("-----进入添加操作-----");
System.out.println("-----请输入key值-----");
String key = s.nextLine();
System.out.println("-----请输入value值-----");
String value = s.nextLine();
put(key,value,true);
}else if (inStr.equals("update")){
System.out.println("-----进入修改操作-----");
System.out.println("-----请输入key值-----");
String key = s.nextLine();
System.out.println("-----请输入value值-----");
String value = s.nextLine();
update(key,value,true);
}else if (inStr.equals("delete")){
System.out.println("-----进入删除操作-----");
System.out.println("-----请输入key值-----");
String key = s.nextLine();
delete(key,true);
}else if (inStr.equals("query")){
System.out.println("-----进入查询操作-----");
System.out.println("-----请输入key值-----");
String key = s.nextLine();
query(key);
}else if (inStr.equals("quit")){
System.exit(0);
}
}
}
private static void query(String key) {
Object value = cache.get(key);
System.out.println(key+" 对应的值为:"+value);
}
private static void delete(String key) {
cache.remove(key);
}
private static void update(String key, String value) {
cache.replace(key,value);
}
public static void put(String key, String value){
cache.put(key,value);
}
}
```
# 期望 | Futures
> 欢迎提出更好的意见 **mosangshen@163.com**