diff options
| author | shizhendong <[email protected]> | 2023-02-13 17:20:43 +0800 |
|---|---|---|
| committer | shizhendong <[email protected]> | 2023-02-13 17:20:43 +0800 |
| commit | e3a2c54c8f4972cc2a7dba244e987868dc13670e (patch) | |
| tree | ea7e3a0f1c906c8a5ac0b4100008953651152622 | |
| parent | a44aa12684199eea0db0494ad9f10e70beb7be82 (diff) | |
feat: NEZ-2524 监听 binlog 实现 Mysql & Reids 数据同步dev-3.7-query
1. Jedis 版本调整到 4.3.1,以支持 RedisJSON & RedisSearch API
2. 因 Shiro-redis 版本与 Jedis 4.0+ 不匹配,新增 RedisManager
9 files changed, 1300 insertions, 24 deletions
diff --git a/nz-admin/pom.xml b/nz-admin/pom.xml index cecbba23..1d356138 100644 --- a/nz-admin/pom.xml +++ b/nz-admin/pom.xml @@ -146,6 +146,7 @@ <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> + <version>${commons-lang3.version}</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> @@ -343,6 +344,21 @@ <artifactId>jsoup</artifactId> <version>1.14.1</version> </dependency> + + <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 --> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-pool2</artifactId> + <version>2.11.1</version> + </dependency> + + <!--mysql-binlog-connector-java--> + <dependency> + <groupId>com.zendesk</groupId> + <artifactId>mysql-binlog-connector-java</artifactId> + <version>0.25.0</version> + </dependency> + </dependencies> <build> diff --git a/nz-admin/src/main/java/com/nis/common/config/RedisConfig.java b/nz-admin/src/main/java/com/nis/common/config/RedisConfig.java index 0b642fa4..e917ab70 100644 --- a/nz-admin/src/main/java/com/nis/common/config/RedisConfig.java +++ b/nz-admin/src/main/java/com/nis/common/config/RedisConfig.java @@ -1,9 +1,8 @@ package com.nis.common.config; -import java.net.UnknownHostException; -import java.time.Duration; - -import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import cn.hutool.log.Log; +import com.nis.common.utils.Tool; +import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -16,12 +15,11 @@ import org.springframework.data.redis.connection.lettuce.LettucePoolingClientCon import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; - -import com.nis.common.utils.Tool; - -import cn.hutool.log.Log; -import lombok.Data; import org.springframework.data.redis.serializer.StringRedisSerializer; +import redis.clients.jedis.JedisPoolConfig; + +import java.net.UnknownHostException; +import java.time.Duration; /** * redis 初始化配置 @@ -72,19 +70,21 @@ public class RedisConfig { if(Tool.StrUtil.isNotBlank(this.getRedisPin())) { configuration.setPassword(this.getRedisPin()); } - GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); - poolConfig.setMinIdle(this.getMinIdle()); - poolConfig.setMaxIdle(this.getMaxIdle()); - poolConfig.setMaxTotal(this.getMaxActive()); - poolConfig.setMaxWaitMillis(this.getMaxWait()); + JedisPoolConfig poolConfig = new JedisPoolConfig(); + poolConfig.setMinIdle(this.getMinIdle()); + poolConfig.setMaxIdle(this.getMaxIdle()); + poolConfig.setMaxTotal(this.getMaxActive()); + poolConfig.setMaxWait(Duration.ofMillis(this.getMaxWait())); + + LettucePoolingClientConfiguration lettucePoolingClientConfiguration = LettucePoolingClientConfiguration.builder() + .commandTimeout(Duration.ofMillis(this.getRedisTimeout())) + .shutdownTimeout(Duration.ZERO) + .poolConfig(poolConfig) + .build(); - LettucePoolingClientConfiguration lettucePoolingClientConfiguration = LettucePoolingClientConfiguration.builder() - .commandTimeout(Duration.ofMillis(this.getRedisTimeout())) - .shutdownTimeout(Duration.ZERO) - .poolConfig(poolConfig) - .build(); - - RedisConnectionFactory factory = new LettuceConnectionFactory(configuration, lettucePoolingClientConfiguration); + RedisConnectionFactory factory = new LettuceConnectionFactory(configuration, lettucePoolingClientConfiguration); + // setValidateConnection + //((LettuceConnectionFactory) factory).setValidateConnection(true); return factory; } diff --git a/nz-admin/src/main/java/com/nis/common/config/SetupRunner.java b/nz-admin/src/main/java/com/nis/common/config/SetupRunner.java index 2370284a..ca78e6a0 100644 --- a/nz-admin/src/main/java/com/nis/common/config/SetupRunner.java +++ b/nz-admin/src/main/java/com/nis/common/config/SetupRunner.java @@ -14,6 +14,7 @@ import com.nis.modules.panel.entity.VisualPanel; import com.nis.modules.panel.service.VisualPanelService; import com.nis.modules.panel.utils.DashboardConstant; import com.nis.modules.report.job.ReportJobManager; +import com.nis.modules.sys.backend.DbSyncRedisThread; import com.nis.modules.sys.entity.SysUserEntity; import com.nis.modules.sys.job.SysBackJobManager; import com.nis.modules.sys.service.LicenseService; @@ -73,6 +74,9 @@ public class SetupRunner implements CommandLineRunner{ @Autowired private VsysTaskConfigThread vsysTaskConfigThread; + + @Autowired + private DbSyncRedisThread dbSyncRedisThread; @@ -115,6 +119,10 @@ public class SetupRunner implements CommandLineRunner{ Tool.ThreadUtil.execute(vsysTaskConfigThread); log.info("启动 {} 成功", "VsysTaskConfigThread"); + // 启动 Resis & Mysql 数据同步线程 + Tool.ThreadUtil.execute(dbSyncRedisThread); + log.info("启动 {} 成功", "DbSyncRedisThread"); + if (inited == 2) { log.info(" inited = {} ,skip init setup", inited); return; diff --git a/nz-admin/src/main/java/com/nis/common/config/ShiroConfig.java b/nz-admin/src/main/java/com/nis/common/config/ShiroConfig.java index 910991f0..67359bf4 100644 --- a/nz-admin/src/main/java/com/nis/common/config/ShiroConfig.java +++ b/nz-admin/src/main/java/com/nis/common/config/ShiroConfig.java @@ -8,6 +8,7 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; +import com.nis.modules.sys.shiro.MyRedisManager; import org.apache.catalina.connector.Connector; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.mgt.SessionManager; @@ -218,8 +219,8 @@ public class ShiroConfig { * * @return */ - public RedisManager redisManager() { - RedisManager redisManager = new RedisManager(); + public MyRedisManager redisManager() { + MyRedisManager redisManager = new MyRedisManager(); redisManager.setHost(config.getRedisHost() + ":" + config.getRedisPort()); redisManager.setTimeout(Tool.NumberUtil.parseInt(Tool.StrUtil.toString(config.getRedisTimeout()))); redisManager.setDatabase(config.getRedisDatabase()); diff --git a/nz-admin/src/main/java/com/nis/modules/sys/backend/DbSyncRedisThread.java b/nz-admin/src/main/java/com/nis/modules/sys/backend/DbSyncRedisThread.java new file mode 100644 index 00000000..27bb62b6 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/sys/backend/DbSyncRedisThread.java @@ -0,0 +1,569 @@ +package com.nis.modules.sys.backend; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; +import com.github.shyiko.mysql.binlog.BinaryLogClient; +import com.github.shyiko.mysql.binlog.event.*; +import com.google.gson.Gson; +import com.nis.common.utils.Constant; +import com.nis.common.utils.RedisLock; +import com.nis.common.utils.Tool; +import com.nis.modules.alert.entity.AlertRuleEntity; +import com.nis.modules.alert.service.AlertRuleService; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.entity.AssetModel; +import com.nis.modules.asset.entity.Dc; +import com.nis.modules.asset.service.AssetAssetService; +import com.nis.modules.asset.service.AssetModelService; +import com.nis.modules.asset.service.DcService; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.endpoint.service.MonitorEndpointService; +import com.nis.modules.module.entity.MonitorModule; +import com.nis.modules.module.service.MonitorModuleService; +import com.nis.modules.project.entity.MonitorProject; +import com.nis.modules.project.service.MonitorProjectService; +import com.nis.modules.sys.util.RedisSearchUtil; +import org.apache.commons.lang3.time.StopWatch; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import redis.clients.jedis.JedisPooled; + +import java.io.IOException; +import java.io.Serializable; +import java.time.Duration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * DbSyncRedisThread + * 通过监听 binlog,将 mysql 数据同步到 redis + * + * @author shizhendong + * @date 2023-02-03 + */ +@Component +public class DbSyncRedisThread implements Runnable { + + private static final Log log = Log.get(); + + @Value("${database.host}") + private String databaseHost; + @Value("${database.port:3306}") + private int databasePort; + @Value("${database.user}") + private String databaseUser; + @Value("${database.pin}") + private String databasePin; + + @Value("${redis.host}") + private String redisHost; + @Value("${redis.port:6379}") + private int redisPort; + @Value("${redis.database:0}") + private int redisDatabase; + @Value("${redis.pin}") + private String redisPin; + @Value("${spring.redis.jedis.pool.max-idle:10}") + private int maxIdle; + @Value("${spring.redis.jedis.pool.min-idle:3}") + private int minIdle; + @Value("${spring.redis.jedis.pool.max-wait:100000}") + private int maxWait; + @Value("${spring.redis.jedis.pool.max-active:100}") + private int maxActive; + @Value("${spring.redis.timeout:100000}") + private int redisTimeout; + + /** + * table_columns_map + * key: table_name + * value: table columns info. include ordinal_position and column_name. + */ + private static Map<String, Object> TABLE_COLUMNS_MAP; + + /** + * redis key + * sync binlog position + */ + private static final String REDIS_KEY_BINLOG_POSITION = "sync_binlog_position"; + + /** + * sync_table_names + * 数据同步的表名称 + */ + private static List<String> SYNC_TABLE_NAMES = Tool.ListUtil.of( + "dc", "asset_asset", "asset_model", + "monitor_project", "monitor_module", "monitor_endpoint", + "alert_rule", "alert_message_active", "alert_message_history", "alert_message_silence" + ); + + private JedisPooled jedisClient; + + private static final Gson GSON = new Gson(); + + @Autowired + private RedisLock redisLock; + + @Autowired + private DcService dcService; + + @Autowired + private AssetAssetService assetService; + + @Autowired + private AssetModelService assetModelService; + + @Autowired + private MonitorProjectService projectService; + + @Autowired + private MonitorModuleService moduleService; + + @Autowired + private MonitorEndpointService endpointService; + + @Autowired + private AlertRuleService alertRuleService; + + @Autowired + private RedisTemplate<String, String> redisTemplate; + + /** + * init Columns Mapping + */ + private void initTableCloumnsMapping() { + log.info("[initTableCloumnsMapping] [init table columns info begin]"); + + TABLE_COLUMNS_MAP = Tool.MapUtil.newHashMap(); + String querySqlStr = StrUtil.concat(true, "SELECT ", + "TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION ", + "FROM ", + "INFORMATION_SCHEMA.COLUMNS ", + "WHERE TABLE_SCHEMA = DATABASE();"); + List<Map<String, Object>> selectList = SqlRunner.db().selectList(querySqlStr); + Map<String, List<Map<String, Object>>> tMap = selectList.stream() + .filter(map -> SYNC_TABLE_NAMES.contains(StrUtil.toString(map.get("TABLE_NAME")))) + .collect(Collectors.groupingBy(map -> StrUtil.toString(map.get("TABLE_NAME")))); + + for (Map.Entry<String, List<Map<String, Object>>> entry : tMap.entrySet()) { + String tableName = entry.getKey(); + List<Map<String, Object>> value = entry.getValue(); + + Map<Integer, String> positionWithNameMapping = value.stream() + .collect(Collectors.toMap( + map -> { + String ordinalPosition = map.get("ORDINAL_POSITION").toString(); + return Integer.valueOf(ordinalPosition); + }, + map -> { + String columnName = map.get("COLUMN_NAME").toString(); + return StringUtils.underlineToCamel(columnName); + })); + TABLE_COLUMNS_MAP.put(tableName, positionWithNameMapping); + } + + log.info("[initTableCloumnsMapping] [table columns map size: {}]", TABLE_COLUMNS_MAP.size()); + } + + @Override + public void run() { + Thread.currentThread().setName("Db Sync Redis Thread"); + log.info("DbSyncRedisThread start..."); + + // init Table Cloumns Mapping + this.initTableCloumnsMapping(); + + // jedis client + this.jedisClient = this.buildJedisPool(redisHost, redisPort, redisTimeout, redisPin, redisDatabase, maxIdle, minIdle, maxWait, maxActive); + + BinaryLogClient binaryLogClient = null; + try { + binaryLogClient = this.buildBinaryLogClient(this.databaseHost, this.databasePort, this.databaseUser, this.databasePin); + + // binaryLogClient.setEventDeserializer(); + + // Lifecycle Listener + binaryLogClient.registerLifecycleListener(this.buildLifecycleListener()); + + // Event Listener + binaryLogClient.registerEventListener(this.buildEventListener()); + + try { + // connect + binaryLogClient.connect(); + } catch (IOException e) { + log.error(e, "[DbSyncRedisThread] [BinaryLogClient connect error]"); + } + } finally { + // disconnect + try { + if (binaryLogClient != null) { + binaryLogClient.disconnect(); + } + } catch (IOException e) { + log.error(e, "[DbSyncRedisThread] [disconnect BinaryLogClient error]"); + } + + // close + Tool.IoUtil.close(this.jedisClient); + } + } + + + /** + * build Jedis Pool + * + * @param redisHost + * @param redisPort + * @param redisTimeout + * @param redisPin + * @param redisDatabase + * @param maxIdle + * @param minIdle + * @param maxWait + * @param maxActive + * @return + */ + private JedisPooled buildJedisPool(String redisHost, int redisPort, int redisTimeout, String redisPin, int redisDatabase, int maxIdle, int minIdle, int maxWait, int maxActive) { + log.info("[buildJedisPool] [begin]"); + log.info("[buildJedisPool] [redisHost: {}] [redisPort: {}] [redisDatabase: {}]", redisHost, redisPort, redisDatabase); + + GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); + poolConfig.setMaxIdle(maxIdle); + poolConfig.setMinIdle(minIdle); + poolConfig.setMaxTotal(maxActive); + poolConfig.setMaxWait(Duration.ofMillis(maxWait)); + + JedisPooled jedisPooled = new JedisPooled(poolConfig, redisHost, redisPort, redisTimeout, StrUtil.emptyToNull(redisPin), redisDatabase); + log.info("[buildJedisPool] [finshed]"); + return jedisPooled; + } + + /** + * build Binary Log Client + * + * @param databaseHost + * @param databasePort + * @param databaseUser + * @param databasePin + * @return + */ + private BinaryLogClient buildBinaryLogClient(String databaseHost, int databasePort, String databaseUser, String databasePin) { + log.info("[buildBinaryLogClient] [begin]"); + log.info("[buildBinaryLogClient] [databaseHost: {}] [databasePort: {}] [databaseUser: {}]", databaseHost, databasePort, databaseUser); + + // 数据库密码解密 + databasePin = Tool.AesUtil.decrypt(databasePin, Constant.AES_SECRET_KEY); + + // Binary Log Client + BinaryLogClient client = new BinaryLogClient(databaseHost, databasePort, databaseUser, databasePin); + + log.info("[buildBinaryLogClient] [finshed]"); + return client; + } + + /** + * build Lifecycle Listener + * 1. create Redis Search Index + * 2. update full data + * + * @return + */ + private BinaryLogClient.AbstractLifecycleListener buildLifecycleListener() { + log.info("[buildLifecycleListener] [begin]"); + BinaryLogClient.AbstractLifecycleListener lifecycleListener = new BinaryLogClient.AbstractLifecycleListener() { + @Override + public void onConnect(BinaryLogClient client) { + super.onConnect(client); + + // HA + try { + boolean lock = redisLock.lock("lock_db_sync_redis", Constant.SERVER_ID, 5L); + log.info("[onConnect] [Get sync lock from redis] [result: {}]", lock); + if (lock) { + // create Redis Search Index + // TODO https://github.com/RediSearch/RediSearch/issues/367 + RedisSearchUtil redisSearchUtil = RedisSearchUtil.RedisSearchUtilBuilder.builder() + .jedisPooled(jedisClient) + .build(); + // create Redis Search Index + redisSearchUtil.createRedisSearchIndex(); + + // db + long currentBinlogPosition = client.getBinlogPosition(); + // redis + String binlogPositionInRedis = redisTemplate.opsForValue().get(REDIS_KEY_BINLOG_POSITION); + log.info("[onConnect] [binlog position] [db: {}] [redis: {}]", currentBinlogPosition, binlogPositionInRedis); + + if (!StrUtil.equals(StrUtil.toString(currentBinlogPosition), binlogPositionInRedis)) { + log.info("[onConnect] [binlog position is updated. full update cache data]"); + // 全量更新-同步 + updateAll(); + // update position + redisTemplate.opsForValue().set(REDIS_KEY_BINLOG_POSITION, StrUtil.toString(currentBinlogPosition)); + } else { + log.info("[onConnect] [binlog position not updated. do not update cached data]"); + } + } else { + log.warn("[DbSyncRedisThread] [did not get the sync lock, do not update cached data]"); + } + } finally { + redisLock.unlock("lock_db_sync_redis", Constant.SERVER_ID); + } + } + }; + log.info("[buildLifecycleListener] [finshed]"); + return lifecycleListener; + } + + /** + * build Event Listener + * + * @return + */ + private BinaryLogClient.EventListener buildEventListener() { + log.info("[buildEventListener] [begin]"); + BinaryLogClient.EventListener eventListener = new BinaryLogClient.EventListener() { + @Override + public void onEvent(Event event) { + // 检查 HA mode + String serverId = redisTemplate.opsForValue().get(Constant.SYS_HA_LOCK); + if (!Tool.StrUtil.equals(serverId, Constant.SERVER_ID)) { + return; + } + + EventHeader eventHeader = event.getHeader(); + EventType eventType = eventHeader.getEventType(); + EventData eventData = event.getData(); + + // table + if (Tool.ObjectUtil.equal(0, EventType.TABLE_MAP.compareTo(eventType))) { + TableMapEventData tableMapEventData = (TableMapEventData) eventData; + String tableName = tableMapEventData.getTable(); + if (SYNC_TABLE_NAMES.contains(tableName)) { + long tableId = tableMapEventData.getTableId(); + if (Tool.ObjectUtil.isNotNull(TABLE_COLUMNS_MAP.get(StrUtil.toString(tableId)))) { + return; + } + // TABLE_MAP 可监听到内容包含 table_id & table_name + // 其他 EVENT 只能获取到 table_id,table_id 只在监听时可获得,于是在 TABLE_MAP 事件做对应 + // TABLE_COLUMNS_MAP.put(StrUtil.toString(tableId), TABLE_COLUMNS_MAP.get(tableName)); + TABLE_COLUMNS_MAP.put(StrUtil.concat(true, StrUtil.toString(tableId), "_table_name"), tableName); + } + } + + // Insert + if (Tool.ObjectUtil.equal(0, EventType.WRITE_ROWS.compareTo(eventType))) { + WriteRowsEventData writeRowsEventData = (WriteRowsEventData) eventData; + String tableName = (String) TABLE_COLUMNS_MAP.get(StrUtil.toString(writeRowsEventData.getTableId()) + "_table_name"); + if (Tool.ObjectUtil.isNull(tableName)) return; + + Map<Integer, String> columnsInfo = (Map) TABLE_COLUMNS_MAP.get(tableName); + for (Serializable[] row : writeRowsEventData.getRows()) { + Map<Object, Object> insertEntityMap = Tool.MapUtil.builder().map(); + for (int i = 0; i < row.length; i++) { + insertEntityMap.put(columnsInfo.get(i + 1), row[i]); + } + // set + jedisClient.jsonSet(getKey(tableName, insertEntityMap.get("id")), GSON.toJson(insertEntityMap)); + } + } + + // Update + if (Tool.ObjectUtil.equal(0, EventType.UPDATE_ROWS.compareTo(eventType))) { + UpdateRowsEventData updateRowsEventData = (UpdateRowsEventData) eventData; + String tableName = (String) TABLE_COLUMNS_MAP.get(StrUtil.toString(updateRowsEventData.getTableId()) + "_table_name"); + if (Tool.ObjectUtil.isNull(tableName)) return; + + Map<Integer, String> columnsInfo = (Map) TABLE_COLUMNS_MAP.get(tableName); + for (Map.Entry<Serializable[], Serializable[]> entry : updateRowsEventData.getRows()) { + Serializable[] after = entry.getValue(); + Map<Object, Object> updateEntityMap = Tool.MapUtil.builder().map(); + for (int i = 0; i < after.length; i++) { + updateEntityMap.put(columnsInfo.get(i + 1), after[i]); + } + // set + jedisClient.jsonSet(getKey(tableName, updateEntityMap.get("id")), GSON.toJson(updateEntityMap)); + } + } + + // Delete + if (Tool.ObjectUtil.equal(0, EventType.DELETE_ROWS.compareTo(eventType))) { + DeleteRowsEventData deleteRowsEventData = (DeleteRowsEventData) eventData; + String tableName = (String) TABLE_COLUMNS_MAP.get(StrUtil.toString(deleteRowsEventData.getTableId()) + "_table_name"); + if (Tool.ObjectUtil.isNull(tableName)) return; + + Map<Integer, String> columnsInfo = (Map) TABLE_COLUMNS_MAP.get(tableName); + for (Serializable[] row : deleteRowsEventData.getRows()) { + for (int i = 0; i < row.length; i++) { + String fieldName = columnsInfo.get(i + 1); + if (StrUtil.equals("id", fieldName)) { + // del + jedisClient.del(getKey(tableName, row[i])); + } + } + } + } + + // XID + if (Tool.ObjectUtil.equal(0, EventType.XID.compareTo(eventType))) { + EventHeaderV4 header = (EventHeaderV4) eventHeader; + redisTemplate.opsForValue().set(REDIS_KEY_BINLOG_POSITION, StrUtil.toString(header.getNextPosition())); + } + } + }; + log.info("[buildEventListener] [finshed]"); + return eventListener; + } + + /** + * 全量更新 asset & endpoint 内容 + * 先删除后增 + */ + private void updateAll() { + log.info("[updateAll] [begin]"); + + StopWatch sw = new StopWatch(); + sw.start(); + try { + // remove + this.removeTablesCache(); + + // push + this.pushTablesCache(); + } catch (Exception e) { + log.error(e, "[updateAll] [error]"); + // 同步失败,停止服务 + Tool.RuntimeUtil.exec("systemctl stop nz-web.service"); + } finally { + sw.stop(); + } + log.info("[updateAll] [finshed] [Run Time: {}]", sw.toString()); + } + + /** + * remove Tables Cache + */ + private void removeTablesCache() { + log.info("[removeTableCache] [begin]"); + StopWatch sw = new StopWatch(); + sw.start(); + + Set<String> dcRemoveKeys = redisTemplate.keys("dc:*"); + if (Tool.CollUtil.isNotEmpty(dcRemoveKeys)) redisTemplate.delete(dcRemoveKeys); + + Set<String> assetRemoveKeys = redisTemplate.keys("asset_asset:*"); + if (Tool.CollUtil.isNotEmpty(assetRemoveKeys)) redisTemplate.delete(assetRemoveKeys); + + Set<String> assetModelRemoveKeys = redisTemplate.keys("asset_model:*"); + if (Tool.CollUtil.isNotEmpty(assetModelRemoveKeys)) redisTemplate.delete(assetModelRemoveKeys); + + Set<String> projectRemoveKeys = redisTemplate.keys("monitor_project:*"); + if (Tool.CollUtil.isNotEmpty(projectRemoveKeys)) redisTemplate.delete(projectRemoveKeys); + + Set<String> moduleRemoveKeys = redisTemplate.keys("monitor_module:*"); + if (Tool.CollUtil.isNotEmpty(moduleRemoveKeys)) redisTemplate.delete(moduleRemoveKeys); + + Set<String> endpointRemoveKeys = redisTemplate.keys("monitor_endpoint:*"); + if (Tool.CollUtil.isNotEmpty(endpointRemoveKeys)) redisTemplate.delete(endpointRemoveKeys); + + Set<String> ruleRemoveKeys = redisTemplate.keys("alert_rule:*"); + if (Tool.CollUtil.isNotEmpty(ruleRemoveKeys)) redisTemplate.delete(ruleRemoveKeys); + + Set<String> alertMsgActiveRemoveKeys = redisTemplate.keys("alert_message_active:*"); + if (Tool.CollUtil.isNotEmpty(alertMsgActiveRemoveKeys)) redisTemplate.delete(alertMsgActiveRemoveKeys); + + Set<String> alertMsgHistoryRemoveKeys = redisTemplate.keys("alert_message_history:*"); + if (Tool.CollUtil.isNotEmpty(alertMsgHistoryRemoveKeys)) redisTemplate.delete(alertMsgHistoryRemoveKeys); + + Set<String> alertMsgSilenceruleRemoveKeys = redisTemplate.keys("alert_message_silence:*"); + if (Tool.CollUtil.isNotEmpty(alertMsgSilenceruleRemoveKeys)) + redisTemplate.delete(alertMsgSilenceruleRemoveKeys); + + sw.stop(); + log.info("[removeTableCache] [finshed] [Run Time: {}]", sw.toString()); + } + + /** + * push Tables Cache + */ + private void pushTablesCache() { + log.info("[pushTablesCache] [begin]"); + StopWatch sw = new StopWatch(); + sw.start(); + + List<Dc> dcList = dcService.list(); + for (Dc dc : dcList) { + this.jedisClient.jsonSet(this.getKey("dc", dc.getId()), GSON.toJson(dc)); + } + + List<AssetAsset> assetList = assetService.list(); + for (AssetAsset asset : assetList) { + this.jedisClient.jsonSet(this.getKey("asset_asset", asset.getId()), GSON.toJson(asset)); + } + + List<AssetModel> modelList = assetModelService.list(); + for (AssetModel model : modelList) { + this.jedisClient.jsonSet(this.getKey("asset_model", model.getId()), GSON.toJson(model)); + } + + List<MonitorProject> projectList = projectService.list(); + for (MonitorProject project : projectList) { + this.jedisClient.jsonSet(this.getKey("monitor_project", project.getId()), GSON.toJson(project)); + } + + List<MonitorModule> moduleList = moduleService.list(); + for (MonitorModule module : moduleList) { + this.jedisClient.jsonSet(this.getKey("monitor_module", module.getId()), GSON.toJson(module)); + } + + List<MonitorEndpoint> endpointList = endpointService.list(); + for (MonitorEndpoint endpoint : endpointList) { + this.jedisClient.jsonSet(this.getKey("monitor_endpoint", endpoint.getId()), GSON.toJson(endpoint)); + } + + List<AlertRuleEntity> alertRuleList = alertRuleService.list(); + for (AlertRuleEntity alertRule : alertRuleList) { + this.jedisClient.jsonSet(this.getKey("alert_rule", alertRule.getId()), GSON.toJson(alertRule)); + } + + List<Map<String, Object>> alertMsgActiveList = SqlRunner.db().selectList("SELECT * FROM alert_message_active;"); + for (Map<String, Object> msgEntity : alertMsgActiveList) { + Map<String, Object> tMap = msgEntity.entrySet().stream().collect(HashMap::new, (k, v) -> k.put(StringUtils.underlineToCamel(v.getKey()), v.getValue()), HashMap::putAll); + this.jedisClient.jsonSet(this.getKey("alert_message_active", Tool.MapUtil.getStr(msgEntity, "id")), GSON.toJson(tMap)); + } + + List<Map<String, Object>> alertMsgHistoryList = SqlRunner.db().selectList("SELECT * FROM alert_message_history;"); + for (Map<String, Object> msgEntity : alertMsgHistoryList) { + Map<String, Object> tMap = msgEntity.entrySet().stream().collect(HashMap::new, (k, v) -> k.put(StringUtils.underlineToCamel(v.getKey()), v.getValue()), HashMap::putAll); + this.jedisClient.jsonSet(this.getKey("alert_message_history", Tool.MapUtil.getStr(msgEntity, "id")), GSON.toJson(tMap)); + } + + List<Map<String, Object>> alertMsgSilenceList = SqlRunner.db().selectList("SELECT * FROM alert_message_silence;"); + for (Map<String, Object> msgEntity : alertMsgSilenceList) { + Map<String, Object> tMap = msgEntity.entrySet().stream().collect(HashMap::new, (k, v) -> k.put(StringUtils.underlineToCamel(v.getKey()), v.getValue()), HashMap::putAll); + this.jedisClient.jsonSet(this.getKey("alert_message_silence", Tool.MapUtil.getStr(msgEntity, "id")), GSON.toJson(tMap)); + } + sw.stop(); + log.info("[pushTablesCache] [finshed] [Run Time: {}]", sw.toString()); + } + + /** + * get Key + * + * @param prefix table name + * @param id + * @return + */ + private String getKey(String prefix, Object id) { + return StrUtil.concat(true, prefix, ":", StrUtil.toString(id)); + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/sys/shiro/MyRedisManager.java b/nz-admin/src/main/java/com/nis/modules/sys/shiro/MyRedisManager.java new file mode 100644 index 00000000..d7659f21 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/sys/shiro/MyRedisManager.java @@ -0,0 +1,92 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by Fernflower decompiler) +// + +package com.nis.modules.sys.shiro; + +import org.crazycake.shiro.IRedisManager; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; + +/** + * MyRedisManager + * 重写自 org.crazycake.shiro.RedisManager + * 重写原因:shiro-redis 最高版本仅支持 Jedis 3.3.0,重写该类解决 jedis api 调用报错问题 + * + * @author shizhendong + * @date 2023-02-13 + */ +public class MyRedisManager extends WorkAloneRedisManager implements IRedisManager { + private static final String DEFAULT_HOST = "127.0.0.1:6379"; + private String host = "127.0.0.1:6379"; + private int timeout = 2000; + private String password; + private int database = 0; + private JedisPool jedisPool; + + public MyRedisManager() { + } + + private void init() { + if (this.jedisPool == null) { + Class var1 = org.crazycake.shiro.RedisManager.class; + synchronized (org.crazycake.shiro.RedisManager.class) { + if (this.jedisPool == null) { + String[] hostAndPort = this.host.split(":"); + this.jedisPool = new JedisPool(this.getJedisPoolConfig(), hostAndPort[0], Integer.parseInt(hostAndPort[1]), this.timeout, this.password, this.database); + } + } + } + + } + + @Override + protected Jedis getJedis() { + if (this.jedisPool == null) { + this.init(); + } + + return this.jedisPool.getResource(); + } + + public String getHost() { + return this.host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getTimeout() { + return this.timeout; + } + + public void setTimeout(int timeout) { + this.timeout = timeout; + } + + public String getPassword() { + return this.password; + } + + public void setPassword(String password) { + this.password = password; + } + + public int getDatabase() { + return this.database; + } + + public void setDatabase(int database) { + this.database = database; + } + + public JedisPool getJedisPool() { + return this.jedisPool; + } + + public void setJedisPool(JedisPool jedisPool) { + this.jedisPool = jedisPool; + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/sys/shiro/WorkAloneRedisManager.java b/nz-admin/src/main/java/com/nis/modules/sys/shiro/WorkAloneRedisManager.java new file mode 100644 index 00000000..bc833935 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/sys/shiro/WorkAloneRedisManager.java @@ -0,0 +1,157 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by Fernflower decompiler) +// + +package com.nis.modules.sys.shiro; + +import org.crazycake.shiro.IRedisManager; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPoolConfig; +import redis.clients.jedis.params.ScanParams; +import redis.clients.jedis.resps.ScanResult; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +/** + * WorkAloneRedisManager + * 重写自 org.crazycake.shiro.common.WorkAloneRedisManager + * 重写原因:shiro-redis 最高版本仅支持 Jedis 3.3.0,重写该类解决 jedis api 调用报错问题 + * + * @author shizhendong + * @date 2023-02-13 + */ +public abstract class WorkAloneRedisManager implements IRedisManager { + protected static final int DEFAULT_COUNT = 100; + private int count = 100; + private JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); + + public WorkAloneRedisManager() { + } + + protected abstract Jedis getJedis(); + + @Override + public byte[] get(byte[] key) { + if (key == null) { + return null; + } else { + Jedis jedis = this.getJedis(); + + byte[] value; + try { + value = jedis.get(key); + } finally { + jedis.close(); + } + + return value; + } + } + + @Override + public byte[] set(byte[] key, byte[] value, int expireTime) { + if (key == null) { + return null; + } else { + Jedis jedis = this.getJedis(); + + try { + jedis.set(key, value); + if (expireTime > 0) { + jedis.expire(key, (long) expireTime); + } + } finally { + jedis.close(); + } + + return value; + } + } + + @Override + public void del(byte[] key) { + if (key != null) { + Jedis jedis = this.getJedis(); + + try { + jedis.del(key); + } finally { + jedis.close(); + } + + } + } + + @Override + public Long dbSize(byte[] pattern) { + long dbSize = 0L; + Jedis jedis = this.getJedis(); + + try { + ScanParams params = new ScanParams(); + params.count(this.count); + params.match(pattern); + byte[] cursor = ScanParams.SCAN_POINTER_START_BINARY; + + ScanResult scanResult; + do { + scanResult = jedis.scan(cursor, params); + List<byte[]> results = scanResult.getResult(); + + for (Iterator var9 = results.iterator(); var9.hasNext(); ++dbSize) { + byte[] result = (byte[]) var9.next(); + } + + cursor = scanResult.getCursorAsBytes(); + } while (scanResult.getCursor().compareTo(ScanParams.SCAN_POINTER_START) > 0); + } finally { + jedis.close(); + } + + return dbSize; + } + + @Override + public Set<byte[]> keys(byte[] pattern) { + Set<byte[]> keys = new HashSet(); + Jedis jedis = this.getJedis(); + + try { + ScanParams params = new ScanParams(); + params.count(this.count); + params.match(pattern); + byte[] cursor = ScanParams.SCAN_POINTER_START_BINARY; + + ScanResult scanResult; + do { + scanResult = jedis.scan(cursor, params); + keys.addAll(scanResult.getResult()); + cursor = scanResult.getCursorAsBytes(); + } while (scanResult.getCursor().compareTo(ScanParams.SCAN_POINTER_START) > 0); + } finally { + jedis.close(); + } + + return keys; + } + + public int getCount() { + return this.count; + } + + public void setCount(int count) { + this.count = count; + } + + public JedisPoolConfig getJedisPoolConfig() { + return this.jedisPoolConfig; + } + + public void setJedisPoolConfig(JedisPoolConfig jedisPoolConfig) { + this.jedisPoolConfig = jedisPoolConfig; + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/sys/util/RedisSearchUtil.java b/nz-admin/src/main/java/com/nis/modules/sys/util/RedisSearchUtil.java new file mode 100644 index 00000000..1412ae89 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/sys/util/RedisSearchUtil.java @@ -0,0 +1,433 @@ +package com.nis.modules.sys.util; + +import cn.hutool.log.Log; +import com.nis.common.smartvalidate.ann.NotNull; +import com.nis.common.utils.Tool; +import lombok.Data; +import org.apache.commons.lang3.time.StopWatch; +import redis.clients.jedis.Connection; +import redis.clients.jedis.JedisPooled; +import redis.clients.jedis.commands.ProtocolCommand; +import redis.clients.jedis.search.IndexDefinition; +import redis.clients.jedis.search.IndexOptions; +import redis.clients.jedis.search.Schema; +import redis.clients.jedis.util.SafeEncoder; + +import java.util.Collections; +import java.util.List; + + +/** + * RedisSearchUtil + * 创建 RedisSearch Index + * 用法 : RedisSearchUtil.RedisSearchUtilBuilder.builder().jedisPooled(jedisClient).build().createRedisSearchIndex(); + * + * @author shizhendong + * @date 2023-02-03 + */ +@Data +public class RedisSearchUtil { + + private final static Log log = Log.get(); + + @NotNull + private JedisPooled jedisClient; + + /** + * query Existing Index List + * exec FT._LIST command by sendCommand() function + * + * @return + */ + private List<String> queryExistingIndexList() { + Connection resource = this.jedisClient.getPool().getResource(); + try { + ProtocolCommand protocolCommand = new ProtocolCommand() { + @Override + public byte[] getRaw() { + return SafeEncoder.encode("FT._LIST"); + } + }; + resource.sendCommand(protocolCommand); + + List<String> respList = Tool.ListUtil.list(true); + Object response = resource.getOne(); + if (response instanceof List) { + for (Object itemResp : ((List) response)) { + respList.add(new String((byte[]) itemResp)); + } + } else { + respList = Collections.singletonList(new String((byte[]) response)); + } + if (log.isDebugEnabled()) { + log.debug("[queryExistingIndexList] [finshed] [exist index size: {}] [content: {}]", respList.size(), Tool.JSONUtil.toJsonStr(respList)); + } + return respList; + } finally { + resource.close(); + } + } + + /** + * create Redis Search Index + */ + public void createRedisSearchIndex() { + log.info("[createRedisSearchIndex] [begin]"); + StopWatch sw = new StopWatch(); + sw.start(); + + // dc + this.createDcIndex(); + + // asset_asset + this.createAssetIndex(); + + // asset_model + this.createModelIndex(); + + // monitor_project + this.createProjectIndex(); + + // monitor_module + this.createModuleIndex(); + + // monitor_endpoint + this.createEndpointIndex(); + + // alert_rule + this.createAlertRuleIndex(); + + // alert_message_active + this.createAlertMsgActiveIndex(); + + // alert_message_history + this.createAlertMsgHistoryIndex(); + + // alert_message_silence + this.createAlertMsgSilenceIndex(); + + sw.stop(); + log.info("[createRedisSearchIndex] [finshed] [Run Time: {}]", sw.toString()); + } + + /** + * create Dc Index + */ + private void createDcIndex() { + log.info("[createDcIndex] [begin]"); + + String indexName = "dcIndex"; + + // query Existing Index List + List<String> existingIndexList = this.queryExistingIndexList(); + + boolean indexExist = existingIndexList.contains(indexName); + log.info("[createDcIndex] [index is exist: {}]", indexExist); + if (indexExist) this.jedisClient.ftDropIndex(indexName); + + IndexOptions indexOptions = IndexOptions.defaultOptions().setDefinition( + new IndexDefinition(IndexDefinition.Type.JSON).setPrefixes(new String[]{"dc:"}) + ); + + Schema schema = new Schema() + .addSortableNumericField("$.id").as("id") + .addSortableTextField("$.name", 1).as("name") + .addSortableTextField("$.state", 1).as("state") + .addTextField("$.location", 1); + // create index + this.jedisClient.ftCreate(indexName, indexOptions, schema); + + log.info("[createDcIndex] [finshed]"); + } + + /** + * create Asset Index + */ + private void createAssetIndex() { + log.info("[createAssetIndex] [begin]"); + + String indexName = "assetIndex"; + + // query Existing Index List + List<String> existingIndexList = this.queryExistingIndexList(); + + boolean indexExist = existingIndexList.contains(indexName); + log.info("[createDcIndex] [index is exist: {}]", indexExist); + if (indexExist) this.jedisClient.ftDropIndex(indexName); + + IndexOptions indexOptions = IndexOptions.defaultOptions().setDefinition( + new IndexDefinition(IndexDefinition.Type.JSON).setPrefixes(new String[]{"asset_asset:"}) + ); + + Schema schema = new Schema() + .addSortableNumericField("$.id").as("id") + .addSortableTextField("$.name", 1).as("name") + .addSortableTextField("$.sn", 1).as("sn") + .addSortableTextField("$.manageIp", 1).as("manageIp") + .addSortableNumericField("$.stateId").as("stateId") + .addSortableNumericField("$.modelId").as("modelId") + .addSortableNumericField("$.typeId").as("typeId"); + // create index + this.jedisClient.ftCreate(indexName, indexOptions, schema); + + log.info("[createAssetIndex] [finshed]"); + } + + /** + * create Model Index + */ + private void createModelIndex() { + log.info("[createModelIndex] [begin]"); + + String indexName = "modelIndex"; + + // query Existing Index List + List<String> existingIndexList = this.queryExistingIndexList(); + + boolean indexExist = existingIndexList.contains(indexName); + log.info("[createModelIndex] [index is exist: {}]", indexExist); + if (indexExist) this.jedisClient.ftDropIndex(indexName); + + IndexOptions indexOptions = IndexOptions.defaultOptions().setDefinition( + new IndexDefinition(IndexDefinition.Type.JSON).setPrefixes(new String[]{"asset_model:"}) + ); + + Schema schema = new Schema() + .addSortableNumericField("$.id").as("id") + .addSortableNumericField("$.brandId").as("brandId") + .addSortableTextField("$.name", 1).as("name"); + // create index + this.jedisClient.ftCreate(indexName, indexOptions, schema); + + log.info("[createModelIndex] [finshed]"); + } + + /** + * create Project Index + */ + private void createProjectIndex() { + log.info("[createProjectIndex] [begin]"); + + String indexName = "projectIndex"; + + // query Existing Index List + List<String> existingIndexList = this.queryExistingIndexList(); + + boolean indexExist = existingIndexList.contains(indexName); + log.info("[createDcIndex] [index is exist: {}]", indexExist); + if (indexExist) this.jedisClient.ftDropIndex(indexName); + + IndexOptions indexOptions = IndexOptions.defaultOptions().setDefinition( + new IndexDefinition(IndexDefinition.Type.JSON).setPrefixes(new String[]{"monitor_project:"}) + ); + Schema schema = new Schema() + .addSortableNumericField("$.id").as("id") + .addSortableTextField("$.name", 1).as("name"); + // create index + this.jedisClient.ftCreate(indexName, indexOptions, schema); + + log.info("[createProjectIndex] [finshed]"); + } + + /** + * create Module Index + */ + private void createModuleIndex() { + log.info("[createModuleIndex] [begin]"); + + String indexName = "moduleIndex"; + + // query Existing Index List + List<String> existingIndexList = this.queryExistingIndexList(); + + boolean indexExist = existingIndexList.contains(indexName); + log.info("[createDcIndex] [index is exist: {}]", indexExist); + if (indexExist) this.jedisClient.ftDropIndex(indexName); + + IndexOptions indexOptions = IndexOptions.defaultOptions().setDefinition( + new IndexDefinition(IndexDefinition.Type.JSON).setPrefixes(new String[]{"monitor_module:"}) + ); + Schema schema = new Schema() + .addSortableNumericField("$.id").as("id") + .addSortableTextField("$.name", 1).as("name"); + // create index + this.jedisClient.ftCreate(indexName, indexOptions, schema); + + log.info("[createModuleIndex] [finshed]"); + } + + /** + * create Endpoint Index + */ + private void createEndpointIndex() { + log.info("[createEndpointIndex] [begin]"); + + String indexName = "endpointIndex"; + + // query Existing Index List + List<String> existingIndexList = this.queryExistingIndexList(); + + boolean indexExist = existingIndexList.contains(indexName); + log.info("[createDcIndex] [index is exist: {}]", indexExist); + if (indexExist) this.jedisClient.ftDropIndex(indexName); + + IndexOptions indexOptions = IndexOptions.defaultOptions().setDefinition( + new IndexDefinition(IndexDefinition.Type.JSON).setPrefixes(new String[]{"monitor_endpoint:"}) + ); + + Schema schema = new Schema() + .addSortableNumericField("$.id").as("id") + .addSortableTextField("$.name", 1).as("name") + .addSortableNumericField("$.assetId").as("assetId") + .addSortableNumericField("$.moduleId").as("moduleId"); + // create index + this.jedisClient.ftCreate(indexName, indexOptions, schema); + + log.info("[createEndpointIndex] [finshed]"); + } + + /** + * create AlertRule Index + */ + private void createAlertRuleIndex() { + log.info("[createAlertRuleIndex] [begin]"); + + String indexName = "ruleIndex"; + + // query Existing Index List + List<String> existingIndexList = this.queryExistingIndexList(); + + boolean indexExist = existingIndexList.contains(indexName); + log.info("[createDcIndex] [index is exist: {}]", indexExist); + if (indexExist) this.jedisClient.ftDropIndex(indexName); + + IndexOptions indexOptions = IndexOptions.defaultOptions().setDefinition( + new IndexDefinition(IndexDefinition.Type.JSON).setPrefixes(new String[]{"alert_rule:"}) + ); + + Schema schema = new Schema() + .addSortableNumericField("$.id").as("id") + .addSortableTextField("$.name", 1).as("name") + .addSortableNumericField("$.severityId").as("severityId"); + // create index + this.jedisClient.ftCreate(indexName, indexOptions, schema); + + log.info("[createAlertRuleIndex] [finshed]"); + } + + + /** + * create Alert Msg Active Index + */ + private void createAlertMsgActiveIndex() { + log.info("[createAlertMsgActiveIndex] [begin]"); + + String indexName = "activeAlertMsgIndex"; + + // query Existing Index List + List<String> existingIndexList = this.queryExistingIndexList(); + + boolean indexExist = existingIndexList.contains(indexName); + log.info("[createDcIndex] [index is exist: {}]", indexExist); + if (indexExist) this.jedisClient.ftDropIndex(indexName); + + IndexOptions indexOptions = IndexOptions.defaultOptions().setDefinition( + new IndexDefinition(IndexDefinition.Type.JSON).setPrefixes(new String[]{"alert_message_active:"}) + ); + + Schema schema = new Schema() + .addSortableNumericField("$.id").as("id") + .addSortableNumericField("$.ruleId").as("ruleId") + .addSortableNumericField("$.assetId").as("assetId") + .addSortableNumericField("$.endpointId").as("endpointId") + .addTextField("$.summary", 1).as("summary") + .addTextField("$.labels", 1).as("labels"); + // create index + this.jedisClient.ftCreate(indexName, indexOptions, schema); + + log.info("[createAlertMsgActiveIndex] [finshed]"); + } + + /** + * create Alert Msg History Index + */ + private void createAlertMsgHistoryIndex() { + log.info("[createAlertMsgHistoryIndex] [begin]"); + + String indexName = "historyAlertMsgIndex"; + + // query Existing Index List + List<String> existingIndexList = this.queryExistingIndexList(); + + boolean indexExist = existingIndexList.contains(indexName); + log.info("[createDcIndex] [index is exist: {}]", indexExist); + if (indexExist) this.jedisClient.ftDropIndex(indexName); + + IndexOptions indexOptions = IndexOptions.defaultOptions().setDefinition( + new IndexDefinition(IndexDefinition.Type.JSON).setPrefixes(new String[]{"alert_message_history:"}) + ); + + Schema schema = new Schema() + .addSortableNumericField("$.id").as("id") + .addSortableNumericField("$.ruleId").as("ruleId") + .addSortableNumericField("$.assetId").as("assetId") + .addSortableNumericField("$.endpointId").as("endpointId") + .addTextField("$.summary", 1).as("summary") + .addTextField("$.labels", 1).as("labels"); + // create index + this.jedisClient.ftCreate(indexName, indexOptions, schema); + + log.info("[createAlertMsgHistoryIndex] [finshed]"); + } + + /** + * create Alert Msg Silence Index + */ + private void createAlertMsgSilenceIndex() { + log.info("[createAlertMsgHistoryIndex] [begin]"); + + String indexName = "silenceAlertMsgIndex"; + + // query Existing Index List + List<String> existingIndexList = this.queryExistingIndexList(); + + boolean indexExist = existingIndexList.contains(indexName); + log.info("[createDcIndex] [index is exist: {}]", indexExist); + if (indexExist) this.jedisClient.ftDropIndex(indexName); + + IndexOptions indexOptions = IndexOptions.defaultOptions().setDefinition( + new IndexDefinition(IndexDefinition.Type.JSON).setPrefixes(new String[]{"alert_message_silence:"}) + ); + + Schema schema = new Schema() + .addSortableNumericField("$.id").as("id") + .addSortableNumericField("$.ruleId").as("ruleId") + .addSortableNumericField("$.assetId").as("assetId") + .addSortableNumericField("$.endpointId").as("endpointId") + .addTextField("$.summary", 1).as("summary") + .addTextField("$.labels", 1).as("labels"); + // create index + this.jedisClient.ftCreate(indexName, indexOptions, schema); + + log.info("[createAlertMsgHistoryIndex] [finshed]"); + } + + public static class RedisSearchUtilBuilder { + + private RedisSearchUtil redisSearchUtil = new RedisSearchUtil(); + + public static RedisSearchUtilBuilder builder() { + return new RedisSearchUtilBuilder(); + } + + public RedisSearchUtilBuilder jedisPooled(JedisPooled jedisClient) { + this.redisSearchUtil.setJedisClient(jedisClient); + return this; + } + + public RedisSearchUtil build() { + return this.redisSearchUtil; + } + } + +} @@ -25,7 +25,7 @@ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <junit.version>4.12</junit.version> - <jedis.version>2.9.0</jedis.version> + <jedis.version>4.3.1</jedis.version> <druid.version>1.2.8</druid.version> <mybatisplus.version>3.0.7.1</mybatisplus.version> <mysql.version>8.0.27</mysql.version> |
