120W数据再两文件夹内对比

本文介绍了一种方法,用于找出两个Elasticsearch索引之间的数据差异。通过将大量数据分批读取并进行逐个对比,最终输出两索引间的数据差集。

情景:

两个ES索引在导入时候出现数据偏差,需要找差集。

思路

由于索引是共用,并且是动态,无法对比数据。
索引字段超多,先分页将数据保留本地再分析。只保留ID,格式为:List 并且以升序排列,不排序也可以。
由于LIST一次运行超过100W数据会超慢,顾分解为5W一个LIST去做对比,结果保留到RESULT LIST内。最后输出。
ES --> search data by id order by asc --> save local data 5w/file --> file compare file --> save diff
测试为两个文件夹,总有22个文件,每5万一个文件,总数据量约为120W,用时大概3分钟。

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author andy 
 * @version $Revision: 1.1 $ $Date: 2020年11月18日 下午4:09:15 $
 */
public class LoadFile2 {
    public static void main(String[] args) throws Exception {
        System.out.println("准备处理。。。");
        String fixPath = "E:/Desktop/es/run/3/";
        long c = System.currentTimeMillis();
        
        // 处理第一个文件夹内所有txt文件名
        List<String> newPath = new ArrayList<>();
        System.out.println("开始统计文件数new");
        getFile(new File(fixPath + "new"), newPath);
        System.out.println("统计文件数 new: " + newPath.size());

        // 处理第二个文件夹内所有txt文件名
        System.out.println("开始统计文件数backup");
        List<String> backPath = new ArrayList<>();
        getFile(new File(fixPath + "backup"), backPath);
        System.out.println("统计文件数 backup: " + backPath.size());

        // 过滤数据
        System.out.println("过滤数据");
        List<String> resultList = filterData(newPath, backPath);
        System.out.println("cost: " + (System.currentTimeMillis() - c));
        resultList.stream().forEach(System.out::println);
        
        System.out.println("保留数据");
        FileWriter fw = new FileWriter(fixPath + "result.txt");
        if (!resultList.isEmpty()) {
            resultList.stream().forEach(x -> {
                try {
                    fw.append(x + "\n");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
        fw.flush();
        fw.close();
        System.out.println("处理完成");
        
    }

    /**
     * @param resultList
     * @param backFbr
     * @param newFbr
     * @throws Exception 
     */
    private static List<String> filterData(List<String> newPath, List<String> backPath) throws Exception {
        if (newPath.size() > backPath.size()) return removeData(newPath, backPath); 
        if (backPath.size() > newPath.size()) return removeData(backPath, newPath);
        return removeData(newPath, backPath);
    }

    /**
     * @param newFbr
     * @param backFbr
     * @return
     * @throws Exception 
     */
    private static List<String> removeData(List<String> bigPath, List<String> smallPath) throws Exception {
        List<String> temp = new ArrayList<>();
        List<String> resultList = new ArrayList<>();
        List<String> firstData = new ArrayList<>();
        List<String> secondData = new ArrayList<>();
        for (int i = 0; i < bigPath.size(); i++) {
            txt2List(bigPath.get(i), firstData);
            if ( i >= smallPath.size()) {
                firstData.removeAll(resultList);
                resultList.addAll(firstData);
                firstData.clear();
                System.out.println("resultListSize: " + resultList.size());
                continue;
            }
            txt2List(smallPath.get(i), secondData);
            System.out.println("file compare: " + bigPath.get(i) + " - " + smallPath.get(i));
            temp.addAll(firstData);
            firstData.removeAll(secondData);
            secondData.removeAll(temp);
            firstData.addAll(secondData);
            
            temp.clear();
            temp.addAll(resultList);
            resultList.removeAll(firstData);
            firstData.removeAll(temp);
            
            resultList.addAll(firstData);
            firstData.clear();
            secondData.clear();
            temp.clear();
            System.out.println("resultListSize: " + resultList.size());
        }
        return resultList;
    }


    public static void txt2List(String path, List<String> list) throws Exception {
        String s = "";
        BufferedReader br = null;
        // 读取txt内容 并转换成List
        br = new BufferedReader(new FileReader(path));// 构造一个BufferedReader类来读取文件
        try {
            while ((s = br.readLine()) != null) {// 使用readLine方法,一次读一行
                list.add(s);
            }
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    // 读取文件夹下所有文件名
    public static void getFile(File file, List<String> listLocal) {

        if (file != null) {
            File[] f = file.listFiles();
            if (f != null) {
                for (int i = 0; i < f.length; i++) {
                    getFile(f[i], listLocal);
                }
            } else {
                listLocal.add(file.getPath());
            }
        }

    }

}
<think> 嗯,用户想要了解如何将项目文件夹挂载到Docker容器内的方法,这个问题之前讨论过,但用户可能需要更清晰的指导。用户可能是个开发者,正在搭建本地开发环境,希望实现代码修改后容器内实时更新的效果。从引用内容看,用户已经接触过三种挂载方式(直接挂载、nsenter操作、volume挂载),但需要整合性解答。 用户提供的三个引用其实展示了不同维度的解决方案:引用[1]是基础命令行操作,引用[2]涉及运行时容器权限突破,引用[3]则是官方推荐的volume方案。不过用户的核心诉求很明确——项目文件夹挂载,重点应该落在开发场景而非生产环境优化。 注意到用户特别强调“项目文件夹”,这意味着需要持久化且双向同步的代码目录。因此绑定挂载(-v参数)显然最符合需求,因为:1)直接映射主机路径 2)支持文件修改实时同步 3)避免volume的数据隔离性(不利于代码调试)。引用[1]的示例恰好完整展示了这个流程,包括工作目录设置和依赖安装环节。 需要提醒权限问题:如果容器内进程以root运行,挂载后生成的文件可能导致主机权限混乱。应该在回答中补充——node:12-alpine镜像默认是node用户,但其他镜像可能需要显式添加用户映射。另外用户可能混淆了docker run和docker create的区别,需强调挂载必须在容器创建时设定。 考虑到用户尝试过复杂方案(如nsenter),说明可能遇到权限障碍。可以补充说明:如果必须修改运行中容器的挂载点,更安全的做法是commit为新镜像再启动,而非强行突破容器隔离。 </think> 以下是将项目文件夹挂载到 Docker 容器内的详细方法及注意事项,参考官方最佳实践整理: ### 📂 核心方法(绑定挂载) ```bash # 基础命令结构 docker run -itd --name 容器名 \ -v "$(pwd)/本地项目路径:容器内目标路径" \ [其他参数] \ 镜像名 [启动命令] # 实际示例(Node.js 项目) docker run -dp 3000:3000 \ -w /app \ # 设置容器内工作目录 -v "$(pwd):/app" \ # 关键挂载指令 node:18-alpine \ sh -c "yarn install && yarn dev" ``` **参数说明**: 1. `-v "$(pwd):/app"` - `$(pwd)`:自动获取当前主机工作目录 - `/app`:容器内的挂载目标路径 - **双向同步**:主机文件修改实时反映到容器内,容器内改动也会同步到主机(需注意权限) 2. `-w /app` 设定容器启动后的工作目录,确保命令在项目路径执行 ### ️ 关键注意事项 1. **权限问题**(常见错误) ```bash # 解决方案:添加用户映射参数 docker run -itd \ -v "$(pwd):/app" \ --user "$(id -u):$(id -g)" \ # 使用当前主机用户UID/GID node:18-alpine ``` 2. **路径特殊字符处理** 若路径含空格或特殊字符,需用引号包裹: ```bash -v "/home/user/My Project:/app" ``` 3. **只读挂载需求**(安全场景) ```bash -v "$(pwd):/app:ro" # 添加:ro后缀限制容器只读 ``` ### 🔧 替代方案对比 | **方法** | 命令示例 | 适用场景 | 缺点 | |------------------|----------------------------------|----------------------------|----------------------| | **绑定挂载** | `-v /host/path:/container/path` | 开发环境(代码实时同步) | 依赖主机目录结构 | | **命名卷** | `-v volume_name:/container_path` | 生产环境(数据库等持久化数据)| 需额外管理volume | | **临时文件系统** | `--tmpfs /container_path` | 敏感临时数据 | 容器停止后数据丢失 | ### 💻 调试技巧 1. **验证挂载结果**: ```bash docker exec -it 容器名 ls /app # 查看容器内挂载内容 ``` 2. **文件权限检查**: ```bash docker exec -it 容器名 stat -c "%U %G" /app/文件 ``` > **开发场景强烈推荐绑定挂载**:修改主机代码即可触发容器内服务热更新(如React/Vue/Nodemon),无需重建镜像[^1]。生产环境建议改用命名卷或构建正式镜像[^3]。 --- ### ❓ 相关问题 1. Docker挂载后容器内文件权限错误如何修复? 2. 如何在Kubernetes中实现类似本地目录挂载? 3. Docker Volume 与 Bind Mount 的核心区别是什么? 4. 容器内修改挂载目录文件导致主机权限混乱怎么办? > 引用说明 > [^1]: 绑定挂载实现开发环境实时同步 > [^3]: 命名卷与绑定挂载的适用场景对比
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值