编辑
2023-12-14
学习记录
00

前提

oracle中没有主键自增这个功能,需要使用数据库序列实现

创建序列

java
create sequence BACKSTAGE_LOG_ID_SEQ start with 1 --从1开始,不能小于最小值 maxvalue 9999999999999999999 --设置最大值 minvalue 0 --设置最小值 nocycle --一直累加,不循环 cache 5000 --缓存,表示一次产生5000个序号 noorder;
编辑
2023-12-12
实用工具
00

xxl介绍

XXL-JOB 是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。

设计思想 是将调度行为抽象形成 调度中心 平台,平台本身不承担业务逻辑,而是负责发起 调度请求 后,由 执行器 接收调度请求并执行 任务,这里的 任务 抽象为 分散的 JobHandler。通过这种方式即可实现 调度 与 任务 相互解耦,从而提高系统整体的稳定性和拓展性。 官方文档 官方git

简单使用

admin模块

克隆 git项目在本地

使用idea打开会发现三个模块

模块名称模块说明
xxl-job-admin调度中心,提供管理平台UI界面,真实开发场景中一般将其进行单独打包部署
xxl-job-core公共依赖模块,项目整合xxl-job时,需要导入该依赖
xxl-job-executor-samplesdemo案例

在mysql数据库中导入sql文件,在项目目录的doc/db路径下

表名说明
xxl_job_group保存执行器信息,新添加的执行器均在此表中保存
xxl_job_info用户保存任务信息,包括任务所属执行器,执行频次,过期策略等
xxl_job_lock任务调度锁
xxl_job_log保存调度结果、执行结果、调度入参、调度机器和执行器
xxl_job_log_report用于记录任务执行的成功次数,失败次数,一般以天为维度
xxl_job_logglue任务GLUE日志:用于保存GLUE更新历史,用于支持GLUE的版本回溯功能
xxl_job_registry执行器注册表,维护在线的执行器和调度中心机器地址信息
xxl_job_user系统用户表,用于登录admin控制台,使用MD5加密
编辑
2023-12-06
实用工具
00

Bean

BeanUtils

java
package com.ruoyi.common.utils.bean; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Bean 工具类 * * @author ruoyi */ public class BeanUtils extends org.springframework.beans.BeanUtils { /** Bean方法名中属性名开始的下标 */ private static final int BEAN_METHOD_PROP_INDEX = 3; /** * 匹配getter方法的正则表达式 */ private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)"); /** * 匹配setter方法的正则表达式 */ private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)"); /** * Bean属性复制工具方法。 * * @param dest 目标对象 * @param src 源对象 */ public static void copyBeanProp(Object dest, Object src) { try { copyProperties(src, dest); } catch (Exception e) { e.printStackTrace(); } } /** * 获取对象的setter方法。 * * @param obj 对象 * @return 对象的setter方法列表 */ public static List<Method> getSetterMethods(Object obj) { // setter方法列表 List<Method> setterMethods = new ArrayList<Method>(); // 获取所有方法 Method[] methods = obj.getClass().getMethods(); // 查找setter方法 for (Method method : methods) { Matcher m = SET_PATTERN.matcher(method.getName()); if (m.matches() && (method.getParameterTypes().length == 1)) { setterMethods.add(method); } } // 返回setter方法列表 return setterMethods; } /** * 获取对象的getter方法。 * * @param obj 对象 * @return 对象的getter方法列表 */ public static List<Method> getGetterMethods(Object obj) { // getter方法列表 List<Method> getterMethods = new ArrayList<Method>(); // 获取所有方法 Method[] methods = obj.getClass().getMethods(); // 查找getter方法 for (Method method : methods) { Matcher m = GET_PATTERN.matcher(method.getName()); if (m.matches() && (method.getParameterTypes().length == 0)) { getterMethods.add(method); } } // 返回getter方法列表 return getterMethods; } /** * 检查Bean方法名中的属性名是否相等。<br> * 如getName()和setName()属性名一样,getName()和setAge()属性名不一样。 * * @param m1 方法名1 * @param m2 方法名2 * @return 属性名一样返回true,否则返回false */ public static boolean isMethodPropEquals(String m1, String m2) { return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX)); } }
编辑
2023-12-06
学习记录
00

前提

AOP,全称是Aspect Oriented Programming,即面向切面编程。AOP的目的是将那些与业务无关,但是业务模块都需要的功能,如日志统计、安全控制、事务处理等,封装成可重用的组件,从而将它们从业务逻辑代码中划分出来,编写成独立的切面。这样做,既可以保持业务逻辑的纯净和高内聚性,又可以使得系统的多个模块都可以共享这些公共的功能。 Spring框架提供了对AOP的支持,Spring Boot自然也不例外。使用Spring Boot的AOP功能,我们可以在运行时动态地将代码横向切入到各个关注点(方法或者类)中。这种横向切面的方式,比传统的纵向切面(继承)更加灵活。

依赖

xml

java
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency>
编辑
2023-12-05
学习记录
00

前提

redis是我们经常使用的一个中间件,他是内存数据库,使用中经常会存一些list或者其他数据结构,内容很多的话,就会产生大key

导致问题

  1. 内存占用过高:大Key会占用大量的内存空间,可能导致可用内存不足,从而触发内存淘汰策略。在极端情况下,可能导致内存耗尽,Redis实例崩溃,影响系统的稳定性。
  2. 性能下降:大Key会占用大量内存空间,导致内存碎片增加,进而影响Redis的性能。对于大Key的操作,如读取、写入、删除等,都会消耗更多的CPU时间和内存资源,进一步降低系统性能。
  3. 阻塞其他操作:某些对大Key的操作可能会导致Redis实例阻塞。例如,使用DEL命令删除一个大Key时,可能会导致Redis实例在一段时间内无法响应其他客户端请求,从而影响系统的响应时间和吞吐量。
  4. 网络拥塞:每次获取大key产生的网络流量较大,可能造成机器或局域网的带宽被打满,同时波及其他服务。例如:一个大key占用空间是1MB,每秒访问1000次,就有1000MB的流量。
  5. 主从同步延迟:当Redis实例配置了主从同步时,大Key可能导致主从同步延迟。由于大Key占用较多内存,同步过程中需要传输大量数据,这会导致主从之间的网络传输延迟增加,进而影响数据一致性。
  6. 数据倾斜:在Redis集群模式中,某个数据分片的内存使用率远超其他数据分片,无法使数据分片的内存资源达到均衡。另外也可能造成Redis内存达到maxmemory参数定义的上限导致重要的key被逐出,甚至引发内存溢出。

解决方式

  1. 压缩 适用于字符串类型的 redis key。采用压缩算法,将 key 压缩至可接受的范围内。压缩也是有讲究的,首先要选择无损的压缩算法,然后在压缩速率和压缩率之间也要权衡。比较常用的压缩算法/工具如下:

google snappy:无损压缩,追求压缩速度而不是压缩率(Compression rate) message pack:无损压缩,仅适用于 json 字符串的压缩,可以得到一个更小的 JSON,官网是:msgpack.org

  1. 分割 适用于 list,set,hash 等容器类型的 redis key。规范要求容器的元素数量 < 5000,我们可以在写 redis 的时候做个逻辑,如果超过了 5000 的容器就做切片。

  2. 抛弃 redis不存储过大的,可以直接查询数据库,或者是将不太重要的数据存储再Mongodb中,直接从mongodb查询