Skip to content

2024年4月随笔

JPS命令的使用

jps(Java Virtual Machine Process Status Tool)是JDK提供的一个可以列出正在运行的Java虚拟机的进程信息的命令行工具,它可以显示Java虚拟机进程的执行主类(Main Class,main()函数所在的类)名称、本地虚拟机唯一ID(LVMID,Local Virtual Machine Identifier)等信息。另外,jps命令只能显示它有访问权限的Java进程的信息。

1.1. 常用的JPS命令

options 参数选项作用
-q只输出进程 ID,省略主类的名称
-m输出虚拟机进程启动时传递给主类 main() 方法的参数
-l输出主类的名称,如果进程执行的是 JAR 包,则输出 JAR 文件的路径
-v输出虚拟机进程启动时的 JVM 参数

数据库同步的几种方式

数据库同步是确保多个数据库之间数据一致性的关键过程。以下是一些常见的数据库同步方法:

主从同步:

  • 主从同步是数据库同步的一种常见方式。在这种模式下,一个数据库(主数据库)负责处理所有写入操作,并将这些操作同步到一个或多个从数据库。从数据库通常用于读取操作,以减轻主数据库的负载。
  • 实现主从同步时,需要选择合适的同步方案,如基于二进制日志的同步、基于GTID的同步或基于复制拓扑结构的同步等。
  • 配置主从数据库服务器是关键一步,包括在主数据库上开启二进制日志、配置复制用户,以及在从数据库上配置主从复制连接等。
  • 主从同步完成后,还需要定期监控和维护同步状态,确保数据的完整性和安全性。

双主同步:

  • 双主同步是一种在多个数据库之间进行双向同步的方法。每个数据库都可以接收写入操作,并将这些操作同步到其他数据库。
  • 这种同步方式需要解决数据冲突和一致性问题,确保在多个数据库之间同步数据时不会发生冲突或数据不一致的情况。

分布式同步:

  • 分布式同步是在分布式系统中进行数据库同步的方法。分布式系统由多个数据库节点组成,每个节点存储部分数据并独立进行写入操作。
  • 为了保持数据的一致性,需要在节点之间进行数据同步。这通常涉及到复杂的通信和协调机制,以确保数据在所有节点之间保持一致。
  • 分布式同步可以提高系统的可伸缩性和容错性,但也增加了数据同步的一致性和性能问题的复杂性。

日志复制同步:

  • 数据库会生成写入操作的日志文件,包含所有对数据的修改。通过复制这些日志文件,并在其他数据库上重放这些操作,可以实现数据的同步。
  • 这种方法可以确保数据的完整性和一致性,但需要处理日志文件的管理、传输和重放过程中的潜在问题。

基于时间戳的同步:

  • 每个数据库节点维护一个全局时间戳,用于标记每个操作的时间。基于时间戳的同步可以确保数据按照正确的顺序进行同步,从而提供较高的数据一致性。
  • 然而,这种方法可能受到时钟偏差和网络延迟的影响,需要额外的机制来确保时间戳的准确性。

除了上述方法外,还有一些数据库同步工具可以帮助实现数据库同步,如Flyway、Liquibase和SymmetricDS等。这些工具提供了自动化和可视化的同步功能,简化了数据库同步的过程。 在选择合适的数据库同步方法时,需要根据具体的业务需求、系统架构和数据一致性要求进行综合考虑。同时,还需要注意同步过程中的性能问题、数据冲突解决以及数据备份和恢复等方面的挑战。

Mybatis-Plus中使用动态SQL构建IN查询语句

UserMapper.xml

xml
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
<mapper namespace="com.example.mapper.UserMapper">  
  
    <!-- 自定义查询,使用IN语句 -->  
    <select id="selectUsersByIds" resultType="com.example.model.User">  
        SELECT * FROM user  
        WHERE id IN   
        <foreach item="id" index="index" collection="ids" open="(" separator="," close=")">  
            #{id}  
        </foreach>  
    </select>  

    <select id="selectUsersByNames" resultType="com.example.model.User">  
        SELECT * FROM user  
        <where>  
            <!-- 可以通过if语句判断值是否存在 -->
            <if test="names != null and names.size() > 0">  
                AND name IN   
                <foreach item="name" index="index" collection="names" open="(" separator="," close=")">  
                    #{name}  
                </foreach>  
            </if>  
        </where>  
    </select>

</mapper>

UserService接口中定义方法 UserService.java

java
package com.example.mapper;  
  
import com.example.model.User;  
import java.util.List;  
  
public interface UserMapper extends BaseMapper<User> {  
    // 自定义方法,与XML中的select元素的id对应  
    List<User> selectUsersByIds(List<Integer> ids);  
}

如何使用:

java
@Service  
public class UserService {  
    @Autowired  
    private UserMapper userMapper;  
  
    public List<User> findUsersByIds(List<Integer> ids) {  
        return userMapper.selectUsersByIds(ids);  
    }  
}

java中的.builder()方法实现详解

