使用 Redis 作为内部 Cache
目录
内部 Cache 负责存储的信息
在 Tio-boot 运行过程中,内部状态信息会被存入缓存系统 AbsCache
。以下是 Tio-boot 内部会缓存的一些典型信息:
- HTTP 会话(Session)数据:启用会话管理时,浏览器的会话信息会存储在缓存中,以便在后续请求中快速访问。默认情况下,使用
ConcurrentMapCache
存储,但可以通过引入 Caffeine 实现更高效的缓存管理。 - IP 统计信息:缓存保存与 IP 地址相关的统计数据,如请求次数、数据包数量等。这些信息有助于进行访问控制和流量限制。
- HTTP 静态资源内容:为了提升响应速度,静态资源内容会被缓存,避免每次请求都重新读取资源。
- IP 黑名单信息:在安全防护中,黑名单 IP 列表会被缓存,以阻止不良 IP 的访问。
- 锁定机制状态:与
LockUtils
相关的状态信息会存储在缓存中,以便在并发场景中管理读写锁。
这些缓存信息的管理通过 CacheFactory
实现。CacheFactory
负责缓存实例的注册、获取以及数据的存取,并支持自定义缓存的 TTL(存活时间)和 TTI(空闲时间)设置。通过适当的配置,可以优化系统性能,减少不必要的数据重复计算和资源消耗。
使用 Redis 作为内部 Cache
为了提高缓存的持久性和分布式能力,本指南将介绍如何使用 Redis 作为 Tio-boot 的内部缓存。
添加依赖
首先,需要在项目的 pom.xml
文件中添加 Redis 客户端依赖。本文使用的是 Jedis
作为 Redis 客户端。
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.1</version>
</dependency>
添加配置
在 app.properties
文件中添加 Redis 相关配置,以及指定使用 Redis 作为缓存存储。
# 指定缓存存储类型为 Redis
server.cache.store=redis
# 启用会话管理
server.session.enable=true
# Redis 连接配置
redis.host=127.0.0.1
redis.port=6379
redis.password= # 如果 Redis 设置了密码,请在此填写
redis.database=2
redis.timeout=15000
配置说明:
server.cache.store=redis
:指定缓存存储类型为 Redis。默认情况下,Tio-boot 使用ConcurrentMapCache
,但通过此配置可以切换为 Redis。server.session.enable=true
:启用会话管理,将会话数据存储在 Redis 中。redis.host
、redis.port
、redis.password
、redis.database
、redis.timeout
:配置 Redis 连接的主机、端口、密码、数据库编号和连接超时时间。
添加配置类
创建一个配置类,用于初始化 Redis 连接池,并将其注入到 RedisMapCacheFactory
中。
package com.litongjava.tio.web.hello.config;
import com.litongjava.annotation.BeforeStartConfiguration;
import com.litongjava.annotation.Initialization;
import com.litongjava.tio.boot.server.TioBootServer;
import com.litongjava.tio.utils.cache.redismap.RedisMapCacheFactory;
import com.litongjava.tio.utils.environment.EnvUtils;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
@BeforeStartConfiguration
public class BeforeTioStartConfig {
@Initialization
public void config() {
// 从环境变量获取 Redis 配置
String host = EnvUtils.getStr("redis.host");
int port = EnvUtils.getInt("redis.port", 6379);
Integer timeout = EnvUtils.getInt("redis.timeout", 2000);
String password = EnvUtils.getStr("redis.password");
int database = EnvUtils.getInt("redis.database", 0);
// 创建 Jedis 连接池
JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), host, port, timeout, password, database);
// 将 Jedis 连接池设置到 RedisMapCacheFactory
RedisMapCacheFactory.INSTANCE.setJedisPool(jedisPool);
// 注册销毁方法,确保应用关闭时连接池被正确关闭
TioBootServer.me().addDestroyMethod(jedisPool::close);
}
}
关键点说明:
@BeforeStartConfiguration
:该注解标识的配置类会在 Tio-boot 启动前执行,确保 Redis 连接池在缓存系统初始化前就绪。@Initialization
:标识初始化方法,用于配置和初始化 Redis 连接。RedisMapCacheFactory.INSTANCE.setJedisPool(jedisPool)
:将创建的 Jedis 连接池注入到RedisMapCacheFactory
中,使其能够使用 Redis 进行缓存操作。TioBootServer.me().addDestroyMethod(jedisPool::close)
:注册应用关闭时的销毁方法,确保 Redis 连接池被正确关闭,释放资源。
启动类
启动类无需做任何更改,继续使用现有的 TioApplication.run
方法启动应用。
package com.litongjava.tio.web.hello;
import com.litongjava.annotation.AComponentScan;
import com.litongjava.tio.boot.TioApplication;
@AComponentScan
public class HelloApp {
public static void main(String[] args) {
long start = System.currentTimeMillis();
TioApplication.run(HelloApp.class, args);
long end = System.currentTimeMillis();
System.out.println((end - start) + "ms");
}
}
编写 Controller
编写一个 Controller,用于查看内部缓存存储的数据,验证 Redis 缓存是否正常工作。
package com.litongjava.tio.web.hello.controller;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import com.jfinal.kit.Kv;
import com.litongjava.annotation.RequestPath;
import com.litongjava.model.body.RespBodyVo;
import com.litongjava.tio.boot.server.TioBootServer;
import com.litongjava.tio.utils.cache.AbsCache;
import com.litongjava.tio.utils.cache.CacheFactory;
@RequestPath("/internal")
public class InternalController {
public RespBodyVo cache() {
// 获取 CacheFactory 实例
CacheFactory cacheFactory = TioBootServer.me().getServerTioConfig().getCacheFactory();
Map<String, ? extends AbsCache> map = cacheFactory.getMap();
// 创建响应数据
Kv kv = Kv.by("cacheFactory", cacheFactory);
kv.set("map", map);
// 遍历所有缓存,获取缓存中的数据
for (Map.Entry<String, ? extends AbsCache> entry : map.entrySet()) {
String cacheName = entry.getKey();
AbsCache cache = entry.getValue();
Collection<String> keysCollection = cache.keysCollection();
Map<String, Object> cacheMap = new HashMap<>();
for (String key : keysCollection) {
cacheMap.put(key, cache.get(key));
}
kv.set("cache_" + cacheName, cacheMap);
}
return RespBodyVo.ok(kv);
}
}
功能说明:
- 通过
/internal/cache
路径访问该 Controller,可以查看当前缓存中存储的所有数据。 - 该方法遍历所有缓存实例,获取每个缓存中的键值对,并将其封装在响应体中返回。
关键配置说明
server.cache.store=redis
该配置项指定了 Tio-boot 使用 Redis 作为内部缓存存储。默认情况下,Tio-boot 使用内存中的 ConcurrentMapCache
进行缓存管理,这对于单实例应用足够,但在分布式或高可用场景下可能存在限制。通过设置 server.cache.store=redis
,可以将缓存数据存储在 Redis 中,实现缓存的持久化和跨实例共享。
优点:
- 持久化:缓存数据可以持久化存储,避免因应用重启导致数据丢失。
- 分布式支持:多实例应用可以共享同一个 Redis 缓存,确保数据一致性。
- 扩展性:Redis 提供了丰富的数据结构和高级功能,如过期策略、发布订阅等,增强缓存的灵活性。
@BeforeStartConfiguration
注解
@BeforeStartConfiguration
是自定义的注解,用于标识在 Tio-boot 启动前执行的配置类。被该注解标注的类会在应用启动流程的早期阶段被加载和执行,确保关键配置在缓存系统初始化之前完成。
作用:
- 初始化顺序控制:确保 Redis 连接池在 Tio-boot 启动和缓存系统初始化之前就绪,避免在缓存操作时出现连接未建立的情况。
- 统一配置管理:集中管理与 Redis 相关的配置和初始化逻辑,提高代码的可维护性和可读性。
RedisMapCacheFactory
RedisMapCacheFactory
是 Tio-boot 提供的一个缓存工厂类,负责管理 Redis 作为缓存存储的具体实现。通过将 JedisPool
注入到 RedisMapCacheFactory
,它可以使用 Redis 进行缓存的读写操作。
主要职责:
- 缓存实例管理:注册和获取不同类型的缓存实例,如会话缓存、IP 统计缓存等。
- 数据存取:通过 Redis 客户端与 Redis 服务器交互,实现缓存数据的存取、更新和删除。
- 配置支持:支持自定义缓存的 TTL(存活时间)和 TTI(空闲时间),通过配置优化缓存行为。
使用步骤:
- 初始化 Redis 连接池:在配置类中创建
JedisPool
并注入到RedisMapCacheFactory
。 - 注册销毁方法:确保应用关闭时,连接池能够被正确关闭,释放资源。
- 配置缓存工厂:通过
CacheFactory
获取RedisMapCacheFactory
,并管理具体的缓存实例。
总结
通过以上步骤,您可以将 Redis 成功集成到 Tio-boot 作为内部缓存系统。这不仅提升了缓存的持久性和分布式能力,还增强了系统的扩展性和稳定性。关键配置如 server.cache.store=redis
和 @BeforeStartConfiguration
注解确保了缓存系统的正确初始化和高效运行。RedisMapCacheFactory
则提供了强大的缓存管理功能,使得在不同场景下都能灵活应对。
建议:
- 监控与优化:定期监控 Redis 的性能,调整连接池和缓存策略参数,以确保最佳性能。
- 安全配置:在生产环境中,确保 Redis 配置了强密码,并通过防火墙等手段限制访问,保障数据安全。
- 高可用部署:考虑使用 Redis 集群或主从架构,提升系统的可用性和容错能力。
通过合理配置和优化,Redis 将为您的 Tio-boot 应用提供强大的缓存支持,显著提升系统的响应速度和处理能力。