Browse Source

add:增加redis缓存v1

lvzhiqiang 1 year ago
parent
commit
396509557f

+ 12 - 1
pom.xml

@@ -148,12 +148,23 @@
             <version>0.21.0</version>
         </dependency>
 
-        <!-- https://mvnrepository.com/artifact/commons-net/commons-net -->
+        <!-- FTP文件操作 -->
         <dependency>
             <groupId>commons-net</groupId>
             <artifactId>commons-net</artifactId>
             <version>3.10.0</version>
         </dependency>
+
+        <!--redis-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson-spring-boot-starter</artifactId>
+            <version>3.11.5</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 54 - 0
src/main/java/top/lvzhiqiang/config/RedisAutoConfiguration.java

@@ -0,0 +1,54 @@
+package top.lvzhiqiang.config;
+
+import org.redisson.spring.starter.RedissonAutoConfiguration;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+import top.lvzhiqiang.util.RedisUtils;
+
+/**
+ * Redis自动配置类
+ *
+ * @author shiyong
+ * 2022/9/8 15:50
+ */
+@Configuration
+@AutoConfigureBefore(RedissonAutoConfiguration.class)
+public class RedisAutoConfiguration {
+
+    @Bean
+    @ConditionalOnMissingBean(name = "redisTemplate")
+    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
+        RedisTemplate<String, Object> template = new RedisTemplate<>();
+        template.setConnectionFactory(redisConnectionFactory);
+
+        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
+        RedisObjectSerializer redisObjectSerializer = new RedisObjectSerializer();
+
+        // key采用String的序列化方式
+        template.setKeySerializer(stringRedisSerializer);
+
+        // hash的key也采用String的序列化方式
+        template.setHashKeySerializer(stringRedisSerializer);
+
+        // value序列化方式采用字节数组
+        template.setValueSerializer(redisObjectSerializer);
+
+        // hash的value序列化方式采用字节数组
+        template.setHashValueSerializer(redisObjectSerializer);
+        template.afterPropertiesSet();
+        return template;
+    }
+
+    @Bean
+    @ConditionalOnMissingBean(name = "redisUtils")
+    public RedisUtils redisUtils(RedisTemplate<String, Object> redisTemplate) {
+        RedisUtils redisUtils = new RedisUtils();
+        redisUtils.setRedisTemplate(redisTemplate);
+        return redisUtils;
+    }
+}

+ 50 - 0
src/main/java/top/lvzhiqiang/config/RedisObjectSerializer.java

@@ -0,0 +1,50 @@
+package top.lvzhiqiang.config;
+
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.core.serializer.support.DeserializingConverter;
+import org.springframework.core.serializer.support.SerializingConverter;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.SerializationException;
+
+/**
+ * 自定义Redis序列化类
+ *
+ * @author shiyong
+ * 2020-01-03 18:01
+ */
+public class RedisObjectSerializer implements RedisSerializer<Object> {
+    private final Converter<Object, byte[]> serializer = new SerializingConverter();
+    private final Converter<byte[], Object> deserializer = new DeserializingConverter();
+    static final byte[] EMPTY_ARRAY = new byte[0];
+
+    /**
+     * Serialize the given object to binary data.
+     *
+     * @param o object to serialize. Can be {@literal null}.
+     * @return the equivalent binary data. Can be {@literal null}.
+     */
+    @Override
+    public byte[] serialize(Object o) throws SerializationException {
+        if (o == null) {
+            return EMPTY_ARRAY;
+        }
+
+        return serializer.convert(o);
+    }
+
+    /**
+     * Deserialize an object from the given binary data.
+     *
+     * @param bytes object binary representation. Can be {@literal null}.
+     * @return the equivalent object instance. Can be {@literal null}.
+     */
+    @Override
+    public Object deserialize(byte[] bytes) throws SerializationException {
+        if (bytes == null || bytes.length <= 0) {
+            return null;
+        }
+
+        return deserializer.convert(bytes);
+    }
+}
+

+ 5 - 0
src/main/java/top/lvzhiqiang/mapper/CoinMapper.java

@@ -1,5 +1,6 @@
 package top.lvzhiqiang.mapper;
 
+import com.alibaba.fastjson.JSONObject;
 import org.apache.ibatis.annotations.Insert;
 import org.apache.ibatis.annotations.MapKey;
 import org.apache.ibatis.annotations.Select;