转载地址:https://www.cnblogs.com/moonz-wu/archive/2011/01/11/1932473.html

在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成。那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Builder模式来替代多参数构造函数是一个比较好的实践法则。

我们常常会面临编写一个这样的实现类(假设类名叫DoDoContact),这个类拥有多个构造函数,

DoDoContact(String name);

DoDoContact(String name, int age);

DoDoContact(String name, int age, String address);

DoDoContact(String name, int age, String address, int cardID);

这样一系列的构造函数主要目的就是为了提供更多的客户调用选择,以处理不同的构造请求。这种方法很常见,也很有效力,但是它的缺点也很多。类的作者不得不书写多种参数组合的构造函数,而且其中还需要设置默认参数值,这是一个需要细心而又枯燥的工作。其次,这样的构造函数灵活性也不高,而且在调用时你不得不提供一些没有意义的参数值,例如,DoDoContact("Ace", -1, "SH"),显然年龄为负数没有意义,但是你又不的不这样做,得以符合Java的规范。如果这样的代码发布后,后面的维护者就会很头痛,因为他根本不知道这个-1是什么含义。对于这样的情况,就非常适合使用Builder模式。Builder模式的要点就是通过一个代理来完成对象的构建过程。这个代理职责就是完成构建的各个步骤,同时它也是易扩展的。下面是改写自Effective Java里面的一段代码:

java
public class DoDoContact {
    private final int    age;
    private final int    safeID;
    private final String name;
    private final String address;
 
    public int getAge() {
        return age;
    }
 
    public int getSafeID() {
        return safeID;
    }
 
    public String getName() {
        return name;
    }
 
    public String getAddress() {
        return address;
    }
 
    public static class Builder {
        private int    age     = 0;
        private int    safeID  = 0;
        private String name    = null;
        private String address = null;
   // 构建的步骤
        public Builder(String name) {
            this.name = name;
        }
 
        public Builder age(int val) {
            age = val;
            return this;
        }
 
        public Builder safeID(int val) {
            safeID = val;
            return this;
        }
 
        public Builder address(String val) {
            address = val;
            return this;
        }
 
        public DoDoContact build() { // 构建,返回一个新对象
            return new DoDoContact(this);
        }
    }
 
    private DoDoContact(Builder b) {
        age = b.age;
        safeID = b.safeID;
        name = b.name;
        address = b.address;
 
    }
}

调用方式

java
DoDoContact ddc = new DoDoContact.Builder("Ace").age(10)
                .address("beijing").build();
System.out.println("name=" + ddc.getName() + "age =" + ddc.getAge()
                + "address" + ddc.getAddress());

可以使用lombok进行优化,可以使用@Builder注解实现同样的效果

java
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;


@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
    private int code;
    private String message;
    private T data;
}
java
Result<String> result5 = Result.<String>builder().code(404).message("failure").build();

数据库全量更新和增量更新

全量更新和增量更新各有其优缺点,具体如下:

全量更新的优点:

  1. 数据一致性高:全量更新会替换整个软件包或模块,确保所有数据和功能都是最新的,从而保持数据的一致性。
  2. 简单直接:全量更新不需要复杂的规则和策略,直接替换整个软件包或模块即可,操作简单直接。
  3. 适用于大规模更新:当需要替换整个软件包或模块时,全量更新是一种高效的方法,可以一次性完成所有更新内容。

全量更新的缺点:

  1. 更新速度慢:全量更新需要下载完整的安装包,并进行覆盖安装,因此更新速度相对较慢,且会占用更多的带宽和存储空间。
  2. 更新成本高:对于大规模的软件或系统来说,全量更新需要更多的资源来支持,包括服务器带宽、存储空间等,从而增加了更新成本。
  3. 对系统稳定性有影响:全量更新可能会涉及到系统的核心组件或功能,如果更新过程中出现错误或问题,可能会对系统的稳定性造成影响。

增量更新的优点:

  1. 更新速度快:增量更新只更新发生变化的数据,因此更新速度相对较快,可以节省用户的时间和流量。
  2. 更新成本低:由于只需要下载有变动的部分,因此增量更新可以减少对服务器带宽和存储空间的需求,从而降低更新成本。
  3. 灵活性高:增量更新可以根据需要选择不同的更新内容,灵活满足用户的不同需求。

增量更新的缺点:

  1. 数据一致性风险:增量更新可能会引入数据的不一致性,特别是在数据变更频繁的场景中。如果更新过程中出现问题或错误,可能会导致数据的不一致或丢失。
  2. 复杂度高:增量更新需要建立有效的数据追踪机制,以确定哪些数据已经发生了变化。此外,还需要对数据的变化进行适当的协调和整合,以确保数据的完整性和准确性。这些操作增加了增量更新的复杂度和难度。
  3. 依赖旧版本:增量更新通常需要依赖旧版本的数据或文件,如果旧版本的数据或文件损坏或丢失,可能会导致增量更新失败。

上次更新于: