亿级数据上传到ES数据库

157 阅读3分钟

1.什么是Elasticsearch(ES)

Elasticsearch(ES)是一个基于Apache Lucene的分布式搜索引擎,它主要用于全文搜索、日志分析、实时数据监控等场景。与传统的关系型数据库(RDBMS)不同,Elasticsearch采用了面向文档的数据模型,并且提供了高效的全文检索功能。在Elasticsearch中,理解其数据模型的构建、存储方式以及如何与数据交互,是掌握其使用的基础。

2.使用步骤

1.安装下载elasticsearch(ES数据库),www.elastic.co/downloads/e…

2.可以选择安装ES数据库的可视化工具,目的是可以可视化ES数据库的数据 www.elastic.co/cn/download…

3.打开elasticsearch(ES数据库),找到bin下面的elasticsearch.bat,双击即可启动

补充:首先先去创建你的索引,并且根据你的数据大小去设置主分片:主分片一般默认五个,每个主分片的存储数据最好在30g~50g之间,以下是创建索引和分配主分片的命令

PUT /phone_numbers
{
  "settings": {
    "number_of_shards": 50,  // 设置主分片数量为50
    "number_of_replicas": 1   // 可选:设置副本数为1(默认是1,可以根据需求调整)
  }
}

4.编写代码

1.下载 npm i @elastic/elasticsearch
2.下载 md5 npm i md5
const { Client } = require('@elastic/elasticsearch'); // 引入 Elasticsearch 客户端
const MD5 = require('md5'); // 引入 MD5 加密库

// Elasticsearch 客户端配置
const client = new Client({ node: 'http://localhost:9200' });

// 生成手机号范围的函数
function generatePhoneNumbers(start = 13000000000, end = 13099999999) {
  const phoneNumbers = [];
  for (let i = start; i <= end; i++) {
    phoneNumbers.push(i.toString()); // 将手机号转换为字符串
  }
  return phoneNumbers;
}

// 批量插入到 Elasticsearch 的函数
async function saveToElasticsearchInBatches(phoneNumbers, batchSize = 1000) {
  let failedNumbers = []; // 用于存储失败的手机号

  for (let i = 0; i < phoneNumbers.length; i += batchSize) {
    const batch = phoneNumbers.slice(i, i + batchSize); // 提取当前批次的手机号

    // 构建批量插入的请求体
    const body = batch.flatMap((phoneNumber) => [
      { index: { _index: 'phone_numbers' } },
      { 
        phone_number: phoneNumber, 
        encrypted_number: MD5(phoneNumber) // MD5 加密手机号
      },
    ]);
    console.log(body);
    
    try {
      // 执行批量插入请求
      const bulkResponse = await client.bulk({ body });
      console.log(bulkResponse);
      
      // 检查是否有错误,并记录失败的记录
      if (bulkResponse.items) {
        bulkResponse.items.forEach((item, index) => {
          if (item.index && item.index.error) {
            console.error(`Error in batch at index ${i + index}:`, item.index.error);
            failedNumbers.push({ phoneNumber: batch[index], error: item.index.error });
          }
        });
      }
      console.log(`Batch ${i / batchSize + 1} processed.`);
    } catch (error) {
      console.error('Error in bulk insert:', error);
    }
  }

  return failedNumbers; // 返回失败的手机号和错误信息
}

// 重新插入失败的数据,限制重试次数
async function retryFailedInserts(failedNumbers, batchSize = 1000, maxRetries = 3) {
  let retryCount = 0;
  let remainingFailed = [...failedNumbers];

  while (retryCount < maxRetries && remainingFailed.length > 0) {
    console.log(`Retrying failed inserts, attempt ${retryCount + 1}...`);
    const failedBatch = remainingFailed.splice(0, batchSize);
    
    const retryFailedNumbers = await saveToElasticsearchInBatches(failedBatch.map(f => f.phoneNumber), batchSize);
    
    if (retryFailedNumbers.length > 0) {
      remainingFailed = retryFailedNumbers.map(f => ({ phoneNumber: f, error: 'Unknown error' })); // 标记为失败的手机号
    } else {
      console.log('All failed records reinserted successfully.');
    }
    
    retryCount++;
  }

  // 如果重试次数超过限制,记录失败的手机号
  if (remainingFailed.length > 0) {
    console.error(`${remainingFailed.length} records failed after ${maxRetries} attempts.`);
    // 发送报警或记录失败手机号
    remainingFailed.forEach(f => {
      console.error(`Failed phone number: ${f.phoneNumber}, Error: ${f.error}`);
    });
  }
}

// 主程序
async function main() {
  try {
    const phoneNumbers = generatePhoneNumbers(); // 生成手机号列表
    console.log(`Generated ${phoneNumbers.length} phone numbers.`);

    // 分批插入到 Elasticsearch,每批 1000 个手机号
    const failedNumbers = await saveToElasticsearchInBatches(phoneNumbers, 1000);
    
    // 如果有失败的记录,重新插入
    if (failedNumbers.length > 0) {
      console.log(`${failedNumbers.length} failed records to retry.`);
      await retryFailedInserts(failedNumbers, 1000, 3); // 重新插入失败的记录,最大重试3次
    }
  } catch (error) {
    console.error('Error:', error);
  }
}

// 执行主程序
main();

5.编写代码之后发现连不上ES数据库

原因是因为新版本下的ES数据库默认开启的连接配置得是https 的,但是我们是http连接的,因为会报错连接不上

解决方法:找到es数据库config文件下面的elasticsearch.yml的配置文件,对代码进行修改

xpack.security.http.ssl:
  enabled: true
  keystore.path: certs/http.p12
把enabled由false改为true

3.使用可视化工具kibana

1.打开配置发现要用到一个token令牌,这个一开始执行连接ES数据库的时候会给到,如果给不到的话就重新生成

忘记命令了,到时候遇到了直接复制错误去查某度
但是记住一点,生成的时候先去到es数据库config文件下面的elasticsearch.yml的配置文件,对代码进行修改
xpack.security.enabled: false
xpack.security.enrollment.enabled: false
把这两个原本为true改为false才能给你授权生成新的token令牌

2.对于可视化工具怎么查看数据 找到Dev Tools 就可以输入命令了 常用的命令有

2.1.删除索引:DELETE /your_indexName

2.2.获取总数数据:# 使用scroll分批获取数据

POST /phone_numbers/_search?scroll=1m
        {
          "size": 10000,
          "query": {
            "match_all": {}
          },
          "sort": [
            {
              "phone_number.keyword": {
                "order": "asc"
              }
            }
          ]
        }

最后就大功告成啦~