1. 监控设计方案
1.1 需求
- 监控Redis容量
- 监控数据库容量
- 可配置监控时间间隔和是否开启监控
1.2 方案设计
- Redis容量监控:通过RedisTemplate执行Redis命令
INFO MEMORY
,解析返回结果获取内存信息 - 数据库容量监控:通过JdbcTemplate执行SQL语句,解析返回结果获取容量信息
- 监控任务:使用ScheduledExecutorService实现定时任务,定时执行监控操作
- 配置管理:使用Spring的@ConfigurationProperties注解管理监控配置
1.3 代码实现
- RedisMemoryMonitor类:封装Redis容量监控逻辑
- DBMemoryMonitor类:封装数据库容量监控逻辑
- ScheduledTask类:实现定时任务,根据监控配置决定是否执行监控操作
2. 技术选型与设计
2.1 选型要求
- 提高应用性能,降低资源消耗
- 适应高并发场景,支持多线程操作
2.2 连接池选型
- HikariCP:轻量级、高性能、资源占用小,适合高并发场景
- Druid:功能丰富,但较重,适合有复杂业务逻辑或需要详细监控的场景
- C3P0:老牌连接池,稳定性好,但性能不如HikariCP
2.3 连接池设计
- HikariConfig:使用配置类管理HikariCP连接池配置
- RedisConnectionUtils:使用ThreadLocal管理Redis连接,避免多线程竞争问题
- JdbcTemplate和RedisTemplate:在使用连接时,使用连接池获取连接,执行操作后释放连接
2.4 代码实现Demo
(1)HikariConfig类:管理HikariCP连接池配置
@Configuration
@ConfigurationProperties(prefix = "spring.datasource.hikari")
public class HikariConfig {
private String jdbcUrl;
private String username;
private String password;
private String driverClassName;
private Integer maximumPoolSize;
@Bean
public HikariDataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(jdbcUrl);
config.setUsername(username);
config.setPassword(password);
config.setDriverClassName(driverClassName);
config.setMaximumPoolSize(maximumPoolSize);
return new HikariDataSource(config);
}
// getter and setter methods
}
(2)RedisConnectionUtils类:封装获取和释放Redis连接的方法,使用ThreadLocal管理连接
public class RedisConnectionUtils {
private static ThreadLocal<RedisConnection> redisConnectionThreadLocal = new ThreadLocal<>();
public static RedisConnection getConnection(RedisConnectionFactory redisConnectionFactory) {
RedisConnection redisConnection = redisConnectionThreadLocal.get();
if (redisConnection == null) {
redisConnection = redisConnectionFactory.getConnection();
redisConnectionThreadLocal.set(redisConnection);
}
return redisConnection;
}
public static void releaseConnection() {
RedisConnection redisConnection = redisConnectionThreadLocal.get();
if (redisConnection != null) {
redisConnection.close();
redisConnectionThreadLocal.remove();
}
}
}
(3)RedisTemplateUtils类:使用RedisConnectionUtils获取连接池连接,创建RedisTemplate
public class RedisTemplateUtils {
public static RedisTemplate<String, String> createRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setDefaultSerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
public static void execute(RedisConnectionFactory redisConnectionFactory, RedisCallback<Void> redisCallback) {
RedisConnection redisConnection = null;
try {
redisConnection = RedisConnectionUtils.getConnection(redisConnectionFactory);
redisCallback.doInRedis(redisConnection);
} finally {
RedisConnectionUtils.releaseConnection();
}
}
}
(4)JdbcTemplateUtils类:使用HikariCP连接池获取连接,创建JdbcTemplate
public class JdbcTemplateUtils {
public static JdbcTemplate createJdbcTemplate(HikariDataSource dataSource) {
return new JdbcTemplate(dataSource);
}
public static void execute(HikariDataSource dataSource, ConnectionCallback<Void> connectionCallback) {
Connection connection = null;
try {
connection = dataSource.getConnection();
connectionCallback.doInConnection(connection);
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
}
3. 定时任务
3.1 需求
- 实现定时任务,每天定时查询并统计数据库和Redis的容量信息,并发送邮件告警
- 定时任务可配置,可以动态修改任务执行时间和告警开关
3.2 设计
- 使用Spring的@Scheduled注解实现定时任务
- 定义ScheduledTask类,封装定时任务的执行逻辑,如查询容量信息和发送邮件告警等
- 使用动态配置,将任务执行时间和告警开关参数化,使用数据库表或者配置文件存储
- 使用注解@Value注入动态配置参数,从而实现动态修改任务执行时间和告警开关的功能
3.3 代码实现Demo
@Component
public class ScheduledTask {
private final Logger logger = LoggerFactory.getLogger(ScheduledTask.class);
@Autowired
private DatabaseMemoryMonitor databaseMemoryMonitor;
@Autowired
private RedisMemoryMonitor redisMemoryMonitor;
@Autowired
private EmailService emailService;
@Value("${schedule.task.time}")
private String taskTime;
@Value("${schedule.task.alarmSwitch}")
private boolean alarmSwitch;
// 每天定时执行
@Scheduled(cron = "${schedule.task.time}")
public void execute() {
logger.info("定时任务开始执行");
// 查询数据库容量信息
List<DatabaseCapacityInfo> dbCapacityList = databaseMemoryMonitor.getDatabaseCapacityInfo();
// 查询Redis容量信息
Map<String, Long> redisCapacityMap = redisMemoryMonitor.getRedisCapacityInfo();
// 发送邮件告警
if (alarmSwitch) {
emailService.sendEmail(dbCapacityList, redisCapacityMap);
}
logger.info("定时任务执行完毕");
}
}
其中,@Scheduled(cron = "${schedule.task.time}")
注解表示按照cron表达式执行定时任务,${schedule.task.time}
是从配置文件中读取的动态参数,可根据需要修改执行时间。
同时,使用@Value
注解将动态配置参数注入到类中,如@Value("${schedule.task.alarmSwitch}")
注入告警开关参数,从而实现动态修改告警开关的功能。
另外,需要实现DatabaseMemoryMonitor
和RedisMemoryMonitor
类,分别用于查询数据库容量信息和Redis容量信息,并返回结果给ScheduledTask
类使用。同时,需要实现EmailService
类,用于发送邮件告警。