diff --git a/ebike-operations/src/main/java/com/cdzy/operations/config/RedisConfig.java b/ebike-operations/src/main/java/com/cdzy/operations/config/RedisConfig.java index 105df32..04adf49 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/config/RedisConfig.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/config/RedisConfig.java @@ -1,13 +1,19 @@ package com.cdzy.operations.config; import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; +import java.time.Duration; /** * @author attiya @@ -16,8 +22,104 @@ import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { + @Value("${spring.data.redis.host}") + private String host; + + @Value("${spring.data.redis.port}") + private int port; + + @Value("${spring.data.redis.password}") + private String password; + + @Value("${spring.data.redis.database}") + private int defaultDatabase; + + @Value("${spring.data.redis.lettuce.pool.max-active}") + private int maxActive; + + @Value("${spring.data.redis.lettuce.pool.max-idle}") + private int maxIdle; + + @Value("${spring.data.redis.lettuce.pool.min-idle}") + private int minIdle; + + @Value("${spring.data.redis.lettuce.pool.max-wait}") + private String maxWait; + + /** + * 默认数据库的连接工厂(数据库1) + */ @Bean - public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + @Primary + public RedisConnectionFactory defaultRedisConnectionFactory() { + return createRedisConnectionFactory(defaultDatabase); + } + + /** + * 数据库0的连接工厂 + */ + @Bean + public RedisConnectionFactory redisConnectionFactoryDb0() { + return createRedisConnectionFactory(0); + } + + /** + * 数据库2的连接工厂 + */ + @Bean + public RedisConnectionFactory redisConnectionFactoryDb2() { + return createRedisConnectionFactory(2); + } + + /** + * 创建指定数据库的连接工厂 + */ + private RedisConnectionFactory createRedisConnectionFactory(int database) { + // Redis基本配置 + RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(); + config.setHostName(host); + config.setPort(port); + config.setDatabase(database); + config.setPassword(password); + + // 连接池配置 + LettucePoolingClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder() + .commandTimeout(Duration.ofSeconds(10)) + .shutdownTimeout(Duration.ofSeconds(10)) + .poolConfig(createLettucePoolConfig()) + .build(); + + return new LettuceConnectionFactory(config, clientConfig); + } + + /** + * 创建Lettuce连接池配置 + */ + private org.apache.commons.pool2.impl.GenericObjectPoolConfig createLettucePoolConfig() { + org.apache.commons.pool2.impl.GenericObjectPoolConfig poolConfig = + new org.apache.commons.pool2.impl.GenericObjectPoolConfig<>(); + poolConfig.setMaxTotal(maxActive); + poolConfig.setMaxIdle(maxIdle); + poolConfig.setMinIdle(minIdle); + + if ("-1ms".equals(maxWait)) { + poolConfig.setMaxWait(Duration.ofMillis(-1)); + } else { + try { + long waitMs = Long.parseLong(maxWait.replace("ms", "")); + poolConfig.setMaxWait(Duration.ofMillis(waitMs)); + } catch (NumberFormatException e) { + poolConfig.setMaxWait(Duration.ofMillis(-1)); + } + } + + return poolConfig; + } + + /** + * 创建并配置RedisTemplate的通用方法 + */ + private RedisTemplate createAndConfigureRedisTemplate(RedisConnectionFactory factory) { RedisTemplate template = new RedisTemplate<>(); template.setConnectionFactory(factory); @@ -33,7 +135,35 @@ public class RedisConfig { template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(serializer); + // 设置其他序列化器以确保一致性 + template.setStringSerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); return template; } -} + + /** + * 默认RedisTemplate(数据库1)- 已添加序列化配置 + */ + @Bean + @Primary + public RedisTemplate redisTemplate() { + return createAndConfigureRedisTemplate(defaultRedisConnectionFactory()); + } + +// /** +// * 数据库0的RedisTemplate - 已添加序列化配置 +// */ +// @Bean("redisTemplateDb0") +// public RedisTemplate redisTemplateDb0() { +// return createAndConfigureRedisTemplate(redisConnectionFactoryDb0()); +// } + + /** + * 数据库2的RedisTemplate - 已添加序列化配置 + */ + @Bean("redisTemplateDb2") + public RedisTemplate redisTemplateDb2() { + return createAndConfigureRedisTemplate(redisConnectionFactoryDb2()); + } +} \ No newline at end of file diff --git a/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeInfoServiceImpl.java b/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeInfoServiceImpl.java index c4e66b8..9a8469d 100644 --- a/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeInfoServiceImpl.java +++ b/ebike-operations/src/main/java/com/cdzy/operations/service/impl/EbikeBikeInfoServiceImpl.java @@ -335,7 +335,7 @@ public class EbikeBikeInfoServiceImpl extends ServiceImpl redisTemplate; - + private final RedisTemplate redisTemplate; // 默认数据库 + private final RedisTemplate redisTemplateDb2; // 数据库2 @Autowired - public RedisUtil(RedisTemplate redisTemplate) { + public RedisUtil( + RedisTemplate redisTemplate, + @Qualifier("redisTemplateDb2") RedisTemplate redisTemplateDb2) { this.redisTemplate = redisTemplate; + this.redisTemplateDb2 = redisTemplateDb2; } + /** + * 数据库常量定义 + */ + public static class Database { + public static final int DB1 = 1; // 业务数据(默认) + public static final int DB2 = 2; // 监控/调度数据 + } + + /** + * 获取指定数据库的RedisTemplate + */ + private RedisTemplate getRedisTemplate(int database) { + switch (database) { + case Database.DB1: return redisTemplate; + case Database.DB2: return redisTemplateDb2; + default: throw new IllegalArgumentException("不支持的数据库索引: " + database); + } + } + + /* ==================== 原有功能保持不变 ==================== */ + /** * 设置过期时间 * @param key 键 @@ -252,4 +277,192 @@ public class RedisUtil { public Boolean releaseLock(String key) { return redisTemplate.delete(key); } -} + + /* ==================== 新增:多数据库操作 ==================== */ + + /** + * 设置键值对到指定数据库 + */ + public void set(int database, String key, Object value) { + getRedisTemplate(database).opsForValue().set(key, value); + } + + /** + * 设置键值对到指定数据库并设置过期时间 + */ + public void set(int database, String key, Object value, long timeout, TimeUnit unit) { + getRedisTemplate(database).opsForValue().set(key, value, timeout, unit); + } + + /** + * 从指定数据库获取值 + */ + public Object get(int database, String key) { + return getRedisTemplate(database).opsForValue().get(key); + } + + /** + * 设置Hash键值对到指定数据库 + */ + public void hSet(int database, String key, String hashKey, Object value) { + getRedisTemplate(database).opsForHash().put(key, hashKey, value); + } + + /** + * 从指定数据库获取Hash值 + */ + public Object hGet(int database, String key, String hashKey) { + return getRedisTemplate(database).opsForHash().get(key, hashKey); + } + + /** + * 批量设置Hash键值对到指定数据库 + */ + public void hSetAll(int database, String key, Map map) { + getRedisTemplate(database).opsForHash().putAll(key, map); + } + + /** + * 从指定数据库获取所有Hash键值对 + */ + public Map hGetAll(int database, String key) { + return getRedisTemplate(database).opsForHash().entries(key); + } + + /** + * 从指定数据库删除Hash键 + */ + public Long hDelete(int database, String key, Object... hashKeys) { + return getRedisTemplate(database).opsForHash().delete(key, hashKeys); + } + + /** + * 添加有序集合元素到指定数据库 + */ + public Boolean zAdd(int database, String key, Object value, double score) { + return getRedisTemplate(database).opsForZSet().add(key, value, score); + } + + /** + * 从指定数据库获取有序集合范围 + */ + public Set zRange(int database, String key, long start, long end) { + return getRedisTemplate(database).opsForZSet().range(key, start, end); + } + + /** + * 从指定数据库按分数范围获取有序集合 + */ + public Set zRangeByScore(int database, String key, double min, double max) { + return getRedisTemplate(database).opsForZSet().rangeByScore(key, min, max); + } + + /** + * 从指定数据库删除有序集合元素 + */ + public Long zRemove(int database, String key, Object... values) { + return getRedisTemplate(database).opsForZSet().remove(key, values); + } + + /** + * 删除指定数据库的key + */ + public Boolean delete(int database, String key) { + return getRedisTemplate(database).delete(key); + } + + /** + * 判断指定数据库的key是否存在 + */ + public Boolean hasKey(int database, String key) { + return getRedisTemplate(database).hasKey(key); + } + + /** + * 设置指定数据库key的过期时间 + */ + public Boolean expire(int database, String key, long timeout, TimeUnit unit) { + return getRedisTemplate(database).expire(key, timeout, unit); + } + + /** + * 从指定数据库获取匹配的键 + */ + public Set keys(int database, String pattern) { + return getRedisTemplate(database).keys(pattern); + } + + /* ==================== 新增:便捷方法 ==================== */ + + /** + * 数据库2专用:添加车辆监控任务 + */ + public Boolean addMonitorTask(String bikeId, double score) { + return zAdd(Database.DB2, "bike:monitor:tasks", bikeId, score); + } + + /** + * 数据库2专用:获取到期的监控任务 + */ + public Set getExpiredMonitorTasks(double maxScore) { + return zRangeByScore(Database.DB2, "bike:monitor:tasks", 0, maxScore); + } + + /** + * 数据库2专用:删除监控任务 + */ + public Long removeMonitorTask(String bikeId) { + return zRemove(Database.DB2, "bike:monitor:tasks", bikeId); + } + + /** + * 数据库2专用:存储调度工单 + */ + public void saveDispatchOrder(String orderId, Object orderData) { + set(Database.DB2, "bike:dispatch:order:" + orderId, orderData); + } + + /** + * 数据库2专用:获取调度工单 + */ + public Object getDispatchOrder(String orderId) { + return get(Database.DB2, "bike:dispatch:order:" + orderId); + } + + /** + * 数据库2专用:存储调度工单并设置过期时间 + */ + public void saveDispatchOrder(String orderId, Object orderData, long timeout, TimeUnit unit) { + set(Database.DB2, "bike:dispatch:order:" + orderId, orderData, timeout, unit); + } + + /** + * 数据库2专用:批量添加监控任务 + */ + public void batchAddMonitorTasks(Map bikeScores) { + for (Map.Entry entry : bikeScores.entrySet()) { + zAdd(Database.DB2, "bike:monitor:tasks", entry.getKey(), entry.getValue()); + } + } + + /** + * 数据库2专用:获取监控任务数量 + */ + public Long getMonitorTaskCount() { + return getRedisTemplate(Database.DB2).opsForZSet().size("bike:monitor:tasks"); + } + + /** + * 数据库2专用:分布式锁(针对监控任务) + */ + public Boolean tryMonitorLock(String lockKey, Object value, long timeout, TimeUnit unit) { + return getRedisTemplate(Database.DB2).opsForValue().setIfAbsent(lockKey, value, timeout, unit); + } + + /** + * 数据库2专用:释放监控锁 + */ + public Boolean releaseMonitorLock(String lockKey) { + return delete(Database.DB2, lockKey); + } +} \ No newline at end of file diff --git a/ebike-report/src/main/resources/application-dev.yml b/ebike-report/src/main/resources/application-dev.yml index 4f316c3..1ca03c7 100644 --- a/ebike-report/src/main/resources/application-dev.yml +++ b/ebike-report/src/main/resources/application-dev.yml @@ -29,7 +29,7 @@ spring: # redis配置 redis: # Redis数据库索引(默认为0) - database: 2 + database: 1 # Redis服务器地址 host: 47.109.71.130 # Redis服务器连接端口