@@ -156,4 +157,8 @@ public interface CoinMapper {
             " order by ${sortField} ${sort}" +
             "</script>"})
     List<CoinCmcMap> findCmcMapList(Map<String, Object> params);
+
+    @Select("SELECT * FROM coin_monitor_job WHERE delete_flag = 1")
+    @MapKey("job_name")
+    Map<String, JSONObject> findMonitorJobConfig();
 }

+ 4 - 0
src/main/java/top/lvzhiqiang/service/CoinService.java

@@ -5,6 +5,8 @@ import com.alibaba.fastjson.JSONObject;
 import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.bean.article.NewArticle;
 
+import java.util.Map;
+
 /**
  * Coin Service
  *
@@ -46,4 +48,6 @@ public interface CoinService {
     Object watchlistUpdate(String symbol, String remark);
 
     void syncCoinmarketcapCMap();
+
+    Map<String, JSONObject> getMonitorJobConfig();
 }

+ 100 - 12
src/main/java/top/lvzhiqiang/service/impl/CoinServiceImpl.java

@@ -14,6 +14,8 @@ import me.chanjar.weixin.cp.bean.message.WxCpMessage;
 import me.chanjar.weixin.cp.bean.message.WxCpMessageSendResult;
 import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
 import org.jsoup.Connection;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
@@ -105,6 +107,12 @@ public class CoinServiceImpl implements CoinService {
     @Resource
     private CoinApiConfigMapper coinApiConfigMapper;
 
+    @Resource
+    private RedissonClient redissonClient;
+
+    @Resource
+    private RedisUtils redisUtils;
+
     static {
         // API KEY作为一个字符串。
         basicHeaderMap.put("ACCESS-KEY", "bg_433d37306df0e8901c6d107c6d9e9111");
@@ -120,13 +128,13 @@ public class CoinServiceImpl implements CoinService {
         basicHeaderMap.put("locale", "zh-CN");
 
         // 字符串类型的APIKey
-        basicHeaderMap4OKX.put("OK-ACCESS-KEY","25e4f515-5efd-4bb9-a934-3949b21d9f10");
+        basicHeaderMap4OKX.put("OK-ACCESS-KEY", "25e4f515-5efd-4bb9-a934-3949b21d9f10");
         // 使用HMAC SHA256哈希函数获得哈希值,再使用Base-64编码(请参阅签名)
-        basicHeaderMap4OKX.put("OK-ACCESS-SIGN","");
+        basicHeaderMap4OKX.put("OK-ACCESS-SIGN", "");
         // 发起请求的时间(UTC),如:2020-12-08T09:08:57.715Z
-        basicHeaderMap4OKX.put("OK-ACCESS-TIMESTAMP","");
+        basicHeaderMap4OKX.put("OK-ACCESS-TIMESTAMP", "");
         // 您在创建API密钥时指定的Passphrase
-        basicHeaderMap4OKX.put("OK-ACCESS-PASSPHRASE","tmvxeGY#Q#Y2qm8");
+        basicHeaderMap4OKX.put("OK-ACCESS-PASSPHRASE", "tmvxeGY#Q#Y2qm8");
         // 统一设置为application/json
         basicHeaderMap4OKX.put("Content-Type", "application/json");
 
@@ -451,6 +459,10 @@ public class CoinServiceImpl implements CoinService {
     public String monitorJob() {
         // BITGET开仓平仓监控报警
         scheduler.scheduleWithFixedDelay(() -> {
+            if (!"1".equals(getMonitorJobStatus("bitget-mix-order"))) {
+                return;
+            }
+
             LocalDateTime endTime = LocalDateTime.now();
             // 全部历史委托列表
             Map<String, String> paramMap = new LinkedHashMap<>();
@@ -493,6 +505,10 @@ public class CoinServiceImpl implements CoinService {
 
         // OKX开仓平仓监控报警
         scheduler.scheduleWithFixedDelay(() -> {
+            if (!"1".equals(getMonitorJobStatus("okx-mix-order"))) {
+                return;
+            }
+
             LocalDateTime endTime = LocalDateTime.now();
             // 查看历史持仓信息
             Map<String, String> paramMap = new LinkedHashMap<>();
@@ -524,7 +540,11 @@ public class CoinServiceImpl implements CoinService {
             }
         }, 0, 10, TimeUnit.SECONDS);
 
-        scheduler.scheduleAtFixedRate(() -> {
+        scheduler.scheduleWithFixedDelay(() -> {
+            if (!"1".equals(getMonitorJobStatus("bitget-mix-returnrate"))) {
+                return;
+            }
+
             // BITGET全部合约仓位信息V2
             Map<String, String> paramMap = new HashMap<>();
             paramMap.put("productType", "umcbl");
@@ -616,6 +636,10 @@ public class CoinServiceImpl implements CoinService {
 
         // BITGET跟单员监控报警
         scheduler.scheduleWithFixedDelay(() -> {
+            if (!"1".equals(getMonitorJobStatus("bitget-mix-trader"))) {
+                return;
+            }
+
             List<String> monitorTraderList = coinMapper.findMonitorTraderList();
             forkJoinPool5.submit(() -> monitorTraderList.parallelStream().forEach(e -> {
                 LocalDateTime endTime = LocalDateTime.now();
@@ -660,7 +684,10 @@ public class CoinServiceImpl implements CoinService {
         }, 0, 3, TimeUnit.SECONDS);
 
         // 星球日报新闻快讯监控报警
-        /*scheduler.scheduleWithFixedDelay(() -> {
+        scheduler.scheduleWithFixedDelay(() -> {
+            if (!"1".equals(getMonitorJobStatus("news-odaily"))) {
+                return;
+            }
             try {
                 Connection.Response response = JsoupUtil.requestBody("https://www.odaily.news/v1/openapi/feeds", JsoupUtil.HTTP_GET, InitRunner.proxy, null, null);
                 JSONObject result = JSONObject.parseObject(response.body());
@@ -709,10 +736,13 @@ public class CoinServiceImpl implements CoinService {
                 }
             } catch (Exception e) {
             }
-        }, 0, 3, TimeUnit.SECONDS);*/
+        }, 0, 3, TimeUnit.SECONDS);
 
         // 律动日报新闻快讯监控报警
         scheduler.scheduleWithFixedDelay(() -> {
+            if (!"1".equals(getMonitorJobStatus("news-theblockbeats"))) {
+                return;
+            }
             try {
                 Map<String, String> paramMap = new HashMap<>();
                 paramMap.put("size", "10");
@@ -789,6 +819,10 @@ public class CoinServiceImpl implements CoinService {
 
         // coingecko
         scheduler.scheduleAtFixedRate(() -> {
+            if (!"1".equals(getMonitorJobStatus("watchlist-coingecko-cmc"))) {
+                return;
+            }
+
             Map<String, Object> params = new HashMap<>();
             params.put("sortField", "create_time");
             params.put("sort", "desc");
@@ -803,6 +837,9 @@ public class CoinServiceImpl implements CoinService {
 
         // Upbit交易所监控报警
         scheduler.scheduleWithFixedDelay(() -> {
+            if (!"1".equals(getMonitorJobStatus("upbit-digitalasset-notices"))) {
+                return;
+            }
             try {
                 Map<String, String> paramMap = new HashMap<>();
                 paramMap.put("page", "1");
@@ -1288,7 +1325,7 @@ public class CoinServiceImpl implements CoinService {
 
             renderMainSearch4CmcMap(cmcMapList);
             return cmcMapPageInfo;
-        }else if (params.getString("nameEn").equals("monitorCurrency")) {
+        } else if (params.getString("nameEn").equals("monitorCurrency")) {
             List<CoinMonitorCurrency> monitorCurrencyList = coinMapper.findMonitorCurrencyList();
 
             Map<String, JSONArray> resultMulti = new ConcurrentHashMap<>();
@@ -1569,16 +1606,16 @@ public class CoinServiceImpl implements CoinService {
             String symbol = jsonObject.getString("symbol").replace("USDT_UMCBL", "");
             jsonObject.put("symbol", "<strong style=\"background-color:#F1B90d;\"><font color=\"#242A30\">" + symbol + "</font></strong>USDT_UMCBL");
             // 标记价格
-            jsonObject.put("close",jsonObject.getString("last"));
+            jsonObject.put("close", jsonObject.getString("last"));
             jsonObject.put("closeStyle", " style=\"color:#252B31;background-color:#C4ADE9;font-weight:bold;\"");
             // 基础币量 计价币量 usdt币量
             jsonObject.put("baseVol", readableFileSize(jsonObject.getDouble("baseVolume")));
             jsonObject.put("quoteVol", readableFileSize(jsonObject.getDouble("quoteVolume")));
             jsonObject.put("usdtVol", readableFileSize(jsonObject.getDouble("quoteVolume")));
             // 其他字段兼容
-            jsonObject.put("openUtc0",jsonObject.getString("openUtc"));
-            jsonObject.put("buyOne",jsonObject.getString("bestBid"));
-            jsonObject.put("sellOne",jsonObject.getString("bestAsk"));
+            jsonObject.put("openUtc0", jsonObject.getString("openUtc"));
+            jsonObject.put("buyOne", jsonObject.getString("bestBid"));
+            jsonObject.put("sellOne", jsonObject.getString("bestAsk"));
         })).join();
 
         array4Spot.addAll(array4Mix);
@@ -1788,4 +1825,55 @@ public class CoinServiceImpl implements CoinService {
         int digitGroups = (int) (Math.log10(size) / Math.log10(1000));
         return df1.format(size / Math.pow(1000, digitGroups)) + units[digitGroups];
     }
+
+    public String getMonitorJobStatus(String jobName) {
+        Map<String, JSONObject> monitorJobConfig = getMonitorJobConfig();
+        if (null != monitorJobConfig && monitorJobConfig.containsKey(jobName)) {
+            return monitorJobConfig.get(jobName).getString("job_status");
+        }
+        return null;
+    }
+
+    @Override
+    public Map<String, JSONObject> getMonitorJobConfig() {
+        String cacheKey = "coin:monitor:job:list";
+
+        // 1. 缓存有,直接返回
+        if (redisUtils.hasKey(cacheKey) && redisUtils.get(cacheKey) != null) {
+            return (Map<String, JSONObject>) redisUtils.get(cacheKey);
+        }
+
+        // 加锁防止同时对一个数据发送多次请求
+        RLock lock = redissonClient.getLock("lock:" + cacheKey);
+        try {
+            // 2. 尝试加分布式锁,最多等待30秒,上锁以后60秒自动解锁
+            boolean lockFlag = lock.tryLock(30, 60, TimeUnit.SECONDS);
+            if (lockFlag) {
+                // 3. 加锁成功,二次检查,缓存有,直接返回
+                if (redisUtils.hasKey(cacheKey) && redisUtils.get(cacheKey) != null) {
+                    return (Map<String, JSONObject>) redisUtils.get(cacheKey);
+                }
+
+                // 4. 查数据库,并且按给定的时长加到缓存中
+                Map<String, JSONObject> monitorJobConfigMap = coinMapper.findMonitorJobConfig();
+
+                // 缓存监控任务配置信息
+                if (monitorJobConfigMap != null) {
+                    redisUtils.set(cacheKey, monitorJobConfigMap, 60, TimeUnit.MINUTES);
+                }
+
+                return monitorJobConfigMap;
+            } else {
+                log.error("getMonitorJobConfig 加锁失败 error,lockFlag: false");
+                return null;
+            }
+        } catch (Exception e) {
+            log.error("getMonitorJobConfig Exception", e);
+            return null;
+        } finally {
+            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
+                lock.unlock();
+            }
+        }
+    }
 }

+ 264 - 0
src/main/java/top/lvzhiqiang/util/RedisUtils.java

@@ -0,0 +1,264 @@
+package top.lvzhiqiang.util;
+
+import org.springframework.data.redis.core.RedisTemplate;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Redis工具类
+ *
+ * @author 施勇
+ * 2018年11月27日 下午9:26:11
+ */
+public class RedisUtils {
+
+    private RedisTemplate<String, Object> redisTemplate;
+
+    public RedisTemplate<String, Object> getRedisTemplate() {
+        return redisTemplate;
+    }
+
+    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
+        this.redisTemplate = redisTemplate;
+    }
+
+    /**
+     * 缓存对象信息
+     *
+     * @param key   键
+     * @param value 值
+     * @author 施勇
+     * 2018年12月11日 上午10:54:49
+     */
+    public void set(String key, Object value) {
+        redisTemplate.opsForValue().set(key, value);
+    }
+
+    /**
+     * 缓存信息,并设置缓存时间
+     *
+     * @param key      键
+     * @param value    值
+     * @param time     时间
+     * @param timeUnit 时间单位
+     * @author 施勇
+     * 2018年12月11日 上午10:54:27
+     */
+    public void set(String key, Object value, long time, TimeUnit timeUnit) {
+        if (time > 0) {
+            redisTemplate.opsForValue().set(key, value, time, timeUnit);
+        } else {
+            set(key, value);
+        }
+    }
+
+    /**
+     * 原子递增1
+     *
+     * @param key 键
+     * @return java.lang.Long
+     */
+    public Long increment(String key) {
+        return redisTemplate.opsForValue().increment(key);
+    }
+
+    /**
+     * 原子递增
+     *
+     * @param key   键
+     * @param delta 增量
+     * @return java.lang.Long
+     */
+    public Long increment(String key, Long delta) {
+        if (delta == null || delta < 1) {
+            delta = 1L;
+        }
+        return redisTemplate.opsForValue().increment(key, delta);
+    }
+
+    /**
+     * 递增
+     *
+     * @param key      键
+     * @param delta    递增因子
+     * @param time     时间
+     * @param timeUnit 时间单位
+     * @return java.lang.Long
+     * @author shiyong
+     * 2022/10/18 14:58
+     */
+    public Long increment(String key, Long delta, long time, TimeUnit timeUnit) {
+        if (null == delta || delta < 1) {
+            delta = 1L;
+        }
+        Long increment = redisTemplate.opsForValue().increment(key, delta);
+        redisTemplate.expire(key, time, timeUnit);
+        return increment;
+    }
+
+    /**
+     * 从缓存中获取信息
+     *
+     * @param key 键
+     * @return Object
+     * @author 施勇
+     * 2018年12月11日 上午10:54:10
+     */
+    public Object get(Object key) {
+        return key == null ? "" : redisTemplate.opsForValue().get(key);
+    }
+
+    /**
+     * 从redis中获取key对应的过期时间;
+     * 如果该值有过期时间,就返回相应的过期时间;
+     * 如果该值没有设置过期时间,就返回-1;
+     * 如果没有该值,就返回-2;
+     */
+    public Long getExpire(String key) {
+        return redisTemplate.opsForValue().getOperations().getExpire(key);
+    }
+
+    /**
+     * 设置key的失效时间
+     *
+     * @param key      键
+     * @param time     时长
+     * @param timeUnit 时间单位
+     * @return java.lang.Boolean
+     */
+    public Boolean expire(String key, long time, TimeUnit timeUnit) {
+        return redisTemplate.expire(key, time, timeUnit);
+    }
+
+    /**
+     * 是否存在key
+     *
+     * @param key 键
+     * @return boolean
+     * @author 施勇
+     * 2018年12月11日 上午10:53:54
+     */
+    public boolean hasKey(String key) {
+        if (null == key || "".equals(key)) {
+            return false;
+        }
+        Boolean result = redisTemplate.hasKey(key);
+        if (null == result) {
+            return false;
+        } else {
+            return result;
+        }
+    }
+
+    /**
+     * 删除KEY对应的对象
+     *
+     * @param key 键
+     * @author 施勇
+     * 2018年12月24日 下午4:14:26
+     */
+    public void delete(String key) {
+        redisTemplate.delete(key);
+    }
+
+    /**
+     * 查找匹配的key
+     *
+     * @param pattern 匹配字符串
+     * @return java.util.Set<java.lang.String>
+     * @author shiyong
+     * 2020/1/3 13:42
+     */
+    public Set<String> getKeys(String pattern) {
+        return redisTemplate.keys(pattern);
+    }
+
+    /**
+     * 在队尾追加元素
+     *
+     * @param key   键
+     * @param value 值
+     * @return 添加后队列的长度
+     */
+    public Long rightPush(String key, Object value) {
+        return redisTemplate.opsForList().rightPush(key, value);
+    }
+
+    /**
+     * 从队首移除元素
+     *
+     * @param key 键
+     * @return 移除的元素
+     */
+    public Object leftPop(String key) {
+        return redisTemplate.opsForList().leftPop(key);
+    }
+
+    /**
+     * 从队首开始取值,获取指定区间
+     *
+     * @param key   键
+     * @param start 开始下标
+     * @param stop  结束下标
+     * @return 区间内的全部值
+     */
+    public List<?> leftRange(String key, long start, long stop) {
+        return redisTemplate.opsForList().range(key, start, stop);
+    }
+
+    /**
+     * 将值加到集合中
+     *
+     * @param key    键
+     * @param values 值
+     * @return 添加是否成功(1:成功,0:失败)
+     */
+    public Long addToSet(String key, Object... values) {
+        return redisTemplate.opsForSet().add(key, values);
+    }
+
+    /**
+     * 集合的数量
+     *
+     * @param key 键
+     * @return 集合数量
+     */
+    public Long sizeOfSet(String key) {
+        return redisTemplate.opsForSet().size(key);
+    }
+
+    /**
+     * 集合列表
+     *
+     * @param key 键
+     * @return 集合列表
+     */
+    public Set<Object> getOfSet(String key) {
+        return redisTemplate.opsForSet().members(key);
+    }
+
+    /**
+     * 集合中是否有该值
+     *
+     * @param key   键
+     * @param value 值
+     * @return Boolean
+     */
+    public Boolean hasOfSet(String key, Object value) {
+        return redisTemplate.opsForSet().isMember(key, value);
+    }
+
+    /**
+     * 删除集合中值
+     *
+     * @param key   键
+     * @param value 值
+     * @return 删除是否成功(1:成功,0:失败)
+     */
+    public Long removeOfSet(String key, Object value) {
+        return redisTemplate.opsForSet().remove(key, value);
+    }
+
+}

+ 4 - 0
src/main/resources/application-dev.yml

@@ -43,6 +43,10 @@ spring:
       # 生效超时
       validation-timeout: 3000
       connection-test-query: SELECT 1
+  # Redis配置
+  redis:
+    redisson:
+      config: classpath:env/dev/redisson.yml
 # 日志配置
 logging:
   config: classpath:env/dev/log4j2-spring.xml

+ 4 - 0
src/main/resources/application-test.yml

@@ -43,6 +43,10 @@ spring:
       # 生效超时
       validation-timeout: 3000
       connection-test-query: SELECT 1
+  # Redis配置
+  redis:
+    redisson:
+      config: classpath:env/test/redisson.yml
 # 日志配置
 logging:
   config: classpath:env/test/log4j2-spring.xml

+ 24 - 0
src/main/resources/env/dev/redisson.yml

@@ -0,0 +1,24 @@
+singleServerConfig:
+  idleConnectionTimeout: 10000
+  pingTimeout: 2000
+  connectTimeout: 10000
+  timeout: 6000
+  retryAttempts: 3
+  retryInterval: 2000
+  reconnectionTimeout: 6000
+  failedAttempts: 3
+  password: foobared
+  subscriptionsPerConnection: 5
+  clientName: null
+  address: "redis://204.13.154.148:6379"
+  subscriptionConnectionMinimumIdleSize: 1
+  subscriptionConnectionPoolSize: 50
+  connectionMinimumIdleSize: 50
+  connectionPoolSize: 300
+  database: 2
+  dnsMonitoringInterval: 5000
+  pingConnectionInterval: 30000
+threads: 16
+nettyThreads: 16
+codec: !<org.redisson.codec.JsonJacksonCodec> {}
+transportMode: "NIO"

+ 24 - 0
src/main/resources/env/test/redisson.yml

@@ -0,0 +1,24 @@
+singleServerConfig:
+  idleConnectionTimeout: 10000
+  pingTimeout: 2000
+  connectTimeout: 10000
+  timeout: 6000
+  retryAttempts: 3
+  retryInterval: 2000
+  reconnectionTimeout: 6000
+  failedAttempts: 3
+  password: foobared
+  subscriptionsPerConnection: 5
+  clientName: null
+  address: "redis://204.13.154.148:6379"
+  subscriptionConnectionMinimumIdleSize: 1
+  subscriptionConnectionPoolSize: 50
+  connectionMinimumIdleSize: 50
+  connectionPoolSize: 300
+  database: 2
+  dnsMonitoringInterval: 5000
+  pingConnectionInterval: 30000
+threads: 16
+nettyThreads: 16
+codec: !<org.redisson.codec.JsonJacksonCodec> {}
+transportMode: "NIO"

+ 5 - 5
src/main/resources/static/coin.html

@@ -72,7 +72,7 @@
     }
 
     .selected-value {
-        font-size: 13px;
+        font-size: 14px;
         display: inline-block;
         padding: 0 0.5em;
         background: rgba(206, 205, 202, 0.5);
@@ -218,7 +218,7 @@
             <button class="apis-quiet-div-button3" slideDiv="apis-quiet-content" pageO="prev">上一页</button>
             <button class="apis-quiet-div-button3" slideDiv="apis-quiet-content" pageO="next">下一页</button>
             <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-watchlist-pageNo" value="1">
-            <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-watchlist-pageSize" disabled="disabled" value="25">
+            <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-watchlist-pageSize" disabled="disabled" value="20">
             <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-watchlist-pages" disabled="disabled" value="999999">
             <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-watchlist-keyword" placeholder="名称关键词">
             <select id="apis-quiet-div-watchlist-filterField" style="height: 24px;">
@@ -265,7 +265,7 @@
             <button class="apis-quiet-div-button3" slideDiv="apis-quiet-content" pageO="prev">上一页</button>
             <button class="apis-quiet-div-button3" slideDiv="apis-quiet-content" pageO="next">下一页</button>
             <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-cmcmap-pageNo" value="1">
-            <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-cmcmap-pageSize" disabled="disabled" value="25">
+            <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-cmcmap-pageSize" disabled="disabled" value="20">
             <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-cmcmap-pages" disabled="disabled" value="999999">
             <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-cmcmap-keyword" placeholder="关键词">
             <select id="apis-quiet-div-cmcmap-filterField" style="height: 24px;">
@@ -289,7 +289,7 @@
             <button class="apis-quiet-div-button3" slideDiv="apis-quiet-content" pageO="prev">上一页</button>
             <button class="apis-quiet-div-button3" slideDiv="apis-quiet-content" pageO="next">下一页</button>
             <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-traderList-pageNo" value="1">
-            <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-traderList-pageSize" disabled="disabled" value="25">
+            <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-traderList-pageSize" disabled="disabled" value="20">
             <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-traderList-pages" disabled="disabled" value="999999">
             <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-traderList-keyword" placeholder="昵称关键词">
             <select id="apis-quiet-div-traderList-sortField" style="height: 24px;">
@@ -323,7 +323,7 @@
             <button class="apis-quiet-div-button3" slideDiv="apis-quiet-content" pageO="prev">上一页</button>
             <button class="apis-quiet-div-button3" slideDiv="apis-quiet-content" pageO="next">下一页</button>
             <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-orderHistoryProductType-pageNo" value="1">
-            <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-orderHistoryProductType-pageSize" disabled="disabled" value="25">
+            <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-orderHistoryProductType-pageSize" disabled="disabled" value="20">
             <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-orderHistoryProductType-pages" disabled="disabled" value="999999">
             <input type="text" style="width: 100px;padding-top: 3px;" id="apis-quiet-div-orderHistoryProductType-keyword" placeholder="币对关键词">
             <select id="apis-quiet-div-orderHistoryProductType-sortField" style="height: 24px;">

+ 21 - 0
src/test/java/Test6.java

@@ -0,0 +1,21 @@
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+public class Test6 {
+    private  static final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(10);
+    public static void main(String[] args) {
+
+        scheduler.scheduleWithFixedDelay(() -> {
+            System.out.println("aa");
+            if (true){
+                return;
+            }
+            System.out.println("aaa");
+        }, 0, 2, TimeUnit.SECONDS);
+
+        scheduler.scheduleWithFixedDelay(() -> {
+            System.out.println("bb");
+        }, 0, 3, TimeUnit.SECONDS);
+    }
+}

+ 1 - 1
src/test/java/top/lvzhiqiang/Test6.java → src/test/java/top/lvzhiqiang/TestVideo.java

@@ -27,7 +27,7 @@ import java.util.*;
         "logging.level.top.lvzhiqiang=DEBUG"
 }
 )
-public class Test6 {
+public class TestVideo {
 
     @Resource
     private VideoInfoPoolMapper videoInfoPoolMapper;