Guitar 🎸

指板

chords
在乐音体系中,七个具有独立名称的音级叫做基本音级(也叫自然音级)。 基本音级用“C、D、E、F、G、A、B”七个字母来表示,这就是基本音级的音名唱名是人们在演唱音乐的谱子时所使用的名称,即:“Do,Re,Mi,Fa,Sol,La,Si” 这七个唱名。
简谱上 唱名、音名的表示
十二平均律,是将一个八度的音程等分成十二个半音的律制,各相邻两律之间的波长之比完全相等。一等份为一个半音(小二度),对应吉他一品的距离。两等份为一个全音(大二度)。将一个八度分成12等份有着惊人的一些巧合,这是因为它的纯五度音程的两个音的波长比为(1/2)^(7/12)≈0.6674,与2/3≈0.6667非常接近。 一个八度内 全全半全全全半

C大调音阶在吉他指板上可以有不同的把位 https://www.zhihu.com/tardis/zm/art/496745355?source_id=1005
C大调音阶图

扫弦节奏型:1)下 下 下上 上下上下 下上
节拍

乐理

HUB GUITAR: https://hubguitar.com/zh_han/music-theory 指板: https://hubguitar.com/zh_han/fretboard

弹奏第一品位上的B弦,这就是 C音,一个以一定频率振动的音波。接下来你拨第十三品的同一根弦,同样地,它听上去好像是同一个音,但这个音高更高。这是因为声波的振动是原来的两倍之快,可以表达为1:2, 它们是有同一特性的音。如果两种不同的乐器同时弹奏C音,这个比例是1:1,这称为 同音。在下图中,第一品的音符将会是最左边的C,第十三品的音则是在最右边。所有在这两者之间的音符都是特定的音符,但一旦重新回到C音,就重新按照这个顺序继续下去。

音程:就是两个音符之间的高低关系。在较低的一个 “C” 音和另一个较高的 “C” 音之间的音程就是 八度(八音音阶)。八度是音高的基本来源,其余的还包括将它分成更小的部分而得到的音高,称为 音数。半音就是移动一格,从 C 到 C♯。全音移动两格,从 C 到 D。 大多数现代音乐将八度分割为12级,如图所示,你可以按照这个音符的顺序来弹奏,从第一品的 B 弦开始,每次移动一个品位,直到第十三品,重新回到 C,一边弹奏一边大声说出这个音符的名字。所有这十二个音符一起组成了 半音音阶。音阶就是音符的顺序,并且没有重复的音符,所有的音符以升序,从低到高的顺序来弹奏。

根音?它就是一首歌的主调音,它是一个单音,其余的东西全在它的基础上变化,想像它是重力中心,它是一种吸引力,吸引着一首歌曲里其余所有的音,不管什么情况下都会回到根音上来。

TABS


晴天 - 周杰倫

Hey Jude - The Beatles

小情歌 - 蘇打綠 https://www.bilibili.com/video/BV1R64y1p7WB/

紅豆 - 方大同

找自己 - 陶喆

普通朋友 - 陶喆 https://www.bilibili.com/video/BV1zw4m1a7CU

Canon in C https://www.bilibili.com/video/BV1if4y1A7SZ/

揪心的玩笑與漫長的白日夢 - 萬能青年旅店
https://www.bilibili.com/video/BV1cuHjetENY/?vd_source=ff210768dfaee27c0d74f9c8c50d7274

Milvus

📚 文档链接: 快速入门 | Milvus 文档

什么是向量嵌入?

向量嵌入是从机器学习模型中提取的数值表示,捕捉非结构化数据的语义含义。这些嵌入通过神经网络或变压器架构对数据中的复杂相关性进行分析,创建一个密集的向量空间,其中每个点对应于数据对象(如文档中的词)的“含义”。

这个过程将文本或其他非结构化数据转换为反映语义相似性的向量——在这个多维空间中,意义相关的词被放置得更近,从而实现一种称为“密集向量搜索”的搜索方式。这与依赖精确匹配和使用稀疏向量的传统关键词搜索形成对比。向量嵌入的发展,通常源于大型科技公司广泛训练的基础模型,使得搜索能够捕捉数据的本质,超越词汇或稀疏向量搜索方法的局限性。

向量:可以理解为在多维空间中的一个点,它由一组数字(坐标)表示。在 AI 中,无论是文本、图像还是声音,都可以通过特定的模型(如 qwen3-embedding-4b-torch)转换为一个向量。这个向量捕捉了原始数据的深层特征。
维度:就是指这个向量有多少个数字。例如,一个 [0.12, 0.45, -0.23, …, 0.78]的向量,如果它有 1024 个数字,我们就说它是一个 1024 维​ 的向量。维度的选择通常由您选用的嵌入模型决定,并且在创建 Milvus 集合时必须正确定义,因为所有存入的向量都必须有相同的维度。

非结构化数据、Embeddings 和 Milvus

非结构化数据(如文本、图像和音频)格式各异,蕴含丰富的潜在语义,因此分析起来极具挑战性。Embeddings 被用来将非结构化数据转换成能够捕捉其基本特征的数字向量。然后将这些向量存储在向量数据库中,从而实现快速、可扩展的搜索和分析。

Milvus 提供强大的数据建模功能,使您能够将非结构化或多模式数据组织成结构化的 Collections。它支持多种数据类型,适用于不同的属性模型,包括常见的数字和字符类型、各种向量类型、数组、集合和 JSON,为您节省了维护多个数据库系统的精力。
与处理结构化数据并执行精确搜索操作的传统关系数据库不同,向量数据库擅长使用 Approximate Nearest Neighbor(ANN)算法等技术进行语义相似性搜索。这种能力对于开发推荐系统、聊天机器人和多媒体内容搜索工具等各种领域的应用程序,以及解决 ChatGPT 等大型语言模型和 AI 带来的挑战(如理解上下文和细微差别以及 AI 幻觉)至关重要。

Milvus 概念 类比关系型数据库概念 说明
Collection(集合) Table(表) 存储向量和关联元数据(如文本内容、来源)的基本单位。
Entity(实体) Row(行) 一条完整的记录,包含主键、向量字段和标量字段(元数据)。
Field(字段) Column(列) 包括向量字段(存储向量)和标量字段(存储 ID、标签等结构化数据)。
Index(索引) Index(索引) 为向量字段建立的索引(如 HNSW、IVF_FLAT),是高速检索的关键。
  1. 写入数据(以 Python 为例)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType

    # 1. 连接到您的 Milvus 服务
    connections.connect("default", host='localhost', port='19530')

    # 2. 定义集合结构(假设向量维度为1024)
    fields = [
    FieldSchema(name="id", dtype=DataType.VARCHAR, is_primary=True, max_length=100),
    FieldSchema(name="text_content", dtype=DataType.VARCHAR, max_length=65535),
    FieldSchema(name="embedding_vector", dtype=DataType.FLOAT_VECTOR, dim=1024)
    ]
    schema = CollectionSchema(fields, description="问答助手知识库")
    collection = Collection("qa_knowledge_base", schema)

    # 3. 插入数据(假设您已使用 embedding 模型将文本转换为向量)
    data = [
    ["doc_001", "CMDB是配置管理数据库,用于...", [0.12, 0.34, ...]], # 1024维向量
    ["doc_002", "MongoDB的聚合管道用于...", [0.56, 0.78, ...]],
    ]
    collection.insert(data)
    collection.flush() # 确保数据持久化

    # 4. 创建索引(以HNSW为例)
    index_params = {
    "index_type": "HNSW",
    "metric_type": "COSINE", # 使用余弦相似度
    "params": {"M": 16, "efConstruction": 200}
    }
    collection.create_index("embedding_vector", index_params)
    collection.load() # 将集合加载到内存以提供服务
  2. 读取与搜索

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # 用户提出问题,并转换为向量
    question = "如何查询CMDB中的主机信息?"
    question_vector = embed(question) # 使用相同的模型生成1024维向量

    # 在 Milvus 中搜索最相似的 Top K 个向量
    search_params = {"metric_type": "COSINE", "params": {"ef": 50}}
    results = collection.search(
    data=[question_vector],
    anns_field="embedding_vector",
    param=search_params,
    limit=3, # 返回最相似的3条结果
    output_fields=["id", "text_content"] # 指定需要返回的元数据字段
    )

    # 处理结果
    for hits in results:
    for hit in hits:
    print(f"相似度得分: {hit.score}, 关联知识: {hit.entity.get('text_content')}")
  3. Milvus 支持的搜索类型
    ANN 搜索:查找最接近查询向量的前 K 个向量。
    过滤搜索:在指定的过滤条件下执行 ANN 搜索。
    范围搜索:查找查询向量指定半径范围内的向量。
    混合搜索:基于多个向量场进行 ANN 搜索。
    全文搜索:基于 BM25 的全文搜索。
    Rerankers:根据附加标准或辅助算法调整搜索结果顺序,完善初始 ANN 搜索结果。
    获取:根据主键检索数据。
    查询使用特定表达式检索数据。

Milvus 在 RAG

在 RAG 流程中,Milvus 扮演着 知识库与高速检索引擎 的角色。

  1. 检索(Retrieval):当用户提问时,系统首先使用嵌入模型将问题转换为查询向量。随后,Milvus 在该查询向量与知识库中所有文档向量之间进行高速的相似性比较,找出最相关的几个知识片段。
  2. 增强(Augmentation):将这些检索到的知识片段(元数据中的原始文本)作为上下文,与用户的问题一起组合成一个更丰富的提示词(Prompt)。
  3. 生成(Generation):将这个富含上下文的提示词发送给您的大语言模型(如 qwen3-235b-a22b),由它来生成精准、有据可依的最终答案。

什么是 Agentic RAG?基础的 RAG 中,检索-增强-生成是一次性完成的。而 Agentic RAG(智能体驱动的 RAG) 则引入了“智能体”的概念,使得检索过程变得更智能、更动态。
智能体可以根据对大模型初步生成内容的理解,主动地、多次地 与向量数据库(Milvus)进行交互。这使 RAG 系统从静态的“文档查找”升级为动态的、具有决策能力的“研究助手”。例如:

  • 判断是否需要进一步检索:如果首次检索到的信息不足以回答问题,智能体可以重新生成搜索 query,进行多轮检索,直到信息足够。
  • 分解复杂问题:对于复杂问题,智能体可以将其拆解成多个子问题,然后针对每个子问题去 Milvus 中检索相关信息,最后综合所有信息生成答案。
  • 工具调用(Tool Use):智能体可以将 Milvus 的检索功能视为一个可调用的工具,根据对话进程决定何时以及如何调用这个工具。

人工智能集成

  1. Embeddings 模型集成 Embedding 模型将非结构化数据转换为其在高维数据空间中的数字表示,以便您可以将其存储在 Milvus 中。目前,PyMilvus(Python SDK)集成了多个嵌入模型,因此您可以快速将数据准备成向量嵌入。有关详情,请参阅嵌入概述。
  2. Reranker 模型集成 在信息检索和生成式人工智能领域,Reranker 是优化初始搜索结果顺序的重要工具。PyMilvus 也集成了几种 Rerankers 模型,以优化初始搜索返回结果的顺序。详情请参考Rerankers 概述。
  3. LangChain 和其他人工智能工具集成 在 GenAI 时代,LangChain 等工具受到了应用程序开发人员的广泛关注。作为核心组件,Milvus 通常在此类工具中充当向量存储。要了解如何将 Milvus 集成到您喜爱的人工智能工具中,请参阅我们的集成和教程。

Agent

AI Agent的本质是能够感知环境、自主决策并执行行动的智能实体。与传统AI系统最大的区别在于Agent具有自主性、反应性、目标导向和学习能力,它不再是简单的工具,而是能够主动规划和完成复杂任务的智能体。从1997年击败国际象棋世界冠军的IBM“深蓝”,到2011年苹果推出的个人助理Siri,都展示了Agent在特定领域的强大能力,关键的转折点发生在2023年左右,大语言模型LLM的出现为Agent提供了强大的通用理解和推理能力,使其不再局限于单一任务。

Agent 架构模式

  1. 组成组件
    Agent:智能代理,它是一个能够感知环境、做出决策并执行动作的软件实体(比起LLM只能“回答问题”,Agent可以真正地“执行任务”)。在LLM语境中,Agent通常利用LLM作为大脑,来理解用户输入、决定需要执行的动作(比如调用工具)、处理工具返回的结果并生成响应。
    LLM(大语言模型):如GPT系列,是Agent的核心,负责理解自然语言、进行推理和生成文本。
    Tool:工具,是Agent可以调用的函数,用于执行特定任务,比如查询数据库、调用API。Tool扩展了Agent的能力,使其能够获取实时信息或执行具体操作。
    Function Calling:函数调用,是LLM的一种能力,允许模型根据用户输入决定何时以及如何调用哪个函数(Tool),并以结构化格式(如JSON)输出函数调用参数。然后由外部系统执行该函数。
    Prompt:提示词,是引导LLM生成期望输出的文本。在Agent中,Prompt通常包含系统指令(定义Agent的角色和能力)、用户输入、对话历史以及工具描述等。
    RAG(检索增强生成):通过从外部知识库检索相关信息,并将其作为上下文提供给LLM,从而生成更准确、更相关的回答。
    MCP(模型上下文协议):MCP可以包含本地tools和外部API,但通常 MCP更强调于将工具(无论是本地tools还是外部API)以标准化的上下文协议暴露给AI模型。MCP可以看作是一个中间层,它将工具抽象成标准的接口,使得AI Agent可以通过统一的协议来调用这些工具,从而实现模型与工具之间的解耦。
  2. 一个典型的工作流程如下:
    用户输入自然语言请求。
    Agent将用户输入、对话历史、可用的工具描述(通过Function Calling定义)以及系统提示词组合成一个Prompt,发送给LLM。
    LLM根据Prompt判断是否需要调用工具。如果需要,LLM会返回一个函数调用请求(包括函数名和参数)。
    Agent解析LLM返回的函数调用请求,并执行对应的工具(Tool)。
    工具执行后返回结果,Agent将工具执行结果作为上下文,再次调用LLM,生成最终的自然语言响应。
    Agent将响应返回给用户。
    在这个过程中,RAG可以在第一步之前或之中介入,通过检索外部知识库来增强Prompt的上下文。
  3. a demo
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #### main.py
    from pydantic_ai.models.gemini import GeminiModel
    from pydantic_ai import Agent
    from dotenv import load_dotenv
    import tools

    # 模型API Key等可以写到.env文件 并加载到环境变量
    load_dotenv()
    model = GeminiModel("gemini-2.5-flash-preview-04-17")

    # 将llm模型、系统prompt、工具tools “注册” 到 Agent
    agent = Agent(model,
    system_prompt="You are an experienced programmer",
    tools=[tools.read_file, tools.list_files])

    def main():
    history = []
    while True:
    # eg. Input: list and read file. base on your konwledge tell me what lang each file use.
    user_input = input("Input: ")
    # 将用户输入、历史对话(上下文)发给 agent 并记录本次对话(短期记忆)
    resp = agent.run_sync(user_input,
    message_history=history)
    history = list(resp.all_messages())
    print(resp.output)

    if __name__ == "__main__":
    main()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #### tools.py
    from pathlib import Path
    import os

    base_dir = Path("./test")

    def read_file(name: str) -> str:
    # docstring 帮助模型理解 tools
    """Return file content. If not exist, return error message.
    """
    print(f"(read_file {name})")
    try:
    with open(base_dir / name, "r") as f:
    content = f.read()
    return content
    except Exception as e:
    return f"An error occurred: {e}"

    def list_files() -> list[str]:
    print("(list_file)")
    file_list = []
    for item in base_dir.rglob("*"):
    if item.is_file():
    file_list.append(str(item.relative_to(base_dir)))
    return file_list

MCP

MCP 可以看作是一个中间层,它将工具抽象成标准的接口,使得AI Agent可以通过统一的协议来调用这些工具,从而实现模型与工具之间的解耦。MCP 可以包含本地tools和外部API,但通常 MCP更强调于将工具(无论是本地tools还是外部API)以标准化的上下文协议暴露给AI模型。

  1. Agent通过集成的MCP Client向MCP Server发送请求,调用工具。因此,Agent不再直接调用具体的工具函数,而是可以使用任何符合MCP协议的工具,无论工具是本地还是远程。MCP模式下,我们不再直接注册这些Tools到Agent(如传统框架LangChain),而是注册MCP Client(可以看作是Tools的抽象层),然后Agent通过MCP Client来动态获取MCP Server提供的Tools列表,并在需要时调用它们。
    示例流程:
    步骤1:启动一个MCP Server,它提供了一些工具(例如,天气查询、计算器等)。
    步骤2:在Agent框架中,配置MCP Client,并连接到该MCP Server。
    步骤3:Agent在需要时,通过MCP Client查询MCP Server提供了哪些工具。
    步骤4:当用户提问时,Agent决定调用哪个工具,然后通过MCP Client发送调用请求给MCP Server。
    步骤5:MCP Server执行工具,并将结果返回给MCP Client,然后Agent接收结果并生成最终回答。?
  2. MCP代表了AI应用架构的演进方向,从紧耦合的工具注册转向松耦合的工具治理,特别适合企业级AI应用的复杂集成场景。

RAG

RAG​ 的核心思想是:在让大模型回答问题之前,先从一个外部的、可随时更新的知识库中检索相关信息,然后将这些“新鲜”信息作为上下文和问题一起交给模型,从而引导模型生成更准确、及时且可追溯的答案。它能有效减少模型“幻觉”(即胡编乱造),让AI应用在知识密集型任务中变得真正可靠。以及,它能帮助构建专业领域专家对话机器人。

一个典型的RAG系统工作流程包含三个关键阶段:

  1. 知识库索引构建(Indexing)
    这是准备阶段,目的是将您的私有知识库“灌输”进向量数据库。
    文档解析与分块:首先,系统会解析各种格式的文档(如PDF、Word、HTML),将其转换为纯文本。然后,根据语义或结构将长文本切分成大小适宜的“文本块”(Chunks),以适应模型上下文长度限制。
    向量化(Embedding):使用嵌入模型将每个文本块转换为一个高维向量(一组数字)。这个向量就像是文本在数学空间中的“坐标”,语义相近的文本,其向量在空间中的距离也更近。
    向量存储:将这些向量及其对应的原始文本块、元数据(如来源、标题)一并存入向量数据库。
  2. 实时检索(Retrieval)
    当用户提出问题时,系统执行以下操作:
    使用相同的嵌入模型将用户问题也转换为一个向量。
    将这个“问题向量”送入向量数据库,进行相似性搜索。数据库会快速找出与问题向量最相似的K个“文档向量”。
    为了提高检索质量,常采用混合检索策略,结合语义向量搜索和传统关键词搜索,并利用重排序模型对初步结果进行精细排序,以提升准确性。
  3. 增强生成(Generation)
    提示词增强:将检索到的最相关的文本块作为上下文,与用户的原始问题一起组合成一个结构化的提示词(Prompt)。
    智能生成:将这个富含信息的提示词发送给LLM,基于您提供的权威上下文,而非仅凭其内部可能过时的知识,来生成最终答案

Agent流程编排

业务逻辑

LangChain

LangChain 是一个功能强大的大语言模型应用开发框架。与Spring在Java后端开发中的定位类似。
https://python.langchain.com/docs/concepts/
https://arxiv.org/abs/2302.07842

LangChain 包:通过 pip 命令(类似于Java的Maven或Gradle)安装到项目中,避免重复造轮子。

LangGraph

LangGraph 核心认知:用“有向图”构建智能体的新一代框架,是 用于构建有状态、多步骤、多分支智能体(Agent) 的框架,核心是将 Agent 的行为拆解为节点(Nodes)边(Edges),用有向图(Directed Graph) 替代老版本的“线性循环” 以支持更复杂的流程编排。
LangGraph 可以理解为:给 Agent 设计“流程图”的工具,而老版本 ReAct Agent 只是这个流程图中最基础的“单循环分支”。
https://docs.langchain.com/oss/python/langgraph/overview

  • LangGraph 核心概念解析(多节点、边是关键)
    1. 核心基础:状态(State)
      • 作用:整个图的“共享内存”,所有节点都能读写这个状态(比如用户问题、LLM 思考结果、工具调用结果、最终回答等)。
      • 举例:在你之前的 CMDB Agent 中,状态里会包含:
        1
        2
        3
        4
        5
        {
        "messages": [{"role": "user", "content": "显示运行中的Linux服务器"},
        {"role": "ai", "content": "思考过程+工具调用指令"},
        {"role": "tool", "content": "工具调用结果"}]
        }
      • 特点:状态是持久化的(通过 Checkpoint 如 InMemorySaver),支持中断、恢复、回溯(比如多轮对话的上下文保留)。
    2. 最小执行单元:节点(Node)
      • 定义:图的最小操作单元,对应一个具体的功能(比如调用 LLM、调用工具、格式化回答、清洗用户问题)。
      • 类型(实际开发中常见):
      • LLM 节点:调用大模型生成思考结果或工具调用指令(比如你之前看到的“分析问题+工具选择”)。
      • 工具调用节点:执行具体的工具函数(比如 cmdb_searchcmdb_query)。
      • 预处理/后处理节点:清洗用户问题、格式化最终回答。
      • 判断节点:根据状态判断流程走向(比如“是否需要继续调用工具?”)。
      • 多节点的价值:你可以把 Agent 的复杂行为拆分成多个独立节点,比如:
        用户输入清洗节点LLM 思考节点CMDB 工具节点日志工具节点回答格式化节点
    3. 流程的灵魂:边(Edge)
      • 定义:节点之间的连接关系,定义流程的走向。LangGraph 支持三种边,这也是“多分支”的核心:
      • 普通边(Direct Edge):直接从 A 节点跳转到 B 节点(比如“清洗节点”执行完,直接到“LLM 思考节点”)。
      • 条件边(Conditional Edge):根据状态的内容判断跳转方向(最核心的“多分支”能力)。
        • 举例:LLM 输出“需要调用 CMDB 工具”,则跳转到 cmdb_search 节点;如果输出“需要调用日志工具”,则跳转到 log_search 节点;如果输出“无需调用工具”,则跳转到“回答节点”。
      • 入口/出口边:定义图的开始节点(比如用户输入节点)和结束节点(比如回答节点)。
      • 多边的价值:打破了老版本“单一循环”的限制,支持分支、并行、循环等复杂流程。
    4. 关键能力:检查点(Checkpoint)
      • 作用:记录图的执行状态,支持中断、恢复、回溯(比如你之前用的 InMemorySaver 就是内存级的检查点,还可以用 Redis、SQL 实现持久化)。
      • 场景:多轮对话中,用户可以“回退”到上一步,或 Agent 崩溃后恢复执行。
  • LangGraph 中 Agent 与 Tools 的工作机制(结合你的 CMDB 例子)
    以你之前的“显示运行中的 Linux 服务器”为例,LangGraph 的执行流程可以拆解为一个极简的有向图
    1
    2
    3
    4
    5
    6
    7
    8
    9
    [入口节点:用户输入] 
    ↓(普通边)
    [LLM 思考节点]:分析问题,生成工具调用指令(cmdb_search + 入参)
    ↓(条件边:判断需要调用工具)
    [工具调用节点]:执行 cmdb_search,将结果写回状态
    ↓(条件边:判断无需继续调用工具)
    [LLM 回答节点]:基于工具结果生成最终回答
    ↓(普通边)
    [出口节点:输出回答]
    核心细节:
    1. 状态驱动:所有节点都通过状态交互,没有直接的函数调用——LLM 节点从状态中读用户问题,工具节点从状态中读工具调用指令,执行后写回结果。
    2. 工具的解耦:工具本身是独立的函数(如 cmdb_search),LangGraph 只通过工具调用节点统一管理,支持多工具的动态选择和调用。
    3. 循环执行:通过条件边实现“思考→工具→再思考→再工具”的循环(比如用户问“查生产主机并统计数量”,可能需要先调用 cmdb_search,再调用 cmdb_query 统计)。
  • LangGraph vs 老版本 ReAct Agent(核心区别)
    老版本 ReAct Agent(LangChain v0.x 的 AgentExecutor)是 LangGraph 的简化版,两者的核心差异在于流程的编排能力
    维度 老版本 ReAct Agent(AgentExecutor) LangGraph
    架构基础 线性循环(Single Loop) 有向图(Directed Graph)
    节点/边 无物理节点拆分,只有“思考→工具”的逻辑两步;无多分支边,只有单一循环。 支持多节点、多类型边(条件边、普通边),可编排复杂流程。
    状态管理 临时状态(每次循环重新生成,无持久化) 统一的状态对象,支持持久化、回溯(Checkpoint)。
    流程灵活性 只能“思考→工具→思考”的单一循环,多工具需按顺序调用(一次一个)。 支持多分支(比如不同工具的并行调用)、条件跳转、中断恢复。
    扩展性 扩展复杂流程(如多工具并行)需要大量自定义代码。 通过图的编排即可实现,无需修改核心逻辑。
    老版本 ReAct Agent 的核心是 AgentExecutor单一循环
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    while True:
    # 1. 调用 LLM 生成思考结果和工具调用指令
    llm_output = llm.invoke(状态)
    # 2. 判断是否需要调用工具
    if 需要调用工具:
    tool_result = tool.invoke(llm_output 中的指令)
    # 将工具结果加入状态,继续循环
    else:
    # 生成最终回答,退出循环
    break
    它的“节点”只是逻辑上的两步(思考、工具),没有物理上的节点拆分,也没有多分支的边——即使有多个工具,也只能按顺序单次调用(一次调一个),无法实现并行或多分支跳转。
    比如:
    老版本要实现“查生产主机+查今日告警”,只能先调用 cmdb_search,再调用 alert_search,通过多次循环实现。
    LangGraph 可以通过多节点和条件边,甚至并行执行这两个工具(比如同时调用 CMDB 和告警工具,提升效率)。
  • 五、总结:为什么需要 LangGraph?
    1. 从“单一循环”到“复杂图”:老版本 Agent 适合简单的单工具循环场景,而 LangGraph 适合需要复杂流程编排的场景(比如多工具、多分支、有状态的智能体)。
    2. 可视化与可维护性:将 Agent 的行为拆解为节点和边,流程更清晰,便于调试和维护(比如你之前看到的“两轮 LLM 调用”,在 LangGraph 中就是两个节点的执行)。
    3. 生产级能力:Checkpoint、状态持久化、中断恢复等能力,让 LangGraph 更适合生产环境的部署。

Spring AI

集成到Java

MongoDB


MongoDB 是一个基于文档的开源 NoSQL 数据库,使用类似 JSON 的文档模型灵活存储数据,旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
https://www.mongodb.com/zh-cn/docs/manual/crud/

MongoDB 概念 类比 MySQL 概念 类比 Elasticsearch 概念 核心解析
文档 (Document) 行 (Row) 文档 (Document) 数据的基本单元,是一个键值对的有序集合。它类似于一条完整的记录。
集合 (Collection) 表 (Table) 索引 (Index) 一组文档的容器。它类似于一张数据表。
数据库 (Database) 数据库 (Database) 无直接对应(可类比为索引的逻辑分组) 最高层的命名空间,用于组织和管理多个集合。一个 MongoDB 实例可以运行多个数据库,每个数据库在文件系统上有独立的文件。
字段 (Field) 列 (Column) 字段 (Field) 文档中的键值对,代表一个数据属性。
  • 关键特性与对比
    1. BSON:MongoDB 的“增强版JSON”
    BSON(Binary JSON)是 MongoDB 用来存储文档和数据交换的二进制格式。您可以把它理解为 JSON 的超级版,它支持 JSON 的所有数据类型,但更强大: 二进制编码:比 JSON 更紧凑,存储和扫描效率更高。更丰富的数据类型:除了字符串、数字、数组、对象外,还支持日期、对象ID(ObjectId)、二进制数据等特定类型。
    2. 灵活的模式(Schema)
    这是 MongoDB 与 MySQL 最根本的区别之一。同一个集合内的文档不需要具有相同的字段集。您可以随时为文档添加新字段,而无需像关系型数据库那样进行复杂的 ALTER TABLE 操作。
  • 如何根据场景选择
    特性 MongoDB MySQL Elasticsearch
    数据模型 文档模型,动态模式 关系模型,固定模式 文档模型,可定义映射
    查询语言 面向对象的 API 方法 标准 SQL 语句 JSON-based DSL
    核心优势 敏捷开发、水平扩展、存储复杂数据结构 复杂查询、事务一致性、数据完整性 全文搜索、日志分析、复杂聚合
    典型场景 内容管理系统、用户画像、实时分析、物联网 金融交易系统、ERP、CRM等需要严格事务的系统 搜索引擎、日志和指标分析、应用内搜索
  • Mongo CRUD汇总
    操作类型 方法示例 功能说明
    创建 (Create) db.hosts.insertOne({hostname: "web-01", ip: "192.168.1.100"}) 向集合中插入一条新文档。若集合不存在,会自动创建。
    批量创建 db.hosts.insertMany([{hostname: "web-01"}, {hostname: "db-01"}]) 批量插入多条文档。
    查询 (Read) db.hosts.find({status: "running"}) 查询所有符合条件的文档。不传参数则返回所有文档。
    条件查询 db.hosts.find({"specs.memory": {$gte: 8}}, {hostname: 1, _id: 0}) 使用查询操作符进行过滤,并使用投影选择返回的字段。
    更新 (Update) db.hosts.updateOne({hostname: "web-01"}, {$set: {"specs.memory": 32}}) 更新一条匹配的文档。$set 操作符用于修改特定字段的值。
    批量更新 db.hosts.updateMany({environment: "production"}, {$inc: {visits: 1}}) 更新所有匹配的文档。$inc 操作符用于将字段的值增加指定数额。
    删除 (Delete) db.hosts.deleteOne({hostname: "web-01"}) 删除一条匹配的文档。
    批量删除 db.hosts.deleteMany({status: "terminated"}) 删除所有匹配的文档。

读写

  • 写入确认:默认情况下,MongoDB 的写入操作是异步的。如果你的应用需要确保数据已经安全写入,可以设置 写关注(Write Concern)来控制确认级别。
  • 单文档原子性:所有 CRUD 操作在 单个文档 级别是原子的。例如,一条文档的更新操作要么完全成功,要么完全失败,不会出现只更新一半字段的情况。需要注意的是,insertMany 这样的多文档操作,默认情况下并非一个整体事务。
  • 比较操作符:$gt (大于), $gte (大于等于), $lt (小于), $lte (小于等于), $ne (不等于)。
    逻辑操作符:$and, $or, $in (匹配数组中任意值), $nin (不匹配数组中任何值)。
  • 关键操作:
    1
    2
    3
    4
    5
    6
    7
    // 创建
    db.hosts.insertOne({
    hostname: "web-01",
    ip: "192.168.1.100",
    specs: { cpu: 8, memory: 16 }, // 嵌入式文档
    tags: ["web", "production"]
    })
    1
    2
    3
    4
    5
    // 查询与投影
    db.hosts.find(
    { "specs.memory": { $gte: 8 }, "status": "running" },
    { hostname: 1, ip: 1, _id: 0 } // 投影:只返回指定字段
    )
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 更新操作符
    db.hosts.updateOne(
    { hostname: "web-01" },
    {
    $set: { "specs.memory": 32 }, // 设置字段
    $push: { tags: "upgraded" }, // 数组追加
    $inc: { "stats.visits": 1 } // 数值递增
    }
    )
  • 复杂查询模式:
    1
    2
    3
    4
    5
    6
    7
    // 逻辑组合查询
    db.hosts.find({
    $or: [ // $or逻辑操作符用于筛选出符合任意一组给定条件的文档
    { "environment": "production", "status": "running" }, // 每个条件组内部使用隐式的AND逻辑,需同时满足
    { "criticality": "high", "last_backup": { $gte: yesterday } } // $gte是“大于或等于”的比较操作符
    ]
    })
    1
    2
    3
    4
    5
    // 数组查询
    db.hosts.find({
    "tags": { $all: ["web", "load_balancer"] }, // 包含所有指定标签
    "ips": { $size: 3 } // 数组长度匹配
    })
    1
    2
    3
    4
    // 正则表达式与文本搜索
    db.hosts.find({
    "hostname": { $regex: "^web-.*", $options: "i" }
    })

聚合框架

  • 聚合和管道是 MongoDB 最强大、最独特的特性之一。核心概念用工厂流水线来理解:想象一下数据处理就像一条工厂装配线
    • 普通查询:像是在成品仓库里筛选符合条件的产品。例如:“给我找出所有红色的汽车。” 你得到的是原始产品列表。
    • 聚合管道:像是把原材料送进一条多阶段的加工流水线,每个工位(阶段)都对数据进行特定处理,最终产出全新的、经过深度加工的产品。例如:原材料 → 切割 → 焊接 → 喷漆 → 组装 → 全新的汽车模型+统计报告。
  • 目的:对数据进行多阶段转换、分组、计算,生成全新的数据结构。
  • 详细对比解析
    1. 普通查询:检索和筛选文档。你得到的是原始数据。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      // 场景:找出所有生产环境的Linux主机
      db.hosts.find({
      environment: "production",
      "os.type": "Linux"
      })

      // 返回结果:原始文档数组
      [
      {hostname: "web-01", environment: "production", os: {type: "Linux"}, memory_gb: 16, ...},
      {hostname: "db-01", environment: "production", os: {type: "Linux"}, memory_gb: 32, ...},
      // ... 直接返回所有匹配的文档
      ]
    2. 复杂查询:在检索时进行一些简单计算或逻辑处理。
      1
      2
      3
      4
      5
      6
      7
      // 场景:找出内存大于8G的生产环境主机,按内存降序排列,只显示主机名和内存
      db.hosts.find(
      { environment: "production", memory_gb: { $gt: 8 } },
      { hostname: 1, memory_gb: 1, _id: 0 } // 投影:选择字段
      ).sort({ memory_gb: -1 }).limit(10)

      // 返回结果:经过筛选和排序的文档,但结构基本不变
    3. 聚合管道 (Aggregation Pipeline) :对数据进行多阶段转换、分组、计算,生成全新的数据结构
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      // 目标:查询生产环境的应用,并获取其运行主机的详细信息
      db.applications.aggregate([ // 在'applications'集合上执行聚合管道
      // 阶段 1: $match - 筛选文档
      {
      $match: { // 过滤条件:只处理符合以下条件的应用文档
      "environment": "production", // 条件1: 环境为'production'
      "status": "active" // 条件2: 状态为'active'
      }
      },

      // 阶段 2: $lookup - 关联查询(连表查询)
      {
      $lookup: { // 从左集合(applications)关联到右集合(hosts)
      from: "hosts", // 要关联的集合名称:'hosts'
      localField: "app_name", // 左集合(applications)中的关联字段:应用名称
      foreignField: "running_apps", // 右集合(hosts)中的关联字段:运行的应用列表
      as: "host_details" // 将关联匹配到的主机文档存入此新字段(是一个数组)
      }
      },

      // 阶段 3: $unwind - 展开数组字段
      {
      $unwind: "$host_details" // 将`host_details`数组拆分为多条独立的文档,每条包含一个应用和一个主机
      },

      // 阶段 4: $project - 重塑文档结构
      {
      $project: { // 定义输出文档的字段
      "_id": 0, // 不显示原始的_id字段(0为排除)
      "application": "$app_name", // 将app_name重命名为application
      "team": "$owner_team", // 显示负责团队
      "criticality": 1, // 显示应用关键程度(1为包含)
      // 从关联的主机文档中提取信息
      "hostname": "$host_details.hostname", // 显示主机名
      "ip_address": "$host_details.ip_address", // 显示IP地址
      "cpu_cores": "$host_details.specs.cpu_cores", // 显示CPU核心数
      "memory_gb": "$host_details.specs.memory_gb", // 显示内存大小
      "disk_gb": "$host_details.specs.disk_gb" // 显示磁盘大小
      }
      },

      // 阶段 5: $sort - 结果排序
      {
      $sort: { // 排序条件
      "team": 1, // 首先按团队名称升序排列 (1: 升序, -1: 降序)
      "criticality": -1, // 其次按应用关键程度降序排列 (high比medium优先级高)
      "memory_gb": -1 // 关键程度相同时,按主机内存降序排列
      }
      }
      ])
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      // 应用文档示例
      {
      "_id": ObjectId("67a1b2c3d4e5f6a1b2c3d4e5"),
      "app_name": "订单服务",
      "environment": "production", // 环境: production, staging, development
      "owner_team": "order-team",
      "criticality": "high"
      }
      // 主机文档示例
      {
      "_id": ObjectId("77a1b2c3d4e5f6a1b2c3d4e5"),
      "hostname": "prod-order-01",
      "ip_address": "192.168.1.100",
      "environment": "production",
      "specs": {
      "cpu_cores": 8,
      "memory_gb": 32,
      "disk_gb": 500
      },
      "running_apps": ["订单服务", "用户服务"] // 在此主机上运行的应用名称数组
      }
      // 返回结果:完全重新组织的数据
      [
      {
      "application": "订单服务",
      "team": "order-team",
      "criticality": "high",
      "hostname": "prod-order-01",
      "ip_address": "192.168.1.100",
      "cpu_cores": 8,
      "memory_gb": 32,
      "disk_gb": 500
      },
      {
      "application": "支付网关",
      "team": "payment-team",
      "criticality": "critical",
      "hostname": "prod-payment-01",
      "ip_address": "192.168.1.101",
      "cpu_cores": 16,
      "memory_gb": 64,
      "disk_gb": 1000
      }
      // ... 其他结果
      ]
    4. CMDB 应用场景
      问题1:”显示每个团队负责的主机数量,并按环境分别统计”
      1
      2
      3
      4
      5
      6
      7
      8
      db.hosts.aggregate([
      { $match: { status: "running" } },
      { $group: {
      _id: { team: "$owner_team", env: "$environment" },
      host_count: { $sum: 1 }
      }},
      { $sort: { host_count: -1 } }
      ])
      问题2:”找出生产环境中,哪些应用依赖的主机平均内存使用率超过80%”
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      db.applications.aggregate([
      { $match: { environment: "production" } },
      { $lookup: {
      from: "hosts",
      localField: "dependent_hosts",
      foreignField: "hostname",
      as: "host_details"
      }},
      { $project: {
      app_name: 1,
      avg_memory_usage: { $avg: "$host_details.memory_usage_percent" }
      }},
      { $match: { avg_memory_usage: { $gt: 80 } } }
      ])

索引策略

  1. 索引类型与应用场景:
  • 单字段索引:db.hosts.createIndex({ hostname: 1 })
  • 复合索引:db.hosts.createIndex({ environment: 1, status: 1 })
  • 多键索引:数组字段索引 db.hosts.createIndex({ tags: 1 })
  • 文本索引:全文搜索 db.hosts.createIndex({ description: "text" })
  • TTL索引:自动过期数据 db.logs.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })
  1. 索引优化原则:
  • ESR规则:Equality(等值) → Sort(排序) → Range(范围)
  • 覆盖查询:索引包含所有查询字段,避免回表
  • 索引交集:MongoDB可自动组合多个索引

高可用与扩展

1. 复制集(Replica Set)深度

  • 架构组成
    1
    2
    3
    4
    5
    Primary(主节点)← 读写操作
    ↓ 数据同步
    Secondary-1(从节点)← 只读查询
    Secondary-2(从节点)← 只读查询
    Arbiter(仲裁节点)← 仅参与选举
  • 配置示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 复制集配置
    cfg = {
    _id: "cmdb-rs",
    members: [
    {_id: 0, host: "mongo1:27017", priority: 2},
    {_id: 1, host: "mongo2:27017", priority: 1},
    {_id: 2, host: "mongo3:27017", priority: 1, arbiterOnly: true}
    ]
    }
    rs.initiate(cfg)
  • 读写关注
    1
    2
    3
    4
    5
    6
    7
    // 强一致性写操作
    db.hosts.insertOne(doc, {
    writeConcern: { w: "majority", wtimeout: 5000 }
    })

    // 从节点读取(最终一致性)
    db.hosts.find().readPref("secondary")

2. 分片集群(Sharded Cluster)

  • 分片策略选择
    • 基于范围分片:适合范围查询,可能产生热点
    • 基于哈希分片:数据分布均匀,范围查询效率低
    • 区域分片:基于标签的智能数据分布
  • 分片键选择考量
    1
    2
    3
    4
    5
    // 好的分片键:基数高、分布均匀
    sh.shardCollection("cmdb.hosts", { "tenant_id": 1, "hostname": 1 })

    // 避免的选择:低基数、单调递增
    // sh.shardCollection("cmdb.hosts", { "created_date": 1 }) // 不好!

CMDB助手查询工具设计(基于MCP)

  • MCP工具架构设计
    1
    自然语言查询 → MCP Server → 查询解析器 → MongoDB查询生成器 → 结果格式化
  • MCP Server 核心代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    from mcp import MCPServer, Context
    import pymongo
    from typing import Dict, List, Any

    class CMDBAgentMcpServer:
    def __init__(self, mongo_uri: str):
    self.client = pymongo.MongoClient(mongo_uri)
    self.db = self.client.cmdb
    self.setup_tools()

    @mcp_tool(
    name="query_hosts",
    description="根据条件查询主机信息",
    args_schema={
    "type": "object",
    "properties": {
    "environment": {"type": "string", "enum": ["production", "staging", "development"]},
    "os_type": {"type": "string"},
    "min_memory": {"type": "integer"},
    "status": {"type": "string", "enum": ["running", "stopped", "maintenance"]},
    "tags": {"type": "array", "items": {"type": "string"}},
    "limit": {"type": "integer", "default": 10}
    }
    }
    )
    async def query_hosts(self, ctx: Context, **filters) -> List[Dict]:
    """智能主机查询工具"""
    # 构建MongoDB查询
    query = self._build_host_query(filters)

    # 执行查询
    cursor = self.db.hosts.find(query["filter"], query["projection"])
    cursor = cursor.sort(query["sort"]).limit(query["limit"])

    results = list(cursor)
    return self._format_host_results(results)

    def _build_host_query(self, filters: Dict) -> Dict:
    """将自然语言参数转换为MongoDB查询"""
    query_filter = {}

    # 环境过滤
    if filters.get("environment"):
    query_filter["environment"] = filters["environment"]

    # 操作系统过滤(支持模糊匹配)
    if filters.get("os_type"):
    query_filter["os.type"] = {"$regex": filters["os_type"], "$options": "i"}

    # 内存条件
    if filters.get("min_memory"):
    query_filter["specs.memory_gb"] = {"$gte": filters["min_memory"]}

    # 状态过滤
    if filters.get("status"):
    query_filter["status"] = filters["status"]

    # 标签查询
    if filters.get("tags"):
    query_filter["tags"] = {"$all": filters["tags"]}

    return {
    "filter": query_filter,
    "projection": {"_id": 0, "hostname": 1, "ip": 1, "environment": 1, "os": 1, "specs": 1},
    "sort": [("last_seen", -1)],
    "limit": filters.get("limit", 10)
    }

    @mcp_tool(
    name="analyze_infrastructure",
    description="基础设施统计分析",
    args_schema={
    "type": "object",
    "properties": {
    "analysis_type": {"type": "string", "enum": ["environment", "os", "team"]},
    "metric": {"type": "string", "enum": ["count", "memory", "cpu"]}
    }
    }
    )
    async def analyze_infrastructure(self, ctx: Context, analysis_type: str, metric: str = "count"):
    """聚合分析工具"""
    pipeline = self._build_analysis_pipeline(analysis_type, metric)
    results = list(self.db.hosts.aggregate(pipeline))
    return self._format_analysis_results(results, analysis_type, metric)

    # 使用示例
    server = CMDBAgentMcpServer("mongodb://localhost:27017/cmdb")
  • Agent提示词设计
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    你是一个CMDB专家,可以查询和分析基础设施信息。

    可用工具:
    1. query_hosts - 查询主机信息,支持按环境、操作系统、内存等条件过滤
    2. analyze_infrastructure - 统计分析基础设施资源分布

    示例交互:
    用户:列出生产环境中所有运行CentOS的主机
    AI:我将使用query_hosts工具查询...
    工具调用:query_hosts(environment="production", os_type="CentOS")

    用户:按环境统计主机数量
    AI:使用analyze_infrastructure进行分析...
    工具调用:analyze_infrastructure(analysis_type="environment", metric="count")
  • 高级查询特性支持
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    # 支持复杂查询的扩展工具
    @mcp_tool(
    name="advanced_host_search",
    description="高级主机搜索,支持复杂条件组合"
    )
    async def advanced_search(self, ctx: Context, search_expression: str):
    """支持自然语言复杂查询"""
    # 使用LLM解析复杂查询条件
    parsed_query = await self.llm_parse_search(search_expression)
    return await self.execute_advanced_query(parsed_query)

    # 关系查询工具
    @mcp_tool(
    name="find_related_assets",
    description="查找相关资产和依赖关系"
    )
    async def find_related_assets(self, ctx: Context, hostname: str, relation_type: str):
    """查询资产关系"""
    pipeline = [
    {"$match": {"hostname": hostname}},
    {"$graphLookup": { # 使用图查询查找关系
    "from": "asset_relations",
    "startWith": "$_id",
    "connectFromField": "from_asset",
    "connectToField": "to_asset",
    "as": "relationships"
    }}
    ]
    return list(self.db.hosts.aggregate(pipeline))

Kubernetes

2023-07-31 10:25:07 Docker /

Docker 是一种开源平台,一种快速构建、运行和管理应用的工具。它使用容器化技术,使得应用程序及其依赖性可以打包到一个容器中,并在任何支持 Docker 的环境中运行。
1 MobarXterm 通过 SSH 连接 linux虚拟机,操作虚拟机上的 Docker。
2 Windows本地:通过wsl安装Linux发行版本,安装docker desktop(将自动在WSL中配置Docker环境,借助linux内核运行)

容器(Container)

  • 容器是一个轻量级的、可移植的、自包含的单元,包括应用程序和其所有依赖项。
  • Docker 利用容器技术,将应用程序及其依赖项打包成一个容器,确保在不同环境中的一致性运行。
  • Docker 位于容器 和 服务器-操作系统/硬件 之间,是运行容器的引擎。
  • 隔离网络、文件、进程等环境。一个容器是一个沙盒隔离环境。
  • 相对于虚拟机技术,docker 启动更快、更清量。但容器共用宿主机的内存、CPU物理资源,多容器可能存在互相抢占资源的情况。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    docker run -d \                  # 创建并运行一个容器,-d 是让容器在后台运行;同一个镜像可创建多个容器
    --name mysgl \ # 给容器起名字,必须唯一
    -p 3306:3306 \ # 设置 宿主机端口:容器端口 映射
    -e TZ=Asia/Shanghai \ # 设置环境变量
    -e MYSQL_ROOT_PASSWORD=123 \ # 指定运行的镜像名,一般为 [镜像名]:[镜像版本]
    mysql
    docker ps # 查看本地容器(运行中的)
    docker ps a # 查看所有容器 (包括未运行)
    docker start <容器ID> # 启动容器
    docker stop <容器ID> # 停止容器中的进程,容器未删除
    docker rm <容器ID> # 删除容器
    docker inspect <容器ID> # 查看容器配置信息
    docker log <容器ID> # 查看容器日志
    docker exec -it <容器ID> bash # 进入容器内部,命令行模式(容器内部模拟出一个操作系统)
    容器打包成镜像: docker commit -a "作者信息" -m "log信息" <容器ID><目标镜像名称:tag版本>
    拷贝文件到容器: docker cp <文件目录> <容器ID>:<目标目录>
    拷贝容器文件到宿主机:docker cp <容器ID>:<文件目录><宿主机目标目录>
    更新容器设置:docker update <容器ID><相关设置>

镜像(Image)

  • 镜像是一个只读的模板,包含运行应用程序所需的所有信息,包括代码、运行时、库、环境变量和配置文件。
  • 容器是通过运行镜像创建的(像光盘),本地容器是真正运行的实例。镜像是容器的模板,是从容器打包来的,可以在不同操作系统,不同服务器之间传播。
  • 1
    2
    3
    4
    5
    6
    7
    docker images                                # 查看本地镜像
    docker search <名称关键字> # 搜索镜像仓库
    docker pull <镜像名:tag版本> # 下载镜像
    docker push <镜像名:tag版本> # 上传镜像
    docker rmi <镜像名:tag版本> # 删除镜像
    docker save -o <输出文件路径><镜像名:tag版本> # 打包本地镜像文件
    docker load -i <加载文件路径 # 导入本地镜像文件

仓库(Registry)

  • 仓库是存储和组织 Docker 镜像的地方。Docker Hub 是一个常见的公共仓库,你也可以搭建私有仓库。
  • Docker 镜像可以从仓库中拉取,也可以推送到仓库。

沙箱

  • 沙箱是一种安全机制,用于隔离和限制程序或应用程序的运行环境,以防止其对系统或其他程序产生潜在的危害。沙箱技术旨在创建一个受控制的环境,使得运行在其中的代码无法直接影响到系统的其他部分。这种隔离有助于确保安全性、防止恶意软件传播,同时提供一定程度的控制和监控。
  • 容器化平台(如 Docker)使用沙箱技术来隔离容器中的应用程序,确保它们互相独立运行。

容器创建

镜像结构:入口,层,基础镜像。分层的好处是可复用,,

  • 通过命令直接创建,需要完整镜像,几个G常有,稳定。
  • 通过dockerfile创建,不需要完整镜像,更灵活。
    Dockerfile 是一个包含构建镜像步骤的文本文件,包含一个个的指令。通过编写 Dockerfile,你可以定义如何构建镜像,包括基础镜像、安装依赖、复制文件等步骤。
  • 使用 Docker 的基本步骤
    1. 安装 Docker: 根据操作系统的不同,安装适合的 Docker 版本。
    2. 创建 Dockerfile: 编写包含应用程序构建步骤的 Dockerfile。
    3. 构建镜像: 在包含 Dockerfile 的目录中运行 docker build 命令构建镜像。(如java项目还需要jar包)
    4. 运行容器: 使用 docker run 命令基于构建的镜像创建和运行容器。
    5. 发布镜像: 将构建的镜像推送到 Docker 仓库,以便其他人可以拉取使用。

数据卷

  • 数据卷(volume)是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁(两边文件同时修改)。
    (容器一般只包括支持运行的最少文件,一般无vi或其他编辑器,所以无法进入容器直接对容器中的文件进行修改)
  • 如何挂载数据卷?在创建容器时,利用-v 数据卷名:容器内目录完成挂载。创建时如果发现挂载的数据卷不存在,会自动创建。
    1
    2
    3
    4
    docker volumels        # 查看数据卷
    docker volume rm # 删除数据卷
    docker volume inspect # 查看数据卷详情
    docker volume prune # 删除未使用的数据卷

容器编排(Orchestration):运维人员

容器编排是指在生产环境中管理和协调多个容器的过程。Docker 提供了 Docker Compose 工具,用于定义和运行多容器的应用。


Kubernetes

1. 什么是Kubernetes

Kubernetes是一个开源的容器编排引擎,可以用来管理容器化的应用,包括容器的自动化的部署、扩容、缩容、升级、回滚等等;
它是Google在2014年开源的一个项目,它的前身是Google内部的Borg系统。

Kubernetes出现之前,我们一般都是使用Docker来管理容器化的应用,但是Docker只是一个单机的容器管理工具,它只能管理单个节点上的容器,当我们的应用程序需要运行在多个节点上的时候,就需要使用一些其他的工具来管理这些节点,比如Docker Swarm、Mesos、Kubernetes等等;
这些工具都是容器编排引擎,它们可以用来管理多个节点上的容器,但是它们之间也有一些区别,比如Docker Swarm是Docker官方提供的一个容器编排引擎,它的功能比较简单,适合于一些小型的、简单的场景,而Mesos和Kubernetes则是比较复杂的容器编排引擎;
Mesos是Apache基金会的一个开源项目,而Kubernetes是Google在2014年开源的,目前已经成为了CNCF(Cloud Native Computing Foundation)的一个顶级项目,基本上已经成为了容器编排引擎的事实标准了。

2.1 Kubernetes 资源对象

Node:k8s集群节点,可以是物理机/虚拟机
Pod:k8s最小调度单元,容器(运行app/数据库/..镜像)的抽象,可以是一/多个容器的组合,但除非高度耦合,一个pod只运行一个容器
Service:将一组pod封装成一个服务并且提供统一访问入口(解决了一组数据库pod中一个重建后ip变化的问题,类似于“服务发现”)
Ingress:为了对外提供服务,将外部请求路由转发到内部集群的service上

ConfigMap:封装配置信息
Secret:封装敏感信息
其他安全机制:网络安全,访问控制,身份认证
Volumn:将数据挂在到本地磁盘或远程存储上,实现持久化存储

Deployment:部署无状态应用程序,将一/多个Pod组合到一起;冗余备份,相当于对Pod的抽象;具有副本控制、滚动更新、自动扩缩容等功能,实现应用程序的高可用
Statefulset:部署有状态应用程序,如DB、MQ、缓存以及保留会话状态的应用程序

2.2 Kubernetes 架构

分为Master和Worker节点
apiserver:位于master节点上,是k8s集群的API接口;交互方式包括 kubectl 命令行、Dashboard界面或API接口

3. 使用minikube搭建kubernetes集群环境

minikube是一个轻量级的kubernetes集群环境,可以用来在本地快速搭建一个单节点的kubernetes集群;
https://kubernetes.io/zh-cn/docs/tutorials/hello-minikube/ 你好,Minikube

4. 使用Multipassk3s搭建kubernetes集群环境

minikube只能用来在本地搭建一个单节点的kubernetes集群环境,
下面介绍如何使用Multipassk3s来搭建一个多节点的kubernetes集群环境,

5. 在线实验环境

Killercoda Play-With-K8s

6. kubectl常用命令

6.1 基础使用

1
2
3
4
5
6
7
8
# 查看帮助
kubectl --help

# 查看API版本
kubectl api-versions

# 查看集群信息
kubectl cluster-info

6.2 资源的创建和运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 创建并运行一个指定的镜像
kubectl run NAME --image=image [params...]
# e.g. 创建并运行一个名字为nginx的Pod
kubectl run nginx --image=nginx

# 根据YAML配置文件或者标准输入创建资源
kubectl create RESOURCE
# e.g.
# 根据nginx.yaml配置文件创建资源
kubectl create -f nginx.yaml
# 根据URL创建资源
kubectl create -f https://k8s.io/examples/application/deployment.yaml
# 根据目录下的所有配置文件创建资源
kubectl create -f ./dir

# 通过文件名或标准输入配置资源
kubectl apply -f (-k DIRECTORY | -f FILENAME | stdin)
# e.g.
# 根据nginx.yaml配置文件创建资源
kubectl apply -f nginx.yaml

6.3 查看资源信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 查看集群中某一类型的资源
kubectl get RESOURCE
# 其中,RESOURCE可以是以下类型:
kubectl get pods / po # 查看Pod
kubectl get svc # 查看Service
kubectl get deploy # 查看Deployment
kubectl get rs # 查看ReplicaSet
kubectl get cm # 查看ConfigMap
kubectl get secret # 查看Secret
kubectl get ing # 查看Ingress
kubectl get pv # 查看PersistentVolume
kubectl get pvc # 查看PersistentVolumeClaim
kubectl get ns # 查看Namespace
kubectl get node # 查看Node
kubectl get all # 查看所有资源

# 后面还可以加上 -o wide 参数来查看更多信息
kubectl get pods -o wide

# 查看某一类型资源的详细信息
kubectl describe RESOURCE NAME
# e.g. 查看名字为nginx的Pod的详细信息
kubectl describe pod nginx

6.4 资源的修改、删除和清理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 更新某个资源的标签
kubectl label RESOURCE NAME KEY_1=VALUE_1 ... KEY_N=VALUE_N
# e.g. 更新名字为nginx的Pod的标签
kubectl label pod nginx app=nginx

# 删除某个资源
kubectl delete RESOURCE NAME
# e.g. 删除名字为nginx的Pod
kubectl delete pod nginx

# 删除某个资源的所有实例
kubectl delete RESOURCE --all
# e.g. 删除所有Pod
kubectl delete pod --all

# 根据YAML配置文件删除资源
kubectl delete -f FILENAME
# e.g. 根据nginx.yaml配置文件删除资源
kubectl delete -f nginx.yaml

# 设置某个资源的副本数
kubectl scale --replicas=COUNT RESOURCE NAME
# e.g. 设置名字为nginx的Deployment的副本数为3
kubectl scale --replicas=3 deployment/nginx

# 根据配置文件或者标准输入替换某个资源
kubectl replace -f FILENAME
# e.g. 根据nginx.yaml配置文件替换名字为nginx的Deployment
kubectl replace -f nginx.yaml

6.5 调试和交互

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 进入某个Pod的容器中
kubectl exec [-it] POD [-c CONTAINER] -- COMMAND [args...]
# e.g. 进入名字为nginx的Pod的容器中,并执行/bin/bash命令
kubectl exec -it nginx -- /bin/bash

# 查看某个Pod的日志
kubectl logs [-f] [-p] [-c CONTAINER] POD [-n NAMESPACE]
# e.g. 查看名字为nginx的Pod的日志
kubectl logs nginx

# 将某个Pod的端口转发到本地
kubectl port-forward POD [LOCAL_PORT:]REMOTE_PORT [...[LOCAL_PORT_N:]REMOTE_PORT_N]
# e.g. 将名字为nginx的Pod的80端口转发到本地的8080端口
kubectl port-forward nginx 8080:80

# 连接到现有的某个Pod(将某个Pod的标准输入输出转发到本地)
kubectl attach POD -c CONTAINER
# e.g. 将名字为nginx的Pod的标准输入输出转发到本地
kubectl attach nginx

# 运行某个Pod的命令
kubectl run NAME --image=image -- COMMAND [args...]
# e.g. 运行名字为nginx的Pod
kubectl run nginx --image=nginx -- /bin/bash

7. Portainer的安装和使用

Portainer 是一个轻量级的容器管理工具,可以用来管理Docker和Kubernetes,它提供了一个Web界面来方便我们管理容器
官方网址: https://www.portainer.io/

8. Helm的安装和使用

Helm 是一个Kubernetes的包管理工具,可以用来管理Kubernetes的应用,它提供了一个命令行工具来方便我们管理Kubernetes的应用
官方网址: https://helm.sh/

集群存储

https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/

InfluxDB

InfluxDB 是一个由InfluxData开发的开源时序型数据库,专注于海量时序数据的高性能读、高性能写、高效存储与实时分析等;
在DB-Engines Ranking时序型数据库排行榜上排名第一,广泛应用于DevOps监控、IoT监控、实时分析等场景。
https://jasper-zhang1.gitbooks.io/influxdb/content/Introduction/getting_start.html

influxdb-cluster 是InfluxDB的集群版本,InfluxDB Enterprise 的开源替代方案,设计用于大规模数据存储和高可用性需求。
可以实现数据的分片和复制,从而提高系统的可用性和扩展性。数据安全。operator缺失
https://github.com/chengshiwen/influxdb-cluster/wiki

集群体系结构

InfluxDB Enterprise由两组软件进程组成: Data 数据节点 和 Meta 元节点。集群内的通信是这样的:

influxdb使用的默认端口号为分别为用于meta集群内部服务的8091端口,meta节点通信的8089端口,data集群内部服务的8088端口,以及data节点对外提供http服务的8086端

  • Meta 节点通过 TCP 协议和 Raft 共识协议相互通信,默认都使用端口 8089,此端口必须在 Meta 节点之间是可访问的。默认 Meta 节点还将公开绑定到端口 8091 的 HTTP API,influxd-ctl 命令使用该 API。
  • Data 节点通过绑定到端口 8088 的 TCP 协议相互通信。Data 节点通过绑定到 8091 的 HTTP API 与 Meta 节点通信。这些端口必须在 Meta 节点和 Data 节点之间是可访问的。
  • 在集群内,所有 Meta 节点都必须与所有其它 Meta 节点通信。所有 Data 节点必须与所有其它 Data 节点和所有 Meta 节点通信。

Where data lives

InfluxDB 集群中,一个节点要么是专门用于存储和查询时间序列数据的数据节点,要么是专门用于存储集群元数据的元节点。数据节点负责存储实际的数据和处理查询请求,而元节点则负责管理集群的元数据,包括节点信息、数据库和保留策略等。

Meta

元节点保存以下所有元数据:

  • 集群中的所有节点及其角色
  • 集群中存在的所有数据库和保留策略
  • 所有分片和分片组,以及它们存在于哪些节点上
  • 集群用户及其权限
  • 所有连续查询

元节点将这些数据保存在磁盘上的Raft数据库中,由BoltDB提供支持。默认情况下,Raft数据库是/var/lib/influxdb/meta/raft.db。
注意:Meta节点需要/ Meta目录。

  • influxd-meta 元数据服务
    1
    2
    3
    4
    5
    # 配置文件示例(meta节点)
    [meta]
    dir = "/var/lib/influxdb/meta" # 元数据存储路径
    bind-address = ":8089" # Raft协议通信端口
    http-bind-address = ":8091" # 管理API端口
  • influxd-ctl 集群管理
    1
    2
    3
    4
    5
    6
    7
    8
    # 查看分片分布
    kubectl exec influxdb-meta-0 -- influxd-ctl show-shards
    # 强制同步分片到新节点
    kubectl exec influxdb-meta-0 -- influxd-ctl copy-shard 3 influxdb-data-0:8088
    # 节点维护操作
    influxd-ctl remove-data influxdb-data-0:8088 # 下线节点
    # 检查Meta节点Raft状态
    kubectl exec influxdb-meta-0 -- influxd-ctl raft-state

Data

数据节点保存所有原始时间序列数据和元数据,包括:

  • measurements
  • tag keys and values
  • field keys and values

在磁盘上,数据总是按照//组织。默认父目录为/var/lib/influxdb/data。注意:数据节点需要/var/lib/influxdb/的所有四个子目录,包括/meta(specifically, the clients.json file)、/data、/wal和/hh。

  • influx CLI工具
    1
    2
    3
    4
    5
    6
    7
    # 进入容器执行CLI
    kubectl exec -it influxdb-data-0 -n influxdb -- influx -username admin -password 'xxx'

    # 常用命令
    SHOW DATABASES; # 显示所有数据库
    SELECT * FROM cpu; # 查询数据
    CREATE RETENTION POLICY "1d" ON db3 DURATION 1d REPLICATION 2; # 创建保留策略
  • influxd 数据节点服务
    1
    2
    3
    4
    5
    6
    # 查看运行状态
    kubectl exec influxdb-data-0 -- ps aux | grep influxd

    # 关键参数
    -data-dir /var/lib/influxdb/data # 数据存储目录
    -wal-dir /var/lib/influxdb/wal # WAL日志目录
  • influx_inspect 数据工具
    1
    2
    3
    4
    5
    6
    7
    8
    # 导出TSM文件(需进入容器)
    kubectl exec -it influxdb-data-0 -- influx_inspect export \
    -datadir /var/lib/influxdb/data \
    -waldir /var/lib/influxdb/wal \
    -out backup.gz -compress

    # 验证数据完整性
    influx_inspect verify -dir /var/lib/influxdb/data/db3

Data 与 Meta节点交互机制

  1. 通信协议

    组件 端口 用途 协议
    Meta节点间 8089 Raft协议同步元数据 TCP
    Data节点间 8088 分片数据复制 TCP
    Data→Meta节点 8091 注册节点/获取分片元信息 HTTP
  2. 核心交互场景
    节点注册 : Data节点启动时通过HTTP API向Meta节点注册(POST /data
    分片分配 : Meta节点根据replication-factor策略分配分片到Data节点
    写入协调 : 客户端写入数据时,由Meta节点确定目标分片所在Data节点
    故障转移 : Meta节点检测Data节点离线后,自动通过Hinted Handoff机制转移副本

一个集群至少要有三个独立的元节点才能允许一个节点的丢失,如果要容忍n个节点的丢失则需要2n+1个元节点。集群的元节点的数目应该为奇数。不要是偶数元节点,因为这样在特定的配置下会导致故障。
一个集群运行只有一个数据节点,但这样数据就没有冗余了。这里的冗余通过写数据的RP中的副本个数来设置。一个集群在丢失n-1个数据节点后仍然能返回完整的数据,其中n是副本个数。为了在集群内实现最佳数据分配,我们建议数据节点的个数为偶数。

术语 / Glossary

  • measurement:描述了存在关联field中的数据的意义,measurement是字符串。作为tag,fields和time列的容器。相当于MySQL的table,关系/表的意思。单个measurement可以有不同的retention policy(即 一个measurement 中的不同 tag set 可以有不同的 retention policy,构成多组 series)
  • Continuous Query (CQ)是在数据库内部自动周期性跑着的一个InfluxQL的查询,CQs需要在SELECT语句中使用一个函数,并且一定包括一个GROUP BY time()语句。
  • Retention Policy (RP)是InfluxDB数据结构的一部分,描述了InfluxDB保存数据的长短,数据存在集群里面的副本数,以及shard group的时间范围。RPs在每个database里面是唯一的,?连同measurement和tag set定义一个series。当创建一个database时,InfluxDB会自动创建一个叫做autogen的retention policy,其duration为永远,replication factor为1,shard group的duration设为七天。
    • duration:决定InfluxDB中数据保留多长时间。在duration之前的数据会自动从database中删除掉。
    • replication factor:决定在集群模式下数据的副本的个数。InfluxDB在N个数据节点上复制数据,其中N就是replication factor。
    • shard group duration决定了每个shard group跨越多少时间。具体间隔由retention policy中的SHARD DURATION决定。例如,如果retention policy的SHARD DURATION设置为1w,则每个shard group将跨越一周,并包含时间戳在该周内的所有点。
  • series:InfluxDB数据结构的集合,一个特定的series由measurement,tag set和retention policy组成。!field set不是series的一部分
  • schema:数据在InfluxDB里面怎么组织。InfluxDB的schema的基础是database,retention policy,series,measurement,tag key,tag value以及field keys。
  • shard:包含实际的编码和压缩数据,并由磁盘上的TSM文件表示。 每个shard都属于唯一的一个shard group。多个shard可能存在于单个shard group中。每个shard包含一组特定的series。给定shard group中的给定series上的所有点将存储在磁盘上的相同shard(TSM文件)中。
  • shard group:是shard的逻辑组合。shard group由时间和retention policy组织。包含数据的每个retention policy至少包含一个关联的shard group。给定的shard group包含其覆盖的间隔的数据的所有shard。每个shard group跨越的间隔是shard的持续时间。

InfluxDB读写

  1. 命令行工具
    • influx命令行连接本地InfluxDB:直接通过InfluxDB的HTTP接口(如果没有修改,默认是8086)来和InfluxDB通信。(说明:也可以直接发送裸的HTTP请求来操作数据库,例如curl)
      1
      2
      3
      4
      $ influx -precision rfc3339
      Connected to http://localhost:8086 version 1.2.x //
      InfluxDB shell 1.2.x
      >
      InfluxDB的HTTP接口默认起在8086上,所以influx默认也是连的本地的8086端口。-precision参数表明了任何返回的时间戳的格式和精度,如 rfc3339是让InfluxDB返回RFC339格式(YYYY-MM-DDTHH:MM:SS.nnnnnnnnnZ)的时间戳。
    • 数据格式:将数据点写入InfluxDB,只需要遵守如下的行协议:
      1
      <measurement>[,<tag-key>=<tag-value>...] <field-key>=<field-value>[,<field2-key>=<field2-value>...] [unix-nano-timestamp]
      InfluxDB里存储的数据被称为时间序列数据,其包含一个数值。时序数据有零个或多个数据点,每一个都是一个指标值。数据点包括time(一个时间戳),measurement(例如cpu_load),至少一个k-v格式的field(也即指标的数值例如 “value=0.64”或者“temperature=21.2”),零个或多个tag,其一般是对于这个指标值的元数据(例如“host=server01”, “region=EMEA”)。
      可以将measurement类比于SQL里的table,其主键索引总是时间戳。tag和field是在table里的其他列,tag是被索引起来的,field没有。不同之处在于InfluxDB里,你可以有几百万的measurements,不用事先定义数据的scheme,且null值不会被存储。
    • 使用CLI插入单条的时间序列数据到InfluxDB中,用INSERT后跟数据点:
      1
      2
      3
      > use testdb
      Using database testdb
      > INSERT cpu,host=serverA,region=us_west value=0.64
      这样一个measurement为cpu,tag是host和region,value值为0.64的数据点被写入了InfluxDB中。
    • 现在我们查出写入的这笔数据:
      1
      2
      3
      4
      5
      6
      7
      > SELECT "host", "region", "value" FROM "cpu"
      name: cpu
      ---------
      time host region value
      2015-10-21T19:28:07.580664347Z serverA us_west 0.64

      > delete FROM "cpu" WHERE "host" = 'serverA' # 不带where将删除measurement所有数据
      我们在写入的时候没有包含时间戳,当没有带时间戳的时候,InfluxDB会自动添加本地的当前时间作为它的时间戳。
  2. HTTP 请求
    • 写数据
      1
      curl -i -XPOST 'http://localhost:8086/write?db=mydb' --data-binary 'cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000'
    • 读数据
      1
      curl -G 'http://localhost:8086/query?pretty=true' --data-urlencode "db=mydb" --data-urlencode "q=SELECT \"value\" FROM \"cpu_load_short\" WHERE \"region\"='us-west'"
  3. 客户端库,InfluxDB 提供了多种编程语言的客户端库,如Python、Go、Java等,可以方便地在应用程序中读写数据。
  4. 采样和数据保留 https://jasper-zhang1.gitbooks.io/influxdb/content/Guide/downsampling_and_retention.html

集群读写

  • 分片Shard:InfluxDB集群读写的基本单位分片是时间序列数据的物理存储单位,每个分片包含一段时间范围内的数据。
    复制因子为X,则在每个分片的数据同步到X个节点(部署influxdb的主机)上。
    分片的划分依据是时间范围和数据的存储策略(Retention Policy)。在集群环境中,分片可以分布在不同的节点上,以实现数据的分布式存储和负载均衡。这样可以提高数据的读写性能和系统的可扩展性。
    确定数据属于哪个分片的过程主要涉及以下几个步骤:数据写入时,首先根据时间戳确定属于哪个Shard Group(分片组)。然后,基于Measurement和Tag的值计算哈希值。最后,根据哈希值将数据分配到具体的分片。

    shard := shardGroup.shards[fnv.New64a(key) % len(shardGroup.Shards)]

  • 分片组Shard groups:集群在一个分片组内创建分片,以最大限度地利用数据节点的数量。
    分片数计算:当集群有 N 个数据节点且副本因子为 X 时,每个分片组中会创建 floor(N/X) 个分片(向下取整)
    示例:若集群有 4 个数据节点,副本因子为 2,则每个分片组包含 4/2=2 个分片(每个分片在 2 个节点上复制)
  • 集群写入:
    假设一个HTTP写操作被发送到服务器D,数据属于分片1。写操作需要被复制到分片1的所有者:数据节点A和B。当写操作进入D时,该节点从其亚转移的本地缓存中确定需要将写操作复制到A和B,并立即尝试对两者进行写操作。
    每个对HTTP API的请求都可以通过一致性查询参数指定一致性级别。 https://docs.influxdata.com/enterprise_influxdb/v1/concepts/clustering/#write-consistency
  • 集群查询:
    根据查询的时间段和数据的复制因子进行分布的。例如,如果保留策略的复制因子为4,则接收查询的协调数据节点将随机选择存储该分片副本的4个数据节点中的任何一个来接收查询。如果我们假设系统的分片持续时间为一天,那么对于查询覆盖的每一天,协调节点都会选择一个数据节点来接收当天的查询。
    协调节点尽可能在本地执行和完成查询。如果一个查询必须扫描多个shard组(在上面的例子中是多个天),协调节点将查询转发给其他节点,以查找本地没有的shard。查询与扫描自己的本地数据并行转发。查询被分发到尽可能多的节点,以查询每个分片组一次。当结果从每个数据节点返回时,协调数据节点将它们组合成返回给用户的最终结果。
  • Shard Group 与 Shard 的实战示例:
    1. 场景描述,假设有以下配置:
      Retention Policy: Duration: 30d | Replication Factor: 2 | Shard Group Duration: 1d,
      集群数据节点: 4 个(A/B/C/D)
    2. 分片组创建
      时间划分:每天 00:00 自动创建新的分片组(如 2025-04-02 ~ 2025-04-03)
      分片数:4/2=2 个分片(Shard 1 & 2)
    3. 分片分布
      分片 1 | 副本节点 A, B | 存储内容 所有哈希值模2=0的 Series Key 数据
      分片 2 | 副本节点 C, D | 存储内容 所有哈希值模2=1的 Series Key 数据
    4. 数据写入示例
      当写入 cpu,host=svr1 usage=80:Series Key = cpu,host=svr1,哈希值模2=1 ⇒ 分片2,数据同时写入节点 C 和 D
    5. 数据查询流程
      查询 SELECT * FROM cpu WHERE time > '2025-04-02':定位到 2025-04-02 分片组, 协调节点同时向 A/B(分片1)和 C/D(分片2)发起查询, 合并结果后返回

集群部署

Docker安装操作单例InfluxDB https://www.cnblogs.com/nhdlb/p/16409849.html
Docker快速开始集群InfluxDB https://github.com/chengshiwen/influxdb-cluster/wiki#docker-%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B

在使用容器多节点部署InfluxDB时,数据库、容器、Docker、主机和Kubernetes(k8s)之间的关系可以理解如下:

  • 数据库(InfluxDB):InfluxDB是一个时序数据库,用于存储和查询时间序列数据。在多节点部署中,InfluxDB可以运行在多个容器中,以实现高可用性和负载均衡。
  • 容器:容器是一个轻量级、独立的运行环境,用于打包和运行应用程序及其依赖项。InfluxDB可以被打包成一个容器镜像,并在多个容器实例中运行。
  • Docker:Docker是一个容器化平台,用于创建、部署和管理容器。Docker负责启动和管理运行InfluxDB的容器。
  • 主机:主机是运行Docker和容器的物理或虚拟机器。在多节点部署中,可能有多个主机,每个主机上运行一个或多个InfluxDB容器。
  • Kubernetes(k8s):一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。Kubernetes可以管理多个主机上的容器,提供服务发现、负载均衡、自动扩展和自愈能力。在多节点部署中,Kubernetes可以管理InfluxDB容器的部署,确保它们在多个节点上运行,并提供高可用性和扩展性。
  • 关系总结:InfluxDB 作为数据库运行在 容器 中。容器 由 Docker 创建和管理。Docker 运行在 主机 上。Kubernetes 管理多个 主机 上的 Docker 容器,提供编排和管理功能。通过这种方式,InfluxDB可以在一个分布式环境中高效运行,利用Kubernetes的编排能力实现自动化管理和扩展。

Kubernetes 存储与 InfluxDB Shard 的关系解析

  1. PV/PVC:是 Kubernetes 管理存储资源的抽象层。PV 描述物理存储资源(如 NFS、云盘等),PVC 是 Pod 对存储资源的请求声明。PVC 绑定到 PV 后,Pod 通过挂载 PVC 使用持久化存储。
  2. Shard:是 InfluxDB 存储引擎的物理存储单元,表现为磁盘上的 TSM 文件(Time-Structured Merge Tree),每个 Shard 对应一个时间范围内的时序数据块。Shard 的存储路径通常位于 PVC 挂载的 /var/lib/influxdb/data 目录下。
    每个 Shard 包含:时间序列索引(.tsi 文件),压缩后的时序数据块(.tsm 文件),WAL(Write-Ahead Log)日志文件(.wal) 其路径结构为:/var/lib/influxdb/data/<database>/<retention_policy>/<shard_id>
  3. 重建 PVC 导致数据丢失的本质问题
    PVC 删除与 PV 回收策略:若 PVC 的回收策略为 Delete(默认),删除 PVC 会导致 Kubernetes 清理其绑定的 PV 及底层存储数据(如 NFS 目录、云盘等)。此时 /var/lib/influxdb 下的 datameta 目录被清空,导致 Shard 文件丢失。
    • Shard 文件丢失会导致对应时间范围的时序数据不可查询,触发 ERR: shard not found 错误。
    • Meta 文件丢失会破坏集群元数据一致性,导致用户权限、分片策略等配置失效。

InfluxDB 备份与恢复

https://docs.influxdata.com/enterprise_influxdb/v1/administration/backup-and-restore/
https://blog.csdn.net/weixin_46560589/article/details/127748939

InfluxDB Enterprise支持在集群实例、单个数据库和保留策略以及单个分片中备份和恢复数据。

  1. 备份整个实例,即所有数据库(全量备份)。命令如下:
    1
    influxd backup -portable /path/to/backup
  2. 备份单个数据库
    1
    influxd backup -portable -database <database_name> /path/to/backup
  3. 增量备份:对于较大的数据集,可以进行增量备份,只备份自上次全量或增量备份以来的数据
    1
    influxd backup -portable -start <timestamp> /path/to/backup

备份的数据可以恢复到新实例或现有实例中。

  1. 恢复整个实例,包括所有的数据库。命令如下:
    1
    influxd restore -portable /path/to/backup
  2. 恢复单个数据库
    1
    influxd restore -portable -db <database_name> /path/to/backup
  3. 有时你可能希望将备份的数据恢复到另一个数据库,可以使用 -newdb 选项来实现:
    1
    influxd restore -portable -db <old_database_name> -newdb <new_database_name> /path/to/backup

导出和导入数据

对于大多数InfluxDB Enterprise应用程序,备份和恢复实用程序提供了备份和恢复策略所需的工具。但是,在某些情况下,标准备份和恢复实用程序可能无法充分处理应用程序中的大量数据。作为标准备份和恢复实用程序的替代方案,可以使用InfluxDB influx_inspect export和涌入-import命令为灾难恢复和备份策略创建备份和恢复过程。

  1. 数据库导出:容器层面命令,指定 数据文件和 写前日志(WAL)文件的存储目录,将指定数据库中指定时间的数据导出到指定文件。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    root@influxdb-e2cb6c913a191e56c134e-data-0:/# influx_inspect export -datadir "/var/lib/influxdb/data" -waldir "/var/lib/influxdb/wal" -out "influxdb_test01_dump_out" -database "test01" -start "2024-10-22T00:00:00Z"
    writing out tsm file data for test01/autogen...complete.
    writing out wal file data for test01/autogen...complete.
    root@influxdb-e2cb6c913a191e56c134e-data-0:/# cat influxdb_test01_dump_out
    # INFLUXDB EXPORT: 2024-10-22T00:00:00Z - 2262-04-11T23:47:16Z
    # DDL
    CREATE DATABASE test01 WITH NAME autogen
    # DML
    # CONTEXT-DATABASE:test01
    # CONTEXT-RETENTION-POLICY:autogen
    # writing tsm data
    temp,location=room1 value=24.5 1729589246099070937
    temp,location=room2 value=22.5 1729589253425715740
    temp,location=room3 value=22 1729649010554978701
    # writing wal data
  2. 数据库导入:容器层面执行命令,使用admin账号,指定文件、数据库、时间戳精度
    1
    2
    3
    4
    root@influxdb-e73f149ff7192bd87d190-data-1:/# influx -import -path='influxdb_test01_dump_out' -precision=ns -username='' -password=''
    2024/10/25 03:21:47 Processed 1 commands
    2024/10/25 03:21:47 Processed 2 inserts
    2024/10/25 03:21:47 Failed 0 inserts
  3. 实例导出:把influxdb集群实例中所有数据库的数据导出,不加 -database,加 -compress
  4. 实例导入:加-compressed 导入压缩文件,本质上是先解压后倒入

InfluxDB节点迁移

Data节点迁移方案评审:先迁移后逐个恢复分片数据。已验证在分片副本大小70M、写入数据达2000point/s的情况下直接copy-shard会导致增量数据丢失,考虑在copy-shard前先执行truncate-shards截断热分片(集群中所有写入最新数据的分片,截断后关闭写入,变成冷分片),并在所有Data节点上创建该分片的新热分片副本,也就是在迁移节点上恢复了全部原有分片的新热分片副本,最新数据写入这个副本,然后再逐个从健康节点上的冷分片副本copy-shard恢复出分片的历史数据(迁移前分片副本原有的数据&迁移过程中未能写入的数据),该分片数据完全恢复;自测符合预期

  1. 在做迁移操作前,先记录迁移节点拥有的分片副本,后续从健康节点的相同副本中恢复出来;
    1
    kubectl exec -i influxdb-xx-meta-0 -n influxdb -- influxd-ctl show-shards # 或influx命令行执行show shards
  2. 迁移后更新节点/分片元信息,新data-0节点丢失db1的shard3,另外_internal的db1转移到健康节点data-1上了
    1
    2
    kubectl exec -i influxdb-xx-meta-0 -n influxdb -- influxd-ctl remove-data influxdb-xx-data-0.influxdb-xx-data:8088
    kubectl exec -i influxdb-xx-meta-0 -n influxdb -- influxd-ctl add-data influxdb-xx-data-0.influxdb-xx-data:8088
  3. 持续写入数据到db1(只能写入健康节点上的db1分片副本),某一时刻执行truncate-shards,db1的shard3切断,新热分片shard4的分片副本分配到data-1以及迁移后的data-0中,此刻开始写入db1的新数据在data-0和data-1上的分片中一致(一个数据库的分片可能有多个,但只有一个正在写入,其他都是冷分片)
    1
    kubectl exec -i influxdb-xx-meta-0 -n influxdb -- influxd-ctl truncate-shards
  4. 最后再恢复历史数据,也就是执行迁移前的data-0节点拥有的分片副本数据,以及迁移完成前应该写入但没有写入data-0的数据。从健康的data-1上的分片副本copy-shard而来,导出文件可见data-0和data-1上的db1数据完全一致
    1
    2
    3
    # 对于_internal分片的转移 先copy后remove
    kubectl exec -i influxdb-xx-meta-0 -n influxdb -- influxd-ctl copy-shard influxdb-xx-data-1.influxdb-xx-data:8088 influxdb-xx-data-0.influxdb-xx-data:8088 1
    kubectl exec -i influxdb-xx-meta-0 -n influxdb -- influxd-ctl remove-shard influxdb-xx-data-1.influxdb-xx-data:8088 1
    1
    2
    3
    # 分片的物理文件 wal&tsm
    kubectl exec -i influxdb-xx-data-0 -n influxdb -- ls /var/lib/influxdb/data
    kubectl exec -i influxdb-xx-data-0 -n influxdb -- ls /var/lib/influxdb/wal
    1
    2
    3
    # 可能要等wal落tsm
    kubectl exec -i influxdb-xx-data-0 -n influxdb -- influx_inspect export -datadir "/var/lib/influxdb/data" -waldir "/var/lib/influxdb/wal" -out "influxdb_dump_out" -database "db1"
    kubectl exec -i influxdb-xx-data-0 -n influxdb -- md5sum influxdb_dump_out

Golang


Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。
Go 语言被设计成一门应用于搭载 Web 服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。 对于高性能分布式系统领域而言,Go 语言无疑比大多数其它语言有着更高的开发效率。它提供了海量并行的支持,这对于游戏服务端的开发而言是再好不过了。

除了OOP外,近年出现了一些小众的编程哲学,Go语言对这些思想亦有所吸收。例如,Go语言接受了函数式编程的一些想法,支持匿名函数与闭包。再如,Go语言接受了以Erlang语言为代表的面向消息编程思想,支持goroutine和通道,并推荐使用消息而不是共享内存来进行并发编程。总体来说,Go语言是一个非常现代化的语言,精小但非常强大。

Go

  • Go 语言最主要的特性
    自动垃圾回收 更丰富的内置类型 函数多返回值 错误处理 匿名函数和闭包 类型和接口 并发编程 反射 语言交互性
    https://www.runoob.com/go/go-tutorial.html
  • Go 和 Java 有很多共同之处
    C 系列 (强类型,括号) 静态类型 垃圾收集 内存安全 (nil 引用,运行时边界检查) 变量总是初始化 (zero/nil/false)
    方法 接口 类型断言 (实例) 反射
  • Go 与 Java 的不同之处
    代码程序直接编译成机器码,没有 VM
    静态链接二进制 内存布局控制 函数值和词法闭包 内置字符串 (UTF-8) 内置泛型映射和数组/片段 内置并发
  • Go 特意去掉了大量的特性
    没有类 没有构造器 没有继承 没有 final 没有异常 没有注解 没有自定义泛型
  • 为 Java 程序员准备的 Go 语言入门 PPT https://www.runoob.com/w3cnote/go-for-java-programmers.html

Go 项目构建

  • Module:是 Go 语言用于管理项目依赖和版本的一种机制。go.mod 文件定义了模块的元数据和依赖关系。
    go.mod 文件是声明依赖的地方,记录了项目的依赖关系。如果项目中没有 go.mod,需要先运行 go mod init 来初始化模块。然后使用 go get(或其他命令)来引入依赖,下载到本地缓存(~/go/pkg/mod),并更新 go.mod,添加对应的模块路径和版本要求。
  • Makefile:是一个用于自动化构建、测试和其他任务的工具。它允许你定义复杂的构建流程和依赖关系。
    Makefile 可以包含多个targets,例如 build、test、clean 等。make 命令会查找当前目录下的 Makefile 并执行指定的目标。
    构建过程本身不负责引入依赖,它假定所有必要的依赖已经通过 go.mod 文件声明并被解析(否则报错),将编译代码并链接所有必要的依赖来生成最终的可执行文件或库文件。如果 go.mod 中声明的依赖尚未下载,Go 工具链会自动为你下载这些依赖。如果你的项目中没有 go.mod,go build 将无法正确识别和下载依赖(除非是 Go 1.11 前的版本)
  • 项目构建…
    • 对于一个带有 go.mod 文件的 Go 项目,项目所需的依赖不会自动下载到本地环境中。需要手动运行 go mod downloadgo mod tidy 来下载依赖,或者直接运行 go build 以触发依赖的下载。
    • 如果本地已有的依赖版本与 go.mod 文件中声明的版本不同,Go 工具链会优先使用 go.mod 文件中指定的版本。Go 会从远程仓库下载与 go.mod 兼容的依赖版本,并将其存储在本地缓存目录(通常是 ~/go/pkg/mod)中。
    • Go 项目使用的依赖是项目特定的,存储在项目的本地缓存中,而不是全局的 GOPATH 或者 GOROOT 目录。这意味着不同的项目可以依赖同一库的不同版本,而不会发生冲突。其实际工作目录go env中的配置(看上去是如果配置全局 PATH=%GOPATH%\bin 就使用 GOPATH 中的go.exe和pkg)
    • 对于复杂的构建流程和依赖关系,有时还需要根据 Makefile 文件,执行 build来构建项目。
  • VSCode 连接 WSL的Linux环境 开发 Go 项目(先用ubuntu开发,后再centos验证)
    1
    2
    3
    4
    5
    6
    7
    D:\Users\caifeng7>wsl -l -v
    NAME STATE VERSION
    * Ubuntu Running 2
    CentOS7 Running 2

    D:\Users\caifeng7>wsl # 管理员cmd进入wsl的默认linux发行版
    root@caifeng7138:/mnt/d/Users/caifeng7#
    安装go到linux,配置ubuntu上的golang开发环境(centos使用yum管理包)
    1
    2
    sudo apt update
    sudo apt install golang-go
    将GOPATH/bin添加到的PATH环境变量中
    1
    2
    echo 'export PATH=$PATH:/root/go/bin' >> ~/.bashrc
    source ~/.bashrc
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    root@caifeng7138:/mnt/c/Windows/system32# go env
    GO111MODULE=''
    GOARCH='amd64'
    GOBIN='' # 编译后的二进制文件的存放位置
    GOCACHE='/root/.cache/go-build' # Go编译缓存的路径
    GOENV='/root/.config/go/env'
    GOEXE=''
    GOEXPERIMENT=''
    GOFLAGS=''
    GOHOSTARCH='amd64'
    GOHOSTOS='linux'
    GOINSECURE=''
    GOMODCACHE='/root/go/pkg/mod'
    GONOPROXY=''
    GONOSUMDB=''
    GOOS='linux'
    GOPATH='/root/go' # Go工作空间的根目录,用于存放你的Go项目和依赖。
    GOPRIVATE=''
    GOPROXY='https://proxy.golang.org,direct' # 修改代理 export GOPROXY=https://goproxy.cn,direct
    GOROOT='/usr/lib/go-1.22' # Go语言的安装目录,包含了Go的编译器、标准库和工具。
    GOSUMDB='sum.golang.org'
    GOTMPDIR=''
    GOTOOLCHAIN='auto'
    GOTOOLDIR='/usr/lib/go-1.22/pkg/tool/linux_amd64'
    GOVCS=''
    GOVERSION='go1.22.2'
    GCCGO='gccgo'
    GOAMD64='v1'
    AR='ar'
    CC='gcc'
    CXX='g++'
    CGO_ENABLED='1'
    GOMOD='/dev/null'
    GOWORK=''
    CGO_CFLAGS='-O2 -g'
    CGO_CPPFLAGS=''
    CGO_CXXFLAGS='-O2 -g'
    CGO_FFLAGS='-O2 -g'
    CGO_LDFLAGS='-O2 -g'
    PKG_CONFIG='pkg-config'
    GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffil...'
    VSCode使用WSL:Remote Explorer选择linux发行版,使用Ubuntu环境打开Go项目目录: /mnt/d/code/datamars-agent/
    此时自动下载了项目go.mod要求的go版本? 项目中的环境变量发生变化 ↓
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    root@caifeng7138:/mnt/d/code/datamars-agent# go env
    # 个人用户的Go工作空间。用于存放Go项目和依赖
    GOPATH='/root/go'
    # Go的安装目录,指向通过模块系统安装的一个特定版本(1.22.4),而不是 /usr/lib/go(全局路径)
    GOROOT='/root/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.22.4.linux-amd64'
    # Go工具链的安装目录
    GOTOOLDIR='/root/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.22.4.linux-amd64/pkg/tool/linux_amd64'
    GOVERSION='go1.22.4'
    # Go模块缓存的路径
    GOMOD='/mnt/d/code/datamars-agent/go.mod'
    在WSL中,安装protoc,添加到PATH;
    执行make,通过makefile中的配置构建项目,编译proto文件,生成Go,grpc程序
    Protobuf 是一种由 Google 开发的用于序列化结构化数据的语言中立、平台中立的可扩展机制,Protoc 可以将 定义了数据结构和序列化规则的 .proto 文件编译生成包括 Go,Java的多种语言。用于grpc请求的数据同步。。

Lic Ai

保 险

社会保障

通过对国民收入的再分配,使公民在遇到特定风险或困难时能够获得基本生活保障。本质是追求一种公平。

社会保险

  1. 养老保险:为了保障老年人退休后的基本生活,通过个人和单位的缴费,在退休后按月领取养老金。个人在达到法定退休年龄时,如果满足缴费年限等条件,就可以领取养老金。
  2. 医疗保险:旨在为参保人员提供医疗费用的报销或补偿,以减轻医疗费用的负担。参保人员在生病住院或接受治疗时,可以通过医保报销一部分或全部的医疗费用。
  3. 失业保险:为因非个人原因失去工作的参保人员提供一定时间内的生活保障金,帮助他们在失业期间维持基本生活。
  4. 工伤保险:用于保障因工作原因遭受意外伤害或职业病的劳动者,提供医疗费用和伤残补助,甚至提供生活保障金等。
  5. 生育保险:主要为参保女性在生育期间提供一定的经济补助和医疗费用报销。

社保卡

佛山社保卡如何申领?“一人一卡”清理又是个啥? https://mp.weixin.qq.com/s/9uQ5qGOYv35BGRgs4OvzvA
没领佛山社保卡可以使用医保报销吗?可以,微信支付时会显示报销数额。
如何使用医保余额?办理实体医保卡,可以查到余额。

医保

  • 医疗保险是一种社会保障制度。通常由个人和单位共同缴纳,参保人员在医疗机构就诊时可以通过医保报销部分或全部的医疗费用。
    通过医保报销的费用是由医保基金支付的,而这个基金是由全体参保人员(包括你和你的单位)共同缴纳的资金组成的。个人缴纳的那部分医保费用只是整个基金的一部分,而报销的金额往往远超过个人单独缴纳的部分,这正是医保体系的优势所在
  • 佛山医疗保险享受指引
    1. 门诊选点:公众号-粤医保
    2. 异地就医备案
      办理条件:异地安置退休人员、异地长期居住人员、常驻异地工作人员、临时外出就医人员
      办理途径:公众号-粤医保-线上办理-异地就医备案
    3. 医保报销方式
      定点联网机构住院(?)费用:凭社保卡/医保电子凭证/身份证现场结算;未能即使结算的,先挂账后结算;无法补记账结算的,垫付费用后申请零星保险。(医保里的钱可以用吗?怎么用?
      零星报销:提供资料到参保所属医保经办机构办理
      https://ihr.midea.com/selfhelp/ihr/selfhelp/pdf?businessId=8a928ead90719d3201907b3b580d00b7&mc_widget_identifier=com.midea.msd.ihrcommonmx&scene=selfhelp_sdc&page=showPdf&type=1

住房公积金

  • 住房公积金是一种社会福利制度,而不是严格意义上的社会保障。住房公积金是国家为帮助职工解决住房问题而设立的一项长期住房储金。它由职工个人和单位共同缴纳,归职工个人所有,并在一定条件下用于购房、建房、房屋维修或者租房等住房相关支出。
  • 职工可以在以下情况下提取住房公积金:购买、建造、翻建、大修自住住房。偿还住房贷款本息(利率低)。支付房租。离职或退休后可以提取全部住房公积金。
  • 住房公积金可以断缴。如果有购房计划或其他需要公积金支持的需求,最好避免长时间断缴。
    • 可以断缴:如果你换工作、辞职、或者暂时没有固定工作,住房公积金可以暂时断缴。没有法律强制要求必须连续缴纳。一旦找到新工作或稳定下来,你可以恢复缴纳住房公积金。新单位会重新为你开设账户或继续使用之前的账户。
    • 断缴的影响
      贷款购房影响影响贷款资格,在申请住房公积金贷款时,很多地方要求申请人在最近的6个月或12个月内连续缴纳公积金。如果公积金断缴,可能会影响你申请住房公积金贷款的资格。贷款额度影响,公积金贷款额度通常与公积金的缴纳时间和余额挂钩。如果断缴时间较长,贷款额度可能会受到影响。
      影响提取条件:如果计划通过提取公积金支付房租或购房时,断缴可能会影响提取公积金的条件,因为很多地方要求提取前必须有一定的连续缴纳记录。
    • 如何减少断缴的影响:1、补缴:在新单位入职后,你可以尝试与单位协商,进行断缴期间的补缴。以恢复在断缴期间的公积金记录。2、灵活就业人员公积金:有些城市允许灵活就业人员或个体工商户自行缴纳公积金,以避免断缴。
  • 住房公积金在中国是可以随着工作地点的变更而进行转移的。通常的步骤是:在新城市的新工作单位会为你开设一个新的住房公积金账户。向新单位的公积金管理中心申请将旧账户的公积金余额转入新账户。新单位所在的公积金管理中心会联系原城市的公积金管理中心,办理资金转移。公积金转移通常需要一定时间,一旦转移完成,你的住房公积金余额将会合并到新城市的账户中。
  • 佛山公积金提取:wx公众号办理租房提取业务,选择按年/月提取,隔日到账。

个人所得税

工资条计算步骤

  1. 应发合计 = 基本工资 + 考评绩效 + 其他发放 + 福利
    2月说明:12330=3555+8445+0+330(餐补)
  2. 实发工资 = 应发合计 - 代扣代缴
    代扣代缴项:包括五险一金(专项扣除)、本月预扣个人所得税。
    2月说明::9612.2=12330-2717.8
  3. 累计预扣预缴应纳税所得额 = 累计收入 - 累计减除费用 - 累计专项扣除 - 累计专项附加扣除
    累计减除费用:每月5,000元起征点,年度累计为60,000元(如工作满12个月)。
    专项附加扣除:包括子女教育(每月2,000元/孩)、房贷利息(每月1,000元)、赡养老人(每月2,000元)等,需在个税APP填报。
    2月说明:11101.74=35710(2024.12起重新计算?) - 15000 - 6308.26(累计个人缴纳社保&公积金) - 3300, 公式逻辑:逐月累计收入及扣除项,动态计算全年税基。
  4. 扣税 = 累计预扣预缴应纳税所得额 × 税率 - 速算扣除数 - 累计已预扣预缴税额
    税率表:采用七级超额累进税率(3%-45%),按月累计收入匹配税率档位。若某月税额突增,可能是累计收入进入更高税率区间,属正常现象。
    示例:若累计应纳税所得额36,000元,对应税率10%,速算扣除数2,520元,则当月预扣税额 = 36,000×10% - 2,520 - 已缴税额。

退税条件与计算

个人所得税丨2024年个人综合所得年度汇算操作指引 https://mapmpm5.midea.com/newservicenopages/#/content/preview?id=1896853229331374081
个人的汇算清缴,就是把您2024年一整年取得的劳动收入(税法中叫“综合所得”,具体指工资薪金、劳务报酬、稿酬、特许权使用费共4项)合并计算个税,得出应纳个人所得税,与2024年实际预扣预缴的个税比较,税款多退少补。预缴税款与实际应缴税款产生差异的核心原因在于预扣预缴机制与全年综合计算的逻辑差异
预扣预缴是基于局部数据和固定规则的估算,而汇算清缴是基于完整数据和真实扣除的精准计算
建议:通过“个人所得税APP”提前核对收入明细和扣除项,利用汇算规则合法降低税负(如优化年终奖计税方式)。以下是具体原因分析:

  1. 收入结构与预扣方式的差异
    预扣预缴的“分段计算”特性 : 工资薪金采用累计预扣法,按月计算税款(逐月累加收入并匹配税率),而劳务报酬、稿酬等按固定比例预扣(如劳务报酬预扣率20%)。若全年收入波动大(如年终奖集中发放)或存在多处收入,可能导致:1. 前期预缴税率低,后期税率跳档:例如前半年收入低按3%预扣,后半年累计收入超过36,000元后按10%计税,全年汇算需补差额。 2. 劳务报酬预扣率高于综合税率:劳务报酬预扣时按20%扣税,但全年综合所得实际税率可能仅为3%或10%,汇算时可退税。
    年终奖计税方式选择的影响 : 年终奖可选择单独计税(按“年终奖/12”匹配月度税率)或合并计税(并入综合所得)。若预缴时选择单独计税,但汇算时合并后适用更高税率,则需补税。
  2. 扣除项目的动态调整
    专项附加扣除的补充申报 :预缴时未填报的专项附加扣除(如租房、赡养老人等),可在汇算时补充扣除,直接减少应纳税额。例如:租房扣除(1,500元/月):若全年未申报,汇算时补充可减少18,000元应税所得额,按10%税率计算可退1,800元。大病医疗扣除:只能在次年汇算时申报,直接影响退税额度。
    • 其他扣除项的汇算调整:如公益捐赠(需在汇算时提供凭证)、职业资格继续教育等扣除,预缴时未计入的,汇算时可补充抵扣。
  3. 收入合并的税负效应
    综合所得合并计算的税率跃升 :工资、劳务报酬等四项收入合并后,可能使全年应纳税所得额跨越税率档位。例如:单独计算时未超档:工资10万元(适用10%税率)+ 劳务报酬5万元(预扣20%但实际税率10%),合并后15万元应纳税所得额适用20%税率,需补税。多处收入叠加:从两家单位取得工资,每家均按5,000元起征点预扣,但全年合并收入超过6万元的部分需补税。
    • 稿酬的特殊计算规则:按“(稿酬收入×80%)×70%”计入综合所得,若预缴时未按此规则计算(如企业误操作)汇算时需调整。
  4. 政策与实操的特殊情形
    免税收入的误计入 : 部分免税补贴(如差旅津贴、误餐补助)若被错误计入工资,预缴时多缴税款,汇算时可申请剔除并退税。
    预缴申报的误差 : 企业可能因操作失误导致预缴税款错误(如漏报专项扣除),需通过汇算修正。

劳动合同

  1. N+1补偿的适用场景与条件
    触发条件企业合法解除劳动合同但未提前30日通知,需支付“N+1”(经济补偿金+代通知金)。
    • 具体情形包括:
    ◦ 劳动者医疗期满后无法返岗且无法调岗;
    ◦ 劳动者经培训或调岗仍不胜任工作;
    ◦ 客观情况重大变化(如部门撤销、搬迁)导致合同无法履行。
  2. 计算规则
    N:按工作年限计算(每满1年支付1个月工资,不满半年按0.5个月计算)。 N按离职前12个月平均工资计算,包含奖金、津贴等。
    +1:额外支付1个月工资(按解除合同前12个月平均工资或上月工资计算)。
    • ​月工资上限:若月工资高于当地上年度职工月平均工资3倍,按3倍标准支付且年限最高12年
  3. 员工主动离职的经济补偿可能性
    一般情况:员工主动离职无补偿。
    例外情形(企业存在过错,员工被迫离职):
    • 企业未足额支付工资、未缴社保、未提供劳动保护等(依据《劳动合同法》第38条);
    • 此时员工可主张N倍经济补偿金(无“+1”),但需书面通知并保留证据(如工资流水、社保记录)。
  4. 违法解除劳动合同的赔偿标准(2N) :若企业无合法依据解除合同(如无故辞退、程序违法、裁撤孕期员工等),需支付2N赔偿金(经济补偿金的双倍)。
  5. 实务对比与维权建议
    情形 补偿标准 法律依据 维权路径
    企业合法解除未提前通知 N+1 《劳动合同法》第40条 协商或仲裁主张代通知金
    企业违法解除 2N 《劳动合同法》第87条 劳动仲裁或诉讼索赔双倍赔偿
    员工被迫离职(企业过错) N 《劳动合同法》第38条 提交证据申请仲裁

商业保险

【当代年轻人没了铁饭碗,还能负重奔跑多久?北京二胎家庭如何转移风险?】 https://www.bilibili.com/video/BV16F4m1V7wv/?share_source=copy_web&vd_source=2cbe8cdd54a75d0c43fcdefa624d3fbe

“年纪轻的一定要买百万医疗险和意外险,还有抗癌险,关键时候真的能救命的,有余裕买个重疾险,如果生病了确证了就能拿到几十万的保额,可以作为治疗和康复期的生活费开销,医疗费有医保和百万医疗险,到时候真生比较严重的病百分之九十能报销,年纪轻买了便宜加起来一年千把块,父母没生病可以给他们买众民保和中银全名保,还有当地的惠民保三个加起来六百块不到,不看健康告知年龄大可以报销,配合医保大概能报销八十花的多甚至能报销到九十,给家里老人多套保障,不会出现得了病只能放弃的人间惨剧,如果老人没医保可以买城乡医保一年几百块”

mom:东莞农村?居民社保医保,莞家福,莞家福居民保?,midea家属保险

2025年度商业保险开始投保了~ 员工(统一投保无需美福下单)本人及任选两名家属的免费/自付费升级方案 https://mapnew5.midea.com/newservicenopages/#/content/detail?id=1902351310562877442&type=2

快速了解一个保险的7个核心要素

  1. 保障范围(核心)
    • 保什么:疾病类型(如60种重疾)、门诊/住院/手术等报销范围。
    • 特别关注:是否包含社保外费用(如进口药、质子重离子)、癌症特药清单。
    • 图片信息提示:图中“重大疾病列表”需核对乳腺癌是否被列为赔付疾病。
  2. 购买条件
    • 年龄:是否限制60岁以上?续保是否允许超龄?
    • 健康告知:是否询问癌症病史?如有,如何核保?(图片中未提及健康告知,可能宽松)
    • 等待期:生效前等待期(通常30-90天,重疾险可能180天)。
  3. 免赔额与报销比例
    免赔额:如“意外住院补贴限额100元/天”可能指单日免赔额。
    报销比例:社保内是否100%?社保外是否有比例限制?(图中“社保范围内7.5万/位”需进一步解读)。
  4. 既往症条款
    • 关键问题:乳腺癌术后治疗是否被定义为“既往症”?若属于,报销比例是多少?(图中“免检责任”可能指部分疾病免检,需核实)
  5. 保额与限额
    • 单项限额:如“意外住院补贴7.5万/位”是否够用?
    • 年度总限额:重大疾病总保额是否充足(至少100万以上)。
  6. 增值服务
    • 实用性:医疗垫付、重疾绿通、二次诊疗意见(图中未提及,需向HR确认)。
  7. 免责条款
    • 雷区排查:如“不覆盖胎液”(图片底部注释)可能指免责先天性疾病,需明确免责清单。

从报销顺序理解

  1. “社保医保”“惠民保”:基本保障,看病报销“社保范围”内的如60%
  2. 团保商业保险:企业与保险公司合作提供,一方面能够报销“社保范围”内剩余40%中的部分,一方面能保重疾住院等
  3. 百万医疗险:看病报销“社保范围”外的部分,?有患癌史无法购买,可选择众民保
  4. 重疾保:以上“医疗险”报销看病本身的费用,而“重疾险”为支付单笔保费,用于后续正常生活;需要安全告知
  5. 意外险:负责意外事故以及某些“医疗险”不涵盖的病
  6. 可以按照“医疗险”,“重疾险”,“意外险”来搭配购买,但也存在商业保险覆盖其中多种的能力

根据您母亲的情况(47岁、乳腺癌病史、已参保东莞社保及莞家福),结合健康限制和保障需求,以下是商业保险的配置建议及具体产品的分析:

一、基础保障优先级(必选)

  1. 普惠型医疗险(补充社保和莞家福)
    推荐产品:全国版惠民保(如众民保)、东莞本地惠民保(如已参保莞家福需确认既往症规则)
    适用性
    ◦ 无健康告知,覆盖乳腺癌术后治疗费用(报销比例通常为30%-50%,需查看具体条款)。
    ◦ 年保费约100-200元,保额高达300万,覆盖医保内外费用(部分产品含特药)。
    注意事项
    ◦ 优先选择支持“乳腺癌复发治疗”的产品,如众民保对复发医疗费按比例报销。
  2. 乳腺癌复发险(专项核心保障)
    推荐产品
    泰康粉红卫士:0-2期患者可投保,复发或转移一次性赔付最高50万,报销型最高100万(含41种特药)。
    太平洋粉红守护:支持0-2期患者,可选对侧乳腺癌保障,含48种特药报销,续保稳定性较好。
    适用性
    ◦ 覆盖乳腺癌复发、转移、对侧新发,报销比例100%(含社保外费用)。
    ◦ 年保费约1400-3000元(根据保额选择),等待期90天。

二、补充保障(根据预算可选)

  1. 意外险
    推荐产品:众安高危职业意外险、平安综合意外险
    适用性
    ◦ 无健康告知,保意外身故/伤残(50-100万)、意外医疗(不限社保)。
    ◦ 年保费约200-500元,杠杆率高。
  2. 团体医疗险(企业合作产品)
    适用性
    ◦ 您提到的太平洋人寿企业合作套餐,若无健康告知或宽松告知,可作为基础住院医疗补充(覆盖门诊住院费用)。
    ◦ 需确认是否覆盖社保外费用及乳腺癌复发相关治疗。

三、不推荐或限制类产品

  1. 常规重疾险/百万医疗险
    • 因乳腺癌病史,99%产品拒保或除外责任。
  2. 防癌医疗险
    • 仅少数产品允许投保(如支付宝终身防癌险),但通常除外乳腺癌责任。

具体产品对比分析

产品类型 推荐产品 核心优势 局限性 年保费参考
乳腺癌复发险 泰康粉红卫士 保费最低(1400元起),特药覆盖最全(41种) 仅限0-2期患者,续保需审核 1400-5000元
乳腺癌复发险 太平洋粉红守护 含对侧乳腺癌保障,特药清单更新快(48种) 仅限0-2期患者,保费较高 2000-8000元
惠民保 众民保(全国版) 覆盖复发治疗,含CAR-T疗法和质子重离子 免赔额高(2万),报销比例50%-80% 150-300元
团体医疗险 太平洋企业合作套餐 无健康告知,可能覆盖既往症 需确认保额和报销范围(可能仅限社保内) 企业合作价(待确认)

四、配置方案建议

  1. 预算有限方案(年保费约1600元)
    必选:泰康粉红卫士(基础型1400元)+ 众民保(200元)。
    作用:覆盖乳腺癌复发高额医疗费,补充普惠报销。
  2. 全面保障方案(年保费约5000元)
    必选:太平洋粉红守护(含特药责任3000元)+ 众民保(200元)+ 团体医疗险(企业合作)。
    可选:叠加意外险(300元),覆盖意外风险。
  3. 区分保险类型,明确赔付规则
  • 可叠加赔付的保险类型(给付型)
    重疾险:若确诊合同约定的疾病(如癌症、心梗等),不同保司的重疾险可同时赔付,互不影响。例如:投保两份50万保额的重疾险,确诊后可获100万赔付。
    寿险/意外险身故/伤残保障:身故或伤残保额可叠加赔付,但未成年人受保额限制(如10岁以下身故保额最高20万)。
    年金险:按合同约定固定给付生存金,多份保单可同时领取。
  • 不可叠加赔付的保险类型(报销补偿型)
    医疗险(含意外医疗):以实际医疗费用为上限,发票原件仅能用于一次报销。若A公司已全额赔付,B公司不再赔付;若A公司仅报销80%,剩余20%可向B公司申请(需提供分割单)。
    财产险(车险、家财险):遵循损失补偿原则,赔付总和不超过实际损失。例如:车辆全损价值50万,即使投保两份车险,最高仅赔50万。
  1. 保障范围叠加策略
  • 优先覆盖不同风险场景
    疾病+意外+身故组合:例如「重疾险+医疗险+意外险」,覆盖疾病治疗、意外伤害和身故风险。
    高低保额搭配:小额医疗险(覆盖1万内费用) + 百万医疗险(覆盖大额住院费用),减少免赔额影响。
  • 避免重复投保同类报销型保险
    • 同时购买多份百万医疗险无意义(均需扣除1万免赔额),但可搭配无免赔额的小额医疗险。
  • 注意隐性条款冲突
    • 部分医疗险限制“仅报销社保目录内费用”,若另一份医疗险覆盖社保外费用,可互补。
  1. 总结建议
    合理搭配类型:给付型(重疾、寿险) + 报销型(医疗险) + 财产险,避免同类报销险重复。
    重点核查条款:健康告知、免责范围、赔付优先级(如医疗险报销顺序)。
    动态调整保障:定期检视保单,根据家庭阶段(如生子、购房)增减保额或险种。

五、注意事项

  1. 健康告知:购买前务必确认条款中的“既往症定义”,乳腺癌相关治疗可能被除外。
  2. 报销材料:需保存医疗发票、诊断证明、用药清单等,多数产品需先经医保报销。
  3. 续保稳定性:众民保为1年期产品,不保证续保,但众安产品历史稳定性较好。

建议优先投保乳腺癌复发险(专项保障),再补充惠民保和意外险,最后根据企业团体险条款决定是否叠加。
建议通过保险顾问协助核保(如众安、慧择平台),确保理赔无争议。


投资

三、个性化投资策略建议

1. 资金配置方案(月均5000元)

类别 比例 工具示例 目的
学习投入 10% 付费研报、专业课程 知识体系构建
模拟交易 0% 同花顺模拟盘、Backtrader 策略验证
指数定投 40% 沪深300ETF(A股) 强制储蓄+市场β收益
行业ETF 30% 半导体ETF(512480) 把握结构性机会
现金储备 20% 货币基金 应对黑天鹅事件

2. 技术赋能投资的具体路径

  • 量化入门
    1. 用Python复现经典策略(如双均线策略)
    2. 开发舆情监控爬虫(抓取雪球、股吧热词)
    3. 构建多因子选股模型(参考WorldQuant Alpha库)
  • 工具推荐
    • 数据平台:AKShare(开源替代Tushare)
    • 回测框架:QLib(阿里开源)
    • 可视化:Plotly+Dash构建交互式看板

3. 阶段目标管理

  • 新手期(0-1年)
    • 目标:年化收益率跑赢货币基金(2%-3%)
    • 关键动作:完成10个策略回测、建立投资checklist
  • 进阶期(1-3年)
    • 目标:年化收益率8%-10%(同期沪深300水平)
    • 关键动作:开发自动化交易信号系统

四、风险控制工具箱

  1. 极端情况应对预案
    • 设置动态止损线(如回撤超15%强制减仓)
    • 保留3-6个月生活费的现金储备
    • 建立黑天鹅事件清单(如中美脱钩、疫情反复)
  2. 认知偏差矫正方法
    • 交易日志模板:
      1
      2
      3
      | 日期 | 操作 | 决策依据 | 情绪状态 | 事后评估 |
      |------|------|----------|----------|----------|
      | 2023-08-01 | 买入XX股 | MACD金叉 | 焦虑追涨 | 错误:未考虑成交量萎缩 |
  3. 推荐监控指标
    • 十年期美债收益率(全球资产定价锚)
    • 人民币汇率波动区间
    • 融资融券余额变化率

六、推荐资源清单

  1. 数据源
    • 国家统计局宏观数据库
    • FRED(美联储经济数据)
  2. 工具链
    • Jupyter Notebook + Pandas(数据分析)
    • TensorFlow/PyTorch(预测模型)
  3. 深度阅读
    • 《主动型指数投资》(王延巍)
    • 《量化投资:以Python为工具》(蔡立耑)

下一步行动建议

  1. 本周内注册模拟交易账户
  2. 用Matplotlib复现近5年行业轮动图谱
  3. 加入量化投资开源社区(如JoinQuant)

你的技术背景是独特优势,建议从**”工程师型投资者”路径切入,将编程能力转化为投资生产力。记住:在认知不充分时,不亏损追求收益**更重要。

美 的 Midea

08/07/24

入职第一天,熟悉运维平台,目标实现其自动化,后续参与到美的云,?
熟悉新旧平台的功能和调用关系,拆分业务需求开发步骤,编写文档,每日汇报进展,熟悉开发流程、、
软工院作为非互联网公司的非核心业务的底层平台建设部门,结果导向,组员多一年社招;)无校招培养。?

7.17 ~ 7.29

EDP培训 + MGC(头脑风暴/产品调研/拉通对齐>>技术)
T型人才(广度+深度),开发技术+产品思维->架构师
不设限,主动承担任务,机会莫名来:) take other people’s jobs and become indispensable to the team..

复杂的事情简单化(思考简化),简单的事情复杂化(做到极致)
工作就是生活,生活就是工作,不需要平衡(找到热爱的工作)
成功的百分比 = 做事 / (个人 + 做事);做事的比例越大,成功的概率越大

Allen: 向上管理?× 向上反馈,同步进展
MGC结营
融入团队?主动承担?谈论未知?如何选择自己在团队中的角色,人设??
圈子

8.17

佛山校友会迎新
“努力会发光,先有为后有位”,“头三年不要动,把这一套学会”
程序员的本质核心竞争力是什么?1.开发都是那一套 2.专精一个领域 3.meet新公司的需求 4.解决问题的能力

8.22 需求一

华为云主机开/关机/重启自动化 : mq、定时任务、公有云api、crud、、
完成第一版8.14,自测8.15,,merge request,code review,sit,测试,uat,发版8.22、、
反思、、在开发同事的指导下完成了开发,不具备独立调研和开发能力,,
缺少对产品的思考??没有对需求进行120%的思考和完成。。

8.24

顺德校友会迎新
why Midea?1.生活成本低(特别是住宿好通勤方便)2.相比下工作轻松(能够有自己的时间学习业务以外的东西)
思考自己在..年后会到什么层次(本科毕业+6y ?= 博士毕业起步)。。阶段性目标

8.27 Steven:

深入一个领域,,
先做一点功能点,然后负责一个模块,到不同系统的交互、、
多学基础,与外包的区别。。与人沟通的能力
幂等,整体设计,微服务治理,看项目源码,,
干半年就不是应届生了。社会很残酷,前两年要快速成长;思考两/五年后的情况、、
开发整个过一遍,打包,发版,,
多讨论,多问,code review
失败邮件发送:设计一个功能,,关注点,逻辑路径,通用性,,如何表述。。?! –>

9.9 并发先查后改

方法:事务+行锁【悲观锁】,避免在高并发场景下先读后写导致多个线程同时读取相同的值然后同时写入引发数据不一致的问题
测试:线程池多线程访问,打印数据,排查重复值;考虑数据库连接池配置
思考:项目部署到多节点下,则是多进程的多线程环境,需要用Redis分布式锁,或者唯一的全局数据库节点加锁;
单节点的多线程才能用synchronized?、

  • 优化:事实上,update方法会加行锁,所以直接先update后select即可,无需select…for update
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    @Service
    public class NumberService {

    @Autowired
    private NumberMapper numberMapper;

    @Transactional // 在业务逻辑层开启事务,确保整个操作是原子的
    public void incrementNumber(Long id) {
    // 查询并锁定行
    NumberEntity numberEntity = numberMapper.selectForUpdate(id);
    // 读取后进行计算并更新,保证只有当前事务可以操作该行
    int currentNumber = numberEntity.getNumber();
    numberEntity.setNumber(currentNumber + 1);
    // 更新数据库
    numberMapper.updateById(numberEntity);
    // 更新完成后提交事务,释放锁
    }
    }
    1
    2
    3
    4
    5
    6
    7
    @Mapper
    public interface NumberMapper extends BaseMapper<NumberEntity> {

    // 使用 FOR UPDATE 读取并锁定行,防止其他事务并发读取该行
    @Select("SELECT * FROM number_table WHERE id = #{id} FOR UPDATE")
    NumberEntity selectForUpdate(Long id);
    }

9.12 需求二

Azure公有云主机申请 :根据云管界面配置配齐参数发送报文到作业平台,完成自动化主机创建和标准化
对其参数,连续加班,9.9完成第一版,9.10上sit前端联调,9.11开发部分发邮件,9.12上uat,6.同步DDL&DML,7.发版,验收成功
接触运维协同,,code review,联调,,集成,部署,流水线,,

9.14

窝囊费:)120

9.26 需求三:

Azure公有云主机回收/开/关机/重启 : 调研AzureApi和测试方法,开发,,
9.23回收上sit,9.24开关机重启代码重构(原华为云方法过于通用),9.25bug毁了我的足球梦,9.26配置ngix上uat,验收
思考:自测可以 1.全流程验证 2.单独功能验证 3.考虑开发与测试环境的区别(ping的包装方法/命令行执行在开发/测试环境的区别)
后续:完善公有云开发(Azure回收配额,ip,失败邮件),后续由运维平台MOPS -> 参与到数据库开发

10.12 需求四:

任务触发式失败邮件完成,改造为工单定时任务扫描式,10.17上线
邮件通用性??工单+定时任务层面的通用,,

10.14

数据管控平台DataMars: 云管cmcloud开发功能,先提供内部服务,后到SAAS,,
InfluxDB备份恢复 1 调研 2 手工实现 3 详细文档
2-3月时间,不要求11月上线,整体设计,转正答辩
api,数据库内核?,容器,k8s
容器,登录主机,查看docker实例,操作数据库实例

10.22 K8S验证InfluxDB Cluster实例导入导出

  1. FinalShell客户端:主要用于服务器管理和运维。支持 SSH、SFTP 等多种协议,方便用户通过图形界面进行远程连接和操作。
  2. 跳板机/堡垒机: SSH连接,登录堡垒机opsec.midea.com,mip账密 + OTP验证
  3. 资产列表中选择指定环境下的主机,InfluxDB多节点部署在对应环境的几台主机上
  4. 切换用户:rouser,apps,root
    1
    rouser20@(datamars)mhpl74337-10.20.248.65 ~$ sudo su - apps
  5. K8S入门 https://zhuanlan.zhihu.com/p/32618563
    • Namespace(命名空间,是一个逻辑隔离的环境,用于资源分组和隔离) -> InfluxDB集群(可以有多个),Pod(Kubernetes的基本计算单元) -> InfluxDB集群节点(逻辑上),容器 -> InfluxDB单例(物理上)
    • Namespace:作为最顶层的资源,实现了资源的逻辑隔离。
    • StatefulSet:对于有状态的服务如数据库,K8s 推荐使用 StatefulSet 进行管理,确保每个 Pod 都有一个持久的唯一标识并提供稳定的网络标识和存储。 InfluxDB 集群中,StatefulSet 用于管理数据节点和元节点。
    • Pod 是最基本的部署单元,它是可以被创建和管理的最小部署对象。当创建一个 InfluxDB 集群实例时,StatefulSet 会用来管理 Pod 的生命周期(而不是直接创建Pod)。
    • InfluxDB 集群部署:对于一个 Namespace下的几个 Pod,这些节点会通过 StatefulSet或者 Deployment来进行管理和部署。在实际操作中,创建 InfluxDB 集群实例的 Helm Chart 或者 Operator 通常会自动化这些资源的创建过程。
    • 通信调度:K8s 中,Pod 之间的通信通常通过 Service 来进行。Service 会为一组 Pod 提供一个稳定的 IP 地址和 DNS 名称。对于 InfluxDB 集群,可能会有一个或多个 Service 来管理数据节点和元数据节点之间的通信。
    • 查看实例root密码
      kubectl get secrets -n influxdb
      kubectl get secrets -n influxdb influxdb-e73f149ff7192bd87d190-influxdb -o yaml
  6. 连接主机mhpl74337(datamars-uat的三台服务器之一),查看 influxdb 命名空间下的所有 Stateful、Pod 的状态和节点信息
    1
    2
    3
    4
    5
    6
    7
    8
    apps@(datamars)mhpl74337-10.20.248.65 ~$ kubectl get sts -n influxdb
    NAME READY AGE
    influxdb-e2cb6c913a191e56c134e-data 2/2 47d
    influxdb-e2cb6c913a191e56c134e-meta 3/3 47d
    apps@(datamars)mhpl74337-10.20.248.65 ~$ kubectl get pod -n influxdb -o wide
    influxdb-e2cb6c913a191e56c134e-data-0 1/1 Running 0 20d 10.20.205.88 mhpl74338 <none> <none>
    influxdb-e2cb6c913a191e56c134e-data-1 1/1 Running 52 (44h ago) 20d 10.20.206.129 mhpl74344 <none> <none>
    meta-0/1/2...
    可以看到,在 Kubernetes上创建了 InfluxDB集群实例,它们共用一个 Namespace:influxdb,使用 StatefulSet 来创建和管理 Pod。这些 Pod 负责运行 InfluxDB 服务,并由 StatefulSet 确保它们的高可用性和数据持久化。
    对于每个集群实例,有 2个 sts为 meta和 data,分别有2和3个复制,即2个元节点和3个数据节点 Pod,部署在3台服务器上;pod内部共用数据卷,pod之间数据不互通,部署在同一主机上的pod之间可以通过本地机器为中介复制文件。
  7. 查看 influxdb 命名空间下的 service 信息。
    1
    2
    3
    4
    apps@(datamars)mhpl74337-10.20.248.65 ~$ kubectl get svc -n influxdb
    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    influxdb-e2cb6c913a191e56c134e-data ClusterIP None <none> 8086/TCP,8088/TCP,2003/TCP,4242/TCP,25826/UDP,8089/UDP 39d
    influxdb-e2cb6c913a191e56c134e-meta ClusterIP None <none> 8089/TCP,8091/TCP 39d
    有 2 个Service,用来定义一组Pod的访问策略的抽象。它提供了一种方式,使得外部客户端可以通过一个固定的IP地址和端口访问这些Pod,而不需要关心Pod的实际IP地址和端口。Service会通过选择器(selector)将这些端口映射到后端的Pod上。
  8. kubectl exec 进入指定的 Pod(默认进入其中的第一个容器),并启动一个 bash shell;可以看到当前 InfluxDB 版本是v1.8.10-c1.1.2
    1
    2
    3
    apps@(datamars)mhpl74337-10.20.248.65 ~$ kubectl exec -it influxdb-e2cb6c913a191e56c134e-data-0 -n influxdb -- bash
    root@influxdb-e2cb6c913a191e56c134e-data-0:/# influxd version
    InfluxDB v1.8.10-c1.1.2 (git: master 529251fda5d776cf47bb0c247cf81075f2980fed, build: go1.16.15 linux/amd64)
    在使用InfluxDB进行备份和恢复操作时,通常需要在数据节点上执行相关命令(元节点上都没有influx指令。。)
  9. 进入influx命令行界面,验证身份信息;事实上,进入到influxdb实例中,便无需考虑节点,部署,,,了,直接操作数据库和数据
    1
    2
    3
    4
    5
    6
    root@influxdb-e2cb6c913a191e56c134e-data-0:/# influx
    Connected to http://localhost:8086 version 1.8.10-c1.1.2
    InfluxDB shell version: 1.8.10-c1.1.2
    > auth
    username:
    password:
  10. 数据库导出:容器层面命令,指定 数据文件和 写前日志(WAL)文件的存储目录,将指定数据库中指定时间的数据导出到指定文件。
    1
    root@influxdb-e2cb6c913a191e56c134e-data-0:/# influx_inspect export -datadir "/var/lib/influxdb/data" -waldir "/var/lib/influxdb/wal" -out "influxdb_test01_dump_out" -database "test01" -start "2024-10-22T00:00:00Z"
    数据文件复制:1、从pod1复制到本地机器 2、从本地机器复制到部署在同一服务器上的pod2(NODE: mhpl74344)
    1
    2
    sudo kubectl cp influxdb/influxdb-e2cb6c913a191e56c134e-data-1:/influxdb_test01_dump_out data/influxdb_test01_dump_out
    sudo kubectl cp data/influxdb_test01_dump_out influxdb/influxdb-e73f149ff7192bd87d190-data-1:/influxdb_test01_dump_out
    获取密码:查看对应实例的admin账密,解密data
    1
    2
    kubectl get secrets -n influxdb # 看命名空间
    kubectl get secrets -n influxdb influxdb-e73f149ff7192bd87d190-influxdb -o yaml # 看选定实例
    数据库导入:容器层面执行命令,使用admin账号,指定文件、数据库、时间戳精度
    1
    root@influxdb-e73f149ff7192bd87d190-data-1:/# influx -import -path='influxdb_test01_dump_out' -precision=ns -username='admin' -password=''
    实例导出:不加 -database,把influxdb集群实例中所有数据库的数据导出,加 -compress 导出压缩文件
    实例导入:加-compressed 导入压缩文件,本质上是先解压后倒入

11.4 Pod添加datamars-agent Container

  1. 从已有的MongoDB实例中的statefulset配置文件中,找到datamars-agent容器修改配置
    1
    2
    3
    4
    # 导出配置文件
    apps@(datamars)mhpl74337-10.20.248.65 ~$ kubectl get sts influxdb-xxxx-xxx -n influxdb -o yaml > influxdb-sts.yaml
    # 文件下载本地
    apps@(datamars)mhpl74337-10.20.248.65 ~$ sz influxdb-sts.yaml
  2. 本地编辑器打开(for convenience)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    spec:
    template:
    spec:
    containers:
    - command: # 找到datamars-agent容器
    # 配置
    image:
    name:
    volumeMounts: # volumeMounts 是在容器层面配置的,定义了容器内的挂载点
    - mountPath: /etc/localtime
    name: host-local-time
    - mountPath: /etc/mongodb-config
    name: config
    - mountPath: /log # /log 挂载了名为 log 的卷。
    name: log
    volumes: # volumes 是在 Pod 层面配置的,定义了 Pod 中可以使用的卷
    - configMap:
    defaultMode: 420
    name: influxdb-e73f149ff7192bd87d190-data
    name: config # config 卷是一个 configMap,实际路径在物理机上并不固定,由 Kubernetes 动态管理
    - hostPath:
    path: /etc/localtime
    type: File
    name: host-local-time # host-local-time 卷是一个 hostPath,路径为 /etc/localtime,类型为 File
    volumeClaimTemplates: # volumeClaimTemplates 是在 StatefulSet 层面配置的,定义了持久化存储卷的声明
    - apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
    annotations:
    ext.datamars.org/blkio.throttle.read_iops_device: "8000"
    ext.datamars.org/blkio.throttle.write_iops_device: "8000"
    creationTimestamp: null
    name: log # log 卷声明了一个 PersistentVolumeClaim,请求 50Gi 的存储,实际路径在物理机上由存储类 datamars-default-lvm 管理,具体路径取决于存储类的实现
    namespace: mongodb
    spec:
    accessModes:
    - ReadWriteOnce
    resources:
    requests:
    storage: 50Gi
    storageClassName: datamars-default-lvm
    volumeMode: Filesystem
    status:
    phase: Pending
    查看pv(集群层面的存储),pvc(pv的使用规则)
    1
    2
    apps@(datamars)mhpl74337-10.20.248.65 ~$ kubectl get pv -n influxdb
    apps@(datamars)mhpl74337-10.20.248.65 ~$ kubectl get pvc -n influxdb
  3. 添加到influxdb-data Statefulset的配置中,手动更新sts配置(导出influxdb-sts.yaml,sz到本地,修改后rz传到服务器)
    1
    kubectl apply -f influxdb-sts.yaml
    或者,直接修改influxdb-data Statefulset的配置中,:wq 保存,成功后自动更新到Pod
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    apps@(datamars)mhpl74337-10.20.248.65 ~$ kubectl edit sts -n influxdb influxdb-e73f149ff7192bd87d190-data
    statefulset.apps/influxdb-e73f149ff7192bd87d190-data edited
    apps@(datamars)mhpl74337-10.20.248.65 ~$ kubectl describe sts -n influxdb influxdb-e73f149ff7192bd87d190-data
    # 最下面可以看到事件信息
    Events:
    Type Reason Age From Message
    ---- ------ ---- ---- -------
    Warning FailedCreate 50m statefulset-controller create Pod influxdb-e73f149ff7192bd87d190-data-0 in StatefulSet influxdb-e73f149ff7192bd87d190-data failed error: Pod "influxdb-e73f149ff7192bd87d190-data-0" is invalid: spec.containers[1].volumeMounts[0].name: Not found: "conf"
    Normal SuccessfulCreate 48m (x2 over 12d) statefulset-controller create Pod influxdb-e73f149ff7192bd87d190-data-0 in StatefulSet influxdb-e73f149ff7192bd87d190-data successful
    # 或者看日志
    apps@(datamars)mhpl74337-10.20.248.65 ~$ kubectl logs influxdb-e73f149ff7192bd87d190-data-0 -n influxdb -c datamars-agent
  4. 注意以上操作只是手动修改一个Pod,要想新建Pod中的配置更新,需要通过helm chart配置__

11.11 InfluxDB服务化 :实例备份(调研&开发)

10.14-10.18:看文档,建立InfluxDB集群概念(前期已经也在看了..),建立整体框架概念(apiserver–bakserver–agent)
10.21-10.25:本地容器搭建influxdb集群×,连接服务器测试实例验证功能,了解K8S概念,手动验证实例(库级)导入导出即逻辑备份
10.28-11.01:对其需求(能做但没用户??),完成技术文档框架,开始将功能接入datamars-bakserver,了解golang开发
11.04-11.08:搭建go开发和agent项目环境,,无法理解go项目结构,尝试从bakserver侧理解task下发-接收-执行全流程
11.11:理解所有业务代码(after2weeks)发现task下发无需改动,只需适配influxdb(修改配置类和表),接着打包至sit环境打印log调试
11.12-11.15:研究pod添加container(改sts后delete pod重建),go项目构建(windows尝试配齐开发工具但有些包依赖linux环境)》。
11.18-11.27:本机wsl的ubuntu成功构建起datamars-agent,边抄边做,不用理解其框架?.. 及时请教专家
11.28-12.03:kun手改agent代码:)打包image push到dockerhub,宿主机拉取镜像后本地grpcurl调试 pod ip:port 验证功能
12.04-12.09:bakserver打日志流水线部署到uat(集群实例所在环境),通过apiserver-bakserver-agent中的日志验证全流程功能
12.10:验证通过
技术文档先行,将需求拆分成一步步,重要的是要有产出,,能汇报进度。。buffer。。好心态😇不怕叼
关注重要的事情(功能接入已有框架/理解业务逻辑×,功能验证和对齐需求√,开发卡点及时请教)
1/2时间幻想(串联已知信息且验证,对齐上下游并重复验证,本质是开发环境,业务不熟悉),1/4等回复(线上下请教+准备),1/4开发(快乐短暂)
与人沟通是重要的能力。。拉群问。。软件开发还是很残酷的。。

2025.04:重新考虑… 1 influx_inspect export只是把该pod指定数据库(或所有库)的指定时间段的分片数据(tsm&wal)导出line protocol文件,各Data-Pod数据不一致时不能代表整个实例;2 influx -import本质是将数据重新写入,前提要先恢复好shard元数据,,

12.12 年终述职

  • 大家好,那我现在开始~
    七月份入职后,我先是接触了MOPS自动化运维的开发任务:)
  • 总的来说,这五个月以来,我作为团队和开发领域的新人,得到了循序渐进的挑战和成长。了解到如何作为团队中的一个成员进行开发,能够理清一些比较复杂的业务逻辑,能够尝试进行调研和方案设计 ~
    相比于赋能团队,我觉得更多的是还我自身需要补齐能力;也许目前开发效率低,本质是对业务的不熟悉和开发技能的缺失,但是除了我觉得提升开发能力,还应该具备产品思考的能力,服务客户。我的汇报就到这里。

12.27 成长对话

  1. 本年度关键战役及成果产出
    MOPS开发任务
    1 华为云主机开/关机/重启自动化:进行了华为云api的验证并接入代码,对开发环境和流程有了基本认识,学会将需求拆分进行开发和逐步验证。
    2 Azure公有云主机申请自动化:开发初期遇到文档和会议理解上的困难,沟通后明确需要配置参数构造Azure主机申请报文,发送至作业平台完成自动化主机创建和标准化,经过与前端、运维同事协同开发上线,申请数达20+。
    3 Azure公有云主机回收/开/关机/重启自动化:区别于华为云api会返回job状态,为Azure任务设计了新的验证方式,如开机成功是能够ping通主机,重启是先ping不通后ping通,并为适配原业务逻辑进行了代码重构。
    4 公有云主机邮件发送:为公有云消息通知功能设计了多版方案,最终采用定时任务扫描工单表的方式,以工单执行状态和执行时间作为邮件发送条件,简化了发送条件且便于理解和维护,发送邮件数达40+。
    DBEngine开发任务
    1 InfluxDB备份与恢复:先进行了InfluxDB Cluster实例导入导出功能的验证,确定了先导出物理备份文件后上传OSS的技术方案,功能分别接入 apiserver,bakserver,agent 各系统,在配置开发环境及开发验证的过程中补齐了K8s、Linux等能力;目前备份功能进入联调阶段,同步开发备份集恢复功能。
  2. 面对未来1-2年的职业规划
    作为团队和开发新人,在这个阶段希望能锻炼自己的专业能力,补齐开发所需地各项能力,积累实战经验,能够快速开发需求和输出文档;而从需求开发和解决问题的经验中抽象出能力,无非就是在沟通时抓住重点,开发时做到极致,这也许就是院长所说的“复杂的事情简单化,简单的事情复杂化”;
    除了专业能力的提升,还应该具备产品侧思考的能力,对一个系统有深入的认知,能够独当一面,做到专精一个领域。
  3. 希望提升的1-3项核心能力项,计划如何提升
    1 快速学习的能力。通过自主学习/经验复用,辨别需求开发中问题的关键,快速掌握解决问题所需能力,不企图全面构建知识体系
    2 时间管理的能力。目前,需求开发中实际用于写代码的时间很少,大部分的时间用于串联和验证已知或猜测的信息,对齐上下游,这也许是因为对开发环境、业务的不熟悉和开发技能的缺失。另外,由于当前需求开发很依赖他人的讲解,做到高效提问,不耽误他人时间也是很重要的。以及要学会在开发中预留buffer,在实际开发中提高效率。
    3 精确表达的能力。描述调研方案或解释曾做过的功能时,往往没法在当时呈现所有的思考结果。在对齐需求和协同开发中,有时会抓不住重点,重复提问,效率不高。需要向同事请教如何提升这项能力。
  4. 上级总结
    24年成果:
    1)mops完成2个公有云的主机开/关机/重启自动化的能力研发
    2)完成数据库influxdb的备份和恢复任务开发
    做的好的:
    1)作为应届生有一定的主动性,对于不懂的积极学习
    2)能够在同学指导下完成工作
    待改进:
    1)技术能力需要加强和提升,需要快速学习新技能
    明确员工亟待提升的核心能力,并为其制定成长计划:需要提升代码开发基本技能,加强基础学习
  5. more thinking
    无法独立开发,效率低,代码量少;问人很正常,在群里问,卡点,同步领导;值班,锻炼解决问题的能力;长期发展,先补齐技能,有好奇心,,提高工作日效率,边工作边学习成长,,用心,真诚 :_
    阶段目标、、开发效率,高级开发,项目管理
    2024:校招,旅行,吉他
    2025:职场,矫正,足球
    【程序员如何快速成长,这几点值得重点参考,我只教一遍!】 https://www.bilibili.com/video/BV1bK4y1B7rj
    【【社区分享】程序员宝藏推荐!提升天花板!覆盖学生到架构师!】 https://www.bilibili.com/video/BV1Ta411s7ij/
    【建议收藏,高级开发如何提升产品能力!我常用的5个网站!】 https://www.bilibili.com/video/BV1y2C3YpEaL/

2025.01.16 试用期转正答辩汇报

  • 尊敬的领导、各位同事:
  • 大家好!我是蔡枫,今天非常荣幸能在这里与大家分享我在试用期的工作成果和心得。【翻页】我将从试用期工作内容、工作改进点、下季度工作计划以及问题与建议,四个方面进行汇报。【翻页】
  • 试用期工作内容
    这段时间,我主要参与到两个项目中:分别是MOPS公有云自动化和InfluxDB服务化。
    我首先接触到Mops华为云和Azure两个云厂商公有云主机的 “开/关机/重启/申请/回收自动化” 的需求,在业务熟悉的同时,进行了云主机运维功能的完善。以及,我参与到influxdb服务化开发,目前实例备份与恢复功能已开发完成,并将逐步支持其他功能。【翻】
  • ;)
  • 试用期工作改进点
    在试用期间,我意识到需要首先要提高代码能力。在需求开发的过程中,我逐渐熟悉开发环境和流程,初步掌握验证和联调方法。作为团队和开发新人,在这个阶段希望能锻炼自己的专业能力,积累实战经验,能够快速开发需求和输出文档;
    同时,我补充了运维相关的能力,学习并通过实践掌握了K8s,Linux相关知识和基本操作,为后续工作打下坚实基础。
    以及在做需求,协同开发的过程中,我增强了沟通理解的能力,学会从需求开发和解决问题的经验中抽象出能力,要能在沟通时抓住重点,开发时做到极致。【翻】
  • 下季度工作计划
    接下来,我计划完善和支持InfluxDB实例集恢复、扩容、重搭等功能,以进一步提升系统的高可用性。
    总的来说,通过Kubernetes集群和Helm Chart等实现了对InfluxDB集群的高效管理。用户可以通过DataMars控制台方便地进行实例的备份恢复和配置变更,同时支持扩容重搭以应对业务需求的变化。工作流引擎负责处理用户请求并调用相应的Helm Chart模板、通用或专有的apiserver接口等,确保操作的自动化和一致性。相信有了前期开发经验,我能够更快的进行后续的开发产出。【翻】
  • 问题及建议
    最后,希望提出一些建议。首先,在新人指引方面,我认为前期培训缺少技术方面的指引,可能导致新员工在后续开发中理解比较费劲,上手难度大。建议组织开展包括开发流程、开发环境搭建、代码规范等内容的培训,确保新员工能够快速融入。其次,关于文档落实,我发现一些技术文档内容不够详尽,导致无法自行定位问题,需要频繁联系文档编写者。对此首先我应该提高自己的文档撰写水平,确保能够让人快速理解整体流程,找到问题所在,并及时更新文档内容。
  • 总结(的)来说,在各位同事的帮助下,我在试用期间得到了快速成长,收获颇丰。【翻页】以上就是我的汇报内容。感谢各位领导和同事的聆听和支持。我相信,在大家的共同努力下,我们的工作会取得更大的进步。谢谢大家!

1.16 InfluxDB服务化 :备份集恢复

1.02:不上心
1.14:开发uat自测(sit没测)完成,开发分支合dev提测,最后合main上线
1.16:SD/GA测试发版失败,恢复工作流需要人工介入验证,存在问题 1地址没有动态配置!! 2漏配接口/审批流变更
1.21:发布修复版本,生产延后

2.7

复工
当前阶段的关键,,交付能力,,工程能力是练出来的
熬夜是没有对明天的期待、、-》培养兴趣转移注意力、,books
程序员。技术。不要只看自己的一亩三分地。。开源项目
工作以外;:给自己创造需求,根据需求解决问题,在解决问题上配合看书,,从而在某一细分领域有知识图谱,有一技之长,用系统性的看书代替cdsn查找零散的解决方案
“下班的时间放在哪哪里就有提升”
副业?;web3;licai

dataMars服务架构理解

  1. apiserver:1 datamars管控接口 2 mcloud回调接口 3 properties获取apiserver服务自身暴露的域名端口+controller接口拼接url
  2. apiserver-{engine}:引擎专有服务,工作流(其实是workflowclient处理)中调用不同服务暴露的接口(common,,influxdb,,apiserver)
  3. bakserver/metaservice/xx-agent:其他服务,由rpc/grpc暴露服务
  4. 调用架构:api、v1、v2
  5. 服务架构:通过Kubernetes集群和Helm Chart等实现了对InfluxDB集群的高效管理。用户可以通过DataMars控制台方便地进行实例的备份恢复和配置变更,同时支持扩容重搭以应对业务需求的变化。工作流引擎负责处理用户请求并调用相应的Helm Chart模板、通用或专有的apiserver/k8srepository接口等,确保操作的自动化和一致性。

todo 手画图

2.18 InfluxDB服务化 :本地变配

2.6-2.16:现有InfluxDB集群实例(只考虑data节点)的CPU、内存和存储资源已无法满足需求,需对资源配置进行扩展,以提升性能和稳定性。通过修改StatefulSet中cpu、memory配置并删除Pod触发StatefulSet控制器重建data节点Pod以应用新配置,通过修改data节点Pod对应的pvc中storage配置以触发pv的存储扩容(只能增加),实现资源变配(本地变配)
2.17:前端对齐开发,准备进入sit联调
2.18:插入需求“meta节点自定义创建”
2.28:整合已知信息已读代码->无法理解多节点类型实例如何发起变配,应该果断求助
3.3-3.10:改造influxdb集群为父子实例模式,改配置,传参调试,适配已有功能,考虑存量实例的影响
3.11-3.13:data变配基础上开发meta变配,云管订单遇到配额不匹配问题,上线延期下周
3.14:跨团队求助无果,请求协助,,新需求着手开发
3.17:搁置,开发新需求
3.18:实操tidb复现该“问题”,考虑转向与云管沟通。。
3.27:发版 =》InfluxDB父子实例改造/本地变配/节点/实例重启

2.22

正畸, 启动
读书时无所事事的日子,今天拔完牙和妈妈一起冰敷等待的日子,还有多少
刚开始普遍很难,易的是背八股,难的是落实和推进
如何跳出这个困境?如何跳出程序员行业?30岁,35岁
熬夜是因为没有对明天的渴望。但是在晚上的当下,有很多事情想做😿
喜欢一个人独处,是因为不想自己长期以来形成的情绪稳定被打破。害怕形成亲密关系,有时无法融入团体😿

2.27 InfluxDB服务化 :实例创建自定义Meta节点规格

2.18:本需求作为其他需求开发的前置条件
2.19:apisever打log上uat调试创建流程,从已部署分支git branch新分支以免影响正在使用者
2.21:提sql变更 1 dataspace提工单 2 直接进入各环境metadb(其本身为容器部署的mariadb服务) 3 某些配置项可通过datamars控制台修改
2.25:云管运营端商品信息变更,考虑是否影响存量实例;;1 云管释放旧实例将计价报错->调datamars管控接口释放/发版前释放旧实例 2 可以发起工单但无法下单->手动修改配额发起工单后过云管审批
2.27:发版流程、、代码合master,流水线打包使用(发版版本)部署,sql变更(定时,增加条件避免误订正),云运营变更(改一次console-cloud即各环境共用)
Steven👨‍🦲:裁员,残酷,危机感,,工作就是生活的很大一部分

  1. meta规格,配置到instance_spec,engine = “InfluxDBMeta”
    | 场景 | 规格代码 | CPU 核数 | 内存 (GB) | 存储 (GB) | 网络带宽 |
    |————–|———————–|———-|———–|———–|————|
    | 小型集群 | influx-meta-small | 2 | 4 | 50 | 中等 |
    | 中型集群 | influx-meta-medium | 4 | 8 | 50 | 高 |
    | 大型集群 | influx-meta-large | 8+ | 16 | 50 | 超高 |
    | 特大型集群 | influx-meta-xlarge | 16+ | 32 | 50 | 超高 |
  2. apiserver实例创建逻辑
    meta信息通过request.getExtraJson()传入,ClusterInstanceService#initClusterInstanceExtend保存在cluster_instance_extend;initClusterInstanceParams能适配保存meta节点的param吗(iops,连接数,influxdb不考虑?)
    不考虑在cluster_instance要新增字段体现meta规格信息
  3. apiserver-influxdb工作流完成实例创建,pv,sts,helm,install,node,instance
    获取meta规格信息,构造临时value文件,生成用于安装InfluxDB集群的Helm命令并执行
  4. 以上只是在k8s环境中实现了自定义meta规格创建,事实上应该参考tidb,将influxdb集群改造为父子实例模式,逻辑上把data/meta节点区分开,进行变配/更新meta信息..
  5. more to concern? param创建,变更?extend父子实例数量不一致?实例创建流程,sts,副本,顺序。。

3.3 阶段目标 :入职半年 ..

deepseek:数据库方向是一个值得长期投入的领域,尤其适合对系统底层感兴趣的程序员。你的现有经验(运维+K8s)可成为切入云数据库或分布式数据库的跳板。建议以​“运维需求驱动内核学习”​为短期目标,逐步掌握分布式一致性、存储引擎等核心技术,同时通过开源贡献和项目实践构建技术影响力。=> https://yuanbao.tencent.com/bot/app/share/chat/c6b48985efa0c1101e5c6ae18c867724
rong teng:在midea得到的成长是显著的;(身兼开发运维多职,具体求职情况如何?)数据库方向有些窄;(作为senior求职需要专精时显得窄?作为基础能力学习可行?)应届生可以提转方向,转团队;以招聘市场心仪岗位的需求作为努力发展的方向!?

3.13 AI编程助手:codetip

代码可以看作是一种特殊的prompt,用于引导AI生成高质量的代码提示;开发者有目的地编写代码,实是为AI提供清晰的意图上下文。
代码补全 需要让AI理解意图;技巧 提供具体示例,遵循规范和语义化,规范注释;“内联对话”
代码对话 本地工程理解@workspace,RAG增强
最佳实践

todo 体验cursor

3.17 InfluxDB服务化 :实例/节点重启

3.17:简单需求,父子workflow + k8s资源控制器
3.18:接口配置:接口信息查看mariadb已有的相同接口,其他信息参考influxdb自身的其他接口;前端联调完成
3.19:提测,发版:发版分支一周内进行 1 代码扫描-安全扫描 2 安全-软件成分-Web漏洞-灰盒,解决漏洞;代码仓库设置发版分支,史诗中关联所涉及仓库,检索其发版分支的扫描报告,手动关联web漏洞测试报告,质量门禁达标以通过安全卡点

3.24 从零实现Kubernetes环境下的InfluxDB自动化登录工具:Bash与Java的跨语言实践

  • 背景与需求分析
    在云原生环境中,InfluxDB集群常以StatefulSet形式部署于Kubernetes。运维人员需要频繁执行以下操作:
    动态选择特定Data Pod;解密存储在Secret;通过交互式命令登录数据库。
    手工操作存在效率低下、易出错等问题。本工具通过Bash脚本整合Kubernetes CLI、Java加解密等能力,实现全流程自动化。
  • 技术方案设计亮点
    1. 混合编程模式(Bash+Java)
      核心难点:GCM解密在纯Bash环境难以实现(openssl版本低(不会升级…) 没有aes-256-gcm工具)
      创新方案:编写Java脚本,动态生成Java解密类(图1),通过Java标准加密库实现AES-GCM解密
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      # 生成随机类名避免冲突
      CLASS_NAME="InfluxDecryptor_$(mktemp -u XXXXXXXXXX | tr -dc 'a-zA-Z0-9')"
      # 编译并执行Java代码
      if javac "$TEMP_JAVA"; then
      auth_output=$(java -cp /tmp ${CLASS_NAME})
      echo ""
      echo "$auth_output"
      echo ""
      else
      echo "Java编译失败"
      return 1
      fi
      凭证安全处理机制:
      • 使用临时文件存储解密代码(TEMP_JAVA="/tmp/${CLASS_NAME}.java"
      • 执行后立即清理编译产物(rm -f "$TEMP_JAVA"
      • 避免敏感信息持久化
    2. 跨语言参数传递
      动态生成的Java脚本中,选择标准输出+格式控制方案:
      1
      2
      System.out.println("USERNAME:" + username.trim()); 
      System.out.println("PASSWORD:" + new String(decrypted).trim());
      多行输出解析难题
      1
      2
      # 错误示例:初始方案采用`IFS`分割导致变量截断
      IFS=: read username password <<< "$credentials"
      优化方案:bash脚本中,使用sed精确提取java脚本输出,通过正则表达式过滤前后空格,避免不可见字符影响
      1
      2
      3
      4
      5
      6
      7
      8
      credentials=$(get_auth $1) # get_auth()动态生成java解密脚本并多行输出
      if [ $? -ne 0 ]; then
      echo "解密失败,无法登录"
      exit 1
      fi
      # 提取用户名和密码(处理多行输出)
      username=$(echo "$credentials" | sed -n 's/^USERNAME://p' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
      password=$(echo "$credentials" | sed -n 's/^PASSWORD://p' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
    3. 交互式Pod选择器
      1
      2
      3
      4
      5
      6
      7
      8
      9
      function select_data_pod() {
      # 过滤带data标签的Pod
      PODS=$(kubectl get pod -n $NAMESPACE | grep "data" | awk '{print $1, $6}')
      # 构建交互式菜单
      select pod_option in $PODS; do
      SELECTED_POD=$(echo $pod_option | awk '{print $1}')
      break
      done
      }
    4. 传递方案对比:
      方案 优点 缺点
      文件存储 实现简单 存在安全风险
      环境变量 进程内可见 长度受限
      标准输出 无持久化风险 需严格格式控制
      网络传输 适合分布式 增加复杂度

      本项目完整代码已开源,读者可通过GitHub仓库获取最新版本。在Kubernetes运维领域,通过灵活组合各类工具实现自动化,是提升效率的关键路径。

3.28 InfluxDB服务化 :节点迁移 / 重搭

3.28:需求分析->将pod迁移到集群的另一个资源充足的node上,并且恢复数据以及集群功能(元数据)
3.31-4.1:存量实例问题处理,, 建议客户使用改造后的influxdb实例,存量实例释放/启停/重启等功能遇到问题 =》未考虑好适配
4.2-4.7:出方案 1 sts指定亲合度规则以在指定node重建pod和pvc 2 开源influxdb-cluster功能不完全支持,考虑从分片副本层面恢复数据
4.8-4.10:数据恢复的主要思路=》从健康节点的分片副本copy-shard恢复出迁移节点原有的所有分片副本,?质疑->恢复过程中健康节点的分片副本持续写入的增量数据能否恢复??
4.11:考虑创建第3个Data-Pod替代迁移节点(从仍健康的迁移节点上迁移数据)× ->应该认为原节点完全不可用(相当于节点重搭了)设计方案参考其他数据库产品;;
4.14:推方案不动..自验证copy-shard达到预期效果,但无法解答原理,,自测方式还需模拟实际场景,多线程写入。。
4.15:写bash脚本批量写,开多终端模拟多线程,分片副本达70M+大流量2000point/s写 =》copy-shard恢复出分片副本与健康节点持续写的副本md5值不一致,恢复副本export文件小,猜测丢失数据
4.17:InfluxDB Data节点迁移方案评审:先迁移后逐个恢复分片数据。已验证在分片副本大小70M、写入数据达2000point/s的情况下直接copy-shard会导致增量数据丢失,考虑在copy-shard前先执行truncate-shards截断热分片(集群中所有写入最新数据的分片,截断后关闭写入,变成冷分片),并在所有Data节点上创建该分片的新热分片副本,也就是在迁移节点上恢复了全部原有分片的新热分片副本,最新数据写入这个副本,然后再逐个从健康节点上的冷分片副本copy-shard恢复出分片的历史数据(迁移前分片副本原有的数据&迁移过程中未能写入的数据),该分片数据完全恢复;自测符合预期
4.18-4.21:开发。发现原checkPodRebuildReady接口有时不符合预期,执行influxd-ctl指令(硬写成String在代码中)有时失效(meta no leader..),经常需要手工介入。。
4.22:提测
4.23:InfluxDB开源版可靠性不确定,,社区版,单节点,,开发,值班暂停
官方文档 https://influxdb-v1-docs-cn.cnosdb.com/influxdb/v1.8/introduction/install/
开源influxdb-cluster源码 https://github.com/chengshiwen/influxdb-cluster

Data节点迁移方案

  1. 重启所有meta节点,避免后续执行influxd-clt指令时报错“no leader”
  2. 记录待迁移Data节点上的分片副本信息
  3. 迁移节点,sts加affinity节点调度规则,重建pod和pvc,完成后恢复sts
  4. 分片数据和元数据完全丢失,backup工具缺失,考虑逐个恢复分片副本
  5. 迁移节点重新加入集群 influxd-ctl remove/add-data
  6. 截断热分片truncate-shards(集群中所有写入最新数据的分片),在所有Data节点上创建该分片的新热分片副本,也就是在迁移节点上恢复了原有分片的热分片副本,新数据写入这个副本
  7. 再从健康节点上的冷分片副本copy-shard恢复出分片的历史数据(迁移前分片副本原有的数据&迁移过程中未能写入的数据),该分片数据完全恢复
  8. 检查分片恢复情况

故障矩阵: 架构 => 2 data 3 meta 副本因子为2

  1. 挂1个data -> 节点迁移、重搭
  2. 挂2个data -> 备份恢复
  3. 挂1个meta -> 未知
  4. 挂两个meta -> 未知
  5. 挂三个meta -> 未知

4.14 DB值班开始 ; )

DBCLOUD开源DB报警群(实例),DBEngine告警群(机器),致命告警->数据库值班告警处理群,MariaDB/MySQL/MongoDB/PostgreSQL 常见问题,,

  • MariaDB容器数据盘使用率过大
    1.异常内容:容器数据盘占用率超过90%
    2.问题定位:
    1)/var/lib/mysql 目录下存在大量临时文件(如 #sql_1_44.MAD,大小达185G)
    2)show process 查看未提交的长事务(WITH RECURSIVE 查询和 Sending data 状态,确认这些递归查询正在生成大临时表)持有临时表资源,导致文件无法自动清理。
    3.处理方案
    1)KILL 15443008, 15443009, 15443010; // 终止进程(替换为实际ID)临时kill了超长事务连接,临时文件自动清理了(/var/lib/mysql挂载点空间得到释放)
    2)联系用户优化sql
  • MariaDB实例备库IO线程停止
    1.告警内容
    实例 IO 线程停止.通常由于无法连接到主库.
    2.问题定位:
    1)服务可用性->观察到发生主从切换,发生时间符合告警情况
    2)kubectl get pod -n mariadb -Lrole -Lhealthy->从库(原主库切换而来)健康为no
    3)kubectl descirbe 从库pod,观察到mysql container发生terminated,OOMKill,,
    4)监控指标:内存缓慢提升->考虑扩容,暴增->dataspace诊断看慢sql
    3.处理方案
    1)备库重搭
    2)联系用户扩容/优化慢sql

4.22 2025成长对话 & 6.9 年中总结

  • 制定2025年度重点工作计划。
    快速开发InfluxDB服务化需求,持续优化已有功能;深度熟悉开源数据库,确保提供稳定服务。对齐其他数据库产品,了解用户实际需求,多方面考虑设计方案。做好值班任务。

  • 希望提升的1-3项核心能力项,计划如何提升。
    1 深入技术栈学习。阅读InfluxDB源码,学习数据库架构设计,K8s应用课程等,掌握高频业务场景的原理和运维技巧。
    2 高效合作开发的能力。在全面思考,明确需求后开始开发,遇到卡点快速解决。

  • 面向未来1年的职业规划。
    本岗位沉淀
    在这个阶段希望提高自己的工程能力,能比较全面地思考设计方案,快速开发和交付需求;还应该具备产品侧思考的能力,对一个系统有深入的认知,能够独当一面,做到专精一个领域。

  • 工作成果
    1.InfluxDB服务化体系构建
    完成父子实例模式改造,新增InfluxDBMeta规格体系,实现节点级独立变配能力,为后续节点重启、迁移奠定基础;
    针对Data节点迁移提出 “热分片截断-冷副本恢复”双阶段法,通过多线程大流量写入压力验证(2000 points/s),解决开源工具增量数据丢失问题;
    参与数据库运维工作。
    2.NBU备份自动化开发
    支持备份平台自动化运维需求,开发基于Ansible的客户端安装脚本,整合NBU API,实现备份申请自动化;
    开发备份域配置管理界面(增删改查+JSON字段模糊查询)

  • 能力提升
    在InfluxDB服务化需求开发中锻炼了“场景抽象-方案验证”的能力,从寻找开源社区方案到定制化能力开发(如备份集恢复、节点迁移及数据一致性保障),梳理故障矩阵(如单Data宕机、多Meta宕机的应对策略);在NBU备份自动化需求开发中能够快速上手Ansible脚本,复用已有能力,与用户及时沟通并完成开发。

  • 存在不足
    数据库开发方面需要积累技术深度,全面考虑方案并推动评审;自动化运维需求开发可以积累解决方案,缩短交付周期。

4.23 Mops需求:NBU备份自动化

4.25-5.8:手动验证全流程+调通API,分阶段做,卡点及时同步到群聊.. 官网找接口文档/厂家提供,postPolicies接口参数调不好,就先手动设好用get查出来构造requestBody..
5.9-5.13:理清自动化接入和改造方案(先看一期代码,考虑接口和表能否复用),主动拉评审会议
5.14-5.16:开发及时理清需求原型和改造点,开发备份域配置管理界面
5.19-5.23:重难点=》作业平台下发备份客户端安装ansible脚本改造,根据传参when指定不同task,实现在target主机安装指定平台的client,expect实现交互式流程
5.26-5.29:NBU备份申请自动化开发,实现BackupNbuService(备份平台NBU涉及代码,构造RestTemplate调API);备份域配置“增删改查”,分页,模糊查询,@Transation处理先删后插/先改后改/先删后删。。延期->0605
6.3:自测=》页面上发起请求获得requestBody/通过postman调用本地起的后端服务,调试=》注释排查法/计算器debug
6.4:发sit,延期->0612;完善todo
6.5:自测,业务验收,ddl&dml(注意StringEncryptor加密的密钥随env变化!!) 发版,存在问题待完善
11.13:ToB客户验收(产品化环境开发、、接入客户环境、、)

  1. 统一运维平台:就是接各种需求,把主机创建、备份等操作自动化
  2. Ansible入门:脚本在特权机上,指定targetIp执行,,playbook为入口,roles/tasks实现具体逻辑,,安装client注意预检查,常量写在var文件,脚本写在flie/script.py通过scp传到target机器执行
  3. CRUD基本功:1. 分页,baseMapper.selectPage(new Page<>(page, size), getQueryWrapper(req)) 2. 模糊查询,queryWrapper.eqIfNotNull(BackupConfigPO::isDeleted, 0).likeIfNotNull(BackupConfigPO::getConfigKey, condition.getBackupRegion()) 3. 模糊查询条件涉及表中text类型字段的内容为json,本质还是处理wrapper,queryWrapper.apply(“JSON_SEARCH(config_desc, ‘one’, ‘%” + req + “%’, NULL, ‘$.req’) IS NOT NULL”);

6.12 智能体人才认证(一级)

0. ChatGPT的基本原理及应用实践分享
  • what is 大语言模型
    流式输出(逐字计算概率),基于Transformer神经网络(本质上一个Encoder+Decoder结构,自然语言 ⇄ 机器理解)
  • why ChatGPT
    除了卷大模型(参数量)&大数据量,有着更好的交互原因:1 指令微调? 2 基于人类反馈的强化学习
  • 提示工程 Prompt Engineering
    提示词尽量简单、明确,最好完整描述以下关键要素:1 指令 2 上下文 3 输入数据 4 输出指示
    提示词使用技巧:1 明确提出(不)应该做什么 2 提供输出的格式提示 3 使用特殊符号指令将需要处理的文本分开 4 增加示例,少样本提示 5 增加任务角色(Role)或场景
  • 应用场景实践
    本地知识库问答:从本地知识库构成的文本向量库中搜索相关知识+用户问题 =》一个提问(增强Prompt 如:“基于以下知识:{text1}…{textN},回答:{question}”)=》 LLM(如 ChatGLM2、GPT-3.5)读取该 Prompt结合自身语言能力生成最终回答;模型参数提供语言能力,但不存储动态知识。语言模型的“理解能力”本质是参数化的统计规律,通过海量通用文本训练获得。专业领域适配需针对性选择微调或 RAG 策略,二者互补而非互斥。当前技术趋势是:通用大模型作“引擎”,领域知识库作“燃料”,Prompt 工程作“方向盘”,三者协同实现高效、低成本的专业化智能问答。
1. 学习 LLM
  • 大语言模型 LLM 的“理解能力”来源:参数、训练与概率生成
    1. 60亿参数的本质
      参数是什么?神经网络中神经元连接的权重值(浮点数矩阵),例如 ChatGLM2-6B 的 60 亿参数即其网络权重总量。
      参数如何产生?通过海量无监督预训练:模型从数万亿 token 的通用文本(网页、书籍、百科等)中学习语言统计规律。例如:GPT-3 训练数据:45TB 原始文本 → 过滤后 570GB,包含近万亿 token;训练目标:预测文本中遮蔽词(如 “猫喜欢抓__” → “老鼠”)或续写句子。
    2. 参数如何实现“理解”?
      概率建模:LLM 本质是概率生成器。给定输入文本,模型计算下一个词的概率分布(如 “天空是___” → “蓝色”概率 80%,“绿色”概率 0.1%);
      上下文编码:通过 Transformer 的自注意力机制,模型捕捉长距离依赖(如代词指代、逻辑关联);
      知识内化:训练中高频出现的知识(如 “水的沸点是 100°C”)被编码到参数中,形成“通用知识库”。
    3. 训练成果与参数的关系
      训练完成后的参数 = 固化后的语言规律与知识表示;
      生成过程:根据输入 Prompt 的语义,激活相关参数路径,按概率生成符合语言习惯的文本。
  • 专业领域模型训练:微调 vs. 知识库增强
    1. 全参数微调(Full Fine-tuning)
      方法:在领域数据上继续训练模型,更新全部参数(如用医疗文献训练 ChatGLM2);
      效果:模型深度内化领域知识,生成更专业、连贯的文本;
      成本:需大量领域数据(GB 级)和 GPU 算力(如 8×A100 训练数天)。
    2. 高效参数微调(PEFT)
      方法:仅训练少量新增参数(如 LoRA、Adapter),冻结原模型参数;
      优势:节省 90% 算力,适合中小机构;
      适用场景:领域术语适应(如法律条文格式),但无法新增未训练过的知识。
    3. 知识库增强(RAG)的定位
      核心价值:无需训练模型,直接注入动态更新的领域知识(如企业最新产品文档);
      局限:依赖检索质量,复杂推理能力受限于 LLM 本身。
  • DeepSeek 之所以能广泛回答各领域问题,并非因为对所有领域都做过“专门训练”,而是通过大规模通用预训练 + 领域增强技术 + 智能调度机制实现的;
    1. 基础:海量通用预训练(广度覆盖)
      DeepSeek 的底层模型(如 DeepSeek-R1)在训练初期使用数万亿 token 的互联网公开文本,覆盖科技、教育、历史、文化、生活、基础学术等广泛领域。
      效果:模型能对大多数常识性问题生成合理回答,类似一个“受过通识教育的聪明助手”。
    2. 增强:垂直领域优化策略(深度强化)为提升专业领域表现,DeepSeek 采用以下技术实现“泛中求精”:
      混合专家模型(MoE):模型内部划分多个“专家子网络”(如医疗、法律、编程等),根据问题自动激活相关专家;
      领域微调(Fine-tuning):对金融、法律、医学等专业领域,用高质量数据二次训练模型,优化参数
      检索增强生成(RAG):对动态知识(如实时政策、企业数据库),通过外部知识库检索最新信息,再生成答案;
    3. 调度:智能路由与知识管理
      动态路由机制:用户提问时,模型自动判断问题类型,分配至: 通用知识层(如“水的沸点是多少”);专业模块(如“心肌梗死的最新诊疗指南”); 外部检索(如“2025 年光伏产业新政策”)。
      知识更新与纠偏:用户反馈可修正错误答案(如律师指出法律条文解读偏差); 结合知识图谱持续更新事实库,减少“知识过期”问题。
    4. 用户建议:如何获得更专业回答?
      明确领域身份: 提问时声明“以金融分析师身份,分析光伏产业趋势”,引导模型调用专业模块。
      开启深度思考模式: 对逻辑问题(如数学、编程),勾选“深度思考(R1)”提升推理质量。
      补充专业资料: 上传领域文档(如论文、手册),用 RAG 增强答案准确性。
      微调定制专家: 企业用户可通过 LoRA 微调,训练专属领域模型(如“医疗问诊助手”)。
2. 大模型提示词工程基础
  • 提示词基本要素
    1. 指令:想要模型执行的特定任务或指令
    2. 上下文:包含上下文信息,引导模型更好地响应
    3. 输入数据:用户输入的内容或问题
    4. 输出指示:指定输出的类型或格式
  • 提示词工程进阶技术
    1. 少样本提示:可以作为一种提示词,以启用上下文学习,我们在提示中提供演示以引导模型实现更好的性能。
    2. 链式思考(CoT)提示:提出问题的同时提供自己的推理方法,供LLM学习参考
    3. 检索增强生成(RAG):如本地知识库问答。从本质上讲,RAG包括一个检索组件、一个外部知识数据库和一个生成组件。整体流程:RAG需要从外部知识数据库中获取文档,然后将这些文档与用户的查询一起被传输到LLM,用于生成响应
    4. 自动推理并使用工具 (ART):?接到一个新任务的时候,从任务库中选择多步推理和使用工具的案例。在测试中,调用外部工具时,先暂停生成,将工具输出整合后继续接着生成。
    5. 自我反思(Reflexion):?自我反思是一个通过语言反馈来强化基于语言的智能体的机制。
      • 在高层次上,自我反思将来自环境的反馈(自由形式的语言或者标量)转换为语言反馈,也被称作 self-reflection,为下一轮中 LLM 智能体提供上下文。
      • 这有助于智能体快速有效地从之前的错误中学习,进而提升许多高级任务的性能。
3. 如何从0-1开展Prompt工程项目
  • Prompt就是给AI的指令,引导大模型生成响应回答。
    进阶例子:“现在你是一名xx专家,以下是xx内容,你的任务是对内容进行xxx,让我们一步一步做:1. 做/不做xx 2. 以json格式输出… 3. …”
  • 什么是Prompt工程?
    是业务服务应用大语言模型的中枢,用于释放LLM的能力,包括 1)单个任务的Prompt撰写调试 2)多个任务Prompt的设计组合
    如:撰写短视频文案 =》 1. 分析热门文案 2. 结合商品信息生成文案
  • Prompt工程开展方式
    根据生成的可行性与效果,明确对模型的输入、输出目标,经设计/调试后,生成效果达成业务目标后,固化为应用服务。

6.20 一个尝试:生成编程指令Prompt

  • 你是一个资深编程助手,擅长根据用户诉求生成可执行的编程指令。让我们一步步做:
    1. 将用户诉求拆解为清晰、可执行的原子化步骤。
    2. 注意环境适配(例如 Linux/macOS 环境优先使用 Bash/Python,Windows 环境优先使用 PowerShell)以及进行包依赖的检测。
    3. 考虑错误处理,如网络请求需设置超时(例如 ‘timeout 3’)
    4. 输出规范,代码必须包含完整可执行结构和注释(每20行至少1个注释)
    5. 按照以下格式返回:{步骤拆解:””,生成程序:””}
    6. 不受示例语言的限制,选择最适合的语言实现。
  • 这是一个示例AI问答
    输入:写一个能够在Linux环境使用的脚本,检测对指定IP和端口是否连通。
    输出:
    {
    步骤拆解:
    1.参数检查:验证输入参数格式(IP 端口 或 -f 文件)
    2.端口测试:依次尝试 nc → telnet → /dev/tcp 三种方式(3秒超时)
    3.批量处理:支持从文件逐行读取 IP 端口(跳过空行和注释)
    4.结果输出:直接显示开放/关闭状态
    生成程序:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    #!/bin/bash -e
    # 端口检测工具v2 | 支持: Linux/macOS/Windows(WSL)
    # 基础依赖: nc > telnet > /dev/tcp

    config_timeout=3 # 全局超时可配置

    # 函数: 环境预检
    check_dependencies() {
    # 检测网络工具链
    local tools=(nc telnet)
    for tool in "${tools[@]}"; do
    if ! command -v "$tool" &>/dev/null; then
    echo "! 缺少 $tool, 启用降级模式" >&2
    return 1
    done
    done
    return 0
    }

    # 函数: 端口检测 (带双超时)
    test_port() {
    local ip=$1 port=$2
    # 方案1: nc (Linux/macOS)
    if nc -z -w "${config_timeout}" "$ip" "$port" 2>/dev/null; then
    return 0
    # 方案2: /dev/tcp (跨平台)
    elif timeout "${config_timeout}" bash -c "cat < /dev/null > /dev/tcp/${ip}/${port}"2>/dev/null;then
    return 0
    fi
    return 1
    }
    # 主流程
    [ $# -lt 2 ] && echo "用法: $0 IP 端口" && exit 1
    check_dependencies || echo "! 使用基础检测模式" >&2

    if test_port "$1" "$2"; then
    echo "✅ $1:$2 开放"
    else
    echo "❌ $1:$2 关闭" && exit 3
    fi
    }
  • 这是用户的正式诉求
    (输入用户诉求。)

6.27 Mops需求:负载均衡变更自动化

6.27:页面流程理解+看“申请”自动化代码->考虑改造点,找api,输出文档
6.30-7.4:需求对齐,减少开发量的机会,,对于依赖项的变更(healthCheck->ResourcePool-VirtualServer)采用“蓝绿发布”=》先增后删
7.5-7.9:开发完成
7.10-7.11:自测,前端发起一次请求F12取payload / 后端接口处打印入参 + 按需修改 =》构造入参,走通流程,只需关注新加的代码(无关逻辑如校验/审批代码可以先注释掉。。)
7.14:变更成功后回滚。。手动修改+提sql同步配置;思考=》是不是可以直接另提一次变更,或者另外提供回滚接口,,总之此时回滚和前一次变更已经没有关联
7.17:上线。修复 1 管理员节点自动带出尽可能多参数 2 支持定时执行 3 思考:checkChangeSuccess()方法期望同步response,但方法里调API返回fail会隔10s重复十次,就是一直fail的话接口会隔100s才返回数据,假如加了一个定时任务扫描出待变更工单列表,用for循环执行change()并且各调用了checkChangeSuccess(),会发生什么,for循环卡住?”springboot项目,写了一个变更c…”点击查看元宝的回答
https://yuanbao.tencent.com/bot/app/share/chat/qqYiHTHYRWDv
7.29:支持定时执行,注意避免同一个工单被多次扫除(未完成变更后状态->EXECUTED),注意调度任务下发到本地节点,可能由于代码版本不同造成“灵异事件”
10.16:支持变更页面上的所有参数
10.30:支持回收自动化
11.13:优化提交工单时校验逻辑,避免重复补工单(按需增加存表字段&管理端加编辑后门)

  1. f5理解:F5 BIG-IP 是业界主流的硬件/软件负载均衡解决方案。配置好负载均衡后,一个请求从客户端到后端服务器的生效流程涉及多个关键环节,其核心是​​客户端访问域名 → DNS解析至F5的VIP → F5转发请求至Pool Members → 后端处理并返回响应
  2. Mops服务架构。。用户提交工单-> iflow审批流-> 回调/前端调接口-> 传入xxTicketVo-> convert成Dto/Po处理业务逻辑
  3. 蓝鲸。。统一运维平台竞品
  4. 自动化运维开发总结:工单,,提效,,用户,,,

6.28 Alibaba Java开发手册学习

1. 计算机基础

2. 面向对象

解析值。。序列反序列parse,,JSONNode,,

3. 代码风格

  1. 魔法值 => enum
  2. 变量一般以小驼峰格式命名,但有一种特殊情况:定义类成员变量时,特别是POJO类中,针对布尔值类型的变量不要以“is”开头,而是将数据表中的“is_xxx”字段映射到POJO类中的属性“Xxx”(如is_deleted =》Deleted)
  3. 文档注释 /** */ 加上创建和修改时间,写在代码上方,, Idea怎么配置??

4. 走进 JVM

5. 异常与日志

  1. where to throw Exception?who to solve?how solve?
    如果异常在在当前方法的处理能力范围内且无需透出,就直接捕获异常并处理;否则向上抛出,由上层方法或框架来处理。
    如果在方法内部处理异常,需根据业务场景定制处理,如重试、回滚(还有 ticketDetail.setExecutionStatus(xxEnum.FAIL) 返回)等操作;如果向上抛出异常,需要在异常对象中添加上下文参数、局部变量、运行环境等消息,便于排查问题。
    考虑设计业务逻辑,无论在哪一步终止业务,都能让外界感知此时的状态,并保留错误信息(ststus,log)
  2. 异常分类
    • Error(致命异常),不可控错误,如StackOverFlowError、OutOFMemoryError
    • Exception(非致命异常)
      • checked异常(受检异常)例如:IOException, SQLException。
        • 无能为力型,如SQLException,只好保存现场人工介入
        • 力所能及型,如发生非授权异常可跳转权限申请页面
      • unchecked异常(非受检异常)是运行时异常,继承自 RuntimeException,更像是由 业务逻辑可能导致的异常
        • 可预测异常,如IndexOutOfBoundsException, NullPointerException,应该提前做好边界检查而不是抛出
        • 需捕获异常,如Dubno框架进行RFC调用时产生的超时异常DubboTimeoutException,客户端不能因服务端异常导致不可用,可以重试或降级处理
        • 可透出异常,如Spring框架中抛出的NoSuchRequestHandingMethodException,框架会自行将异常映射到合适的状态码如404
  3. throws关键字用于声明一个方法可能抛出的受检异常(checked)。BusinessException 通常是一个运行时异常,也就是非受检异常,不需要在方法签名中用 throws 声明(显式捕捉和处理),因为它通常表示业务逻辑错误,而不是程序错误。非受检异常的设计目的是让开发者在编写代码时不必显式地捕获或声明它们。
    但是,仍然需要确保在适当的地方捕获和处理,特别是在应用程序的边界层(如控制器层)进行统一的异常处理。??
  4. ​​防御式编程,可以让方法返回null,,防止空指针异常(NPE)上调用方的责任,需要事先判断
  5. 需定位报错行数 → 必须打印 e​​(传入异常对象)会输出完整的堆栈(e.printStackTrace())跟踪,包括类名、方法名、文件名和行号。
    ​​仅需错误描述 → 使用 e.getMessage()​​(适用于前端提示或自定义消息)。
    1
    2
    log.error("查询VirtualServer信息异常:"+e.getMessage(), e);
    throw new BusinessException("查询VirtualServer信息异常:" + e.getMessage());

6. 数据结构与集合

7. 并发与多线程

8. 单元测试

9. 代码规约

。。


7.16 Mops 深度学习———暨Java开发体系构建

Java如何处理一个请求 https://yuanbao.tencent.com/bot/app/share/chat/crOguvwf38jw
mops架构熟悉 “如何深入了解当前负责的java项目,在i…” https://yuanbao.tencent.com/bot/app/share/chat/bsqucYK8K9bJ

MOPS 统一运维平台

打造主机、网络、存储等运维一键操作,支持申请、变更、回收等常见场景,实现工单下发、流程审批、策略下发的逻辑,集成平台API、脚本下发、定时调度、CMDB能力,保证流程清晰、节点可控、异常告警。。
负责。。网络管理模块开发,发版小组,值班
竞品。。蓝鲸研发运维技术PaaS体系
产品化。。定制化功能

Mops

网络管理模块。。增删改查。。AI code
技术实现:多平台用策略模式,加注解实现定时任务调度?
解决问题:并发。。

CMDB

配置数据库
mongodb、Elasticsearch
运维事实库,,与mops数据同步,订阅。。
数据重复。。问题排查

Job

作业平台,特权机+脚本下发
运维入口

Agent

自动化运维=》LLM作为“大脑”负责思考和规划,MCP等框架提供标准化的“工具库”,而强大的权限与安全体系则扮演着“交通警察”和“紧箍咒”的角色。这三者的有机结合,使得Agent既能智能地帮我们一步步完成复杂任务,又能被有效地约束在安全、可控的边界之内,从而真正成为一位可靠的数字助手。
Serval raises $52M in funding. Learn More https://www.serval.com/updates/series-a
Spring AI Alibaba 1.0 GA 正式发布,Java智能体开发进入新时代 https://developer.aliyun.com/article/1666891

7.17 Mops & CMDB发版

“一个Java系统开发完了,是怎么跑起来…” https://yb.tencent.com/s/jj0KGxxEGgzU
“IDEA调试、线上运行,Maven、SpringCloud…” https://yb.tencent.com/s/GB2sYz5WPHbB
集成,部署 “所谓的微服务实际上是怎么部署的呢…” https://yuanbao.tencent.com/bot/app/share/chat/gt96bRkSxuos
K8S&微服务部署方案 “k8s和springcloud是如何关联…” https://yuanbao.tencent.com/bot/app/share/chat/H2FtlSdK24y1

MOPS 开发,测试,发版流程

  1. 开发阶段
    • main:生产环境稳定分支,仅用于发布,禁止直接修改。
    • develop:开发/测试/发版分支,功能合并主干。前一个feature/v1.1.0发版完成后,拉出最多下两个版本的开发分支,如 bugfix/v1.1.0和 feature/v1.2.0,发版完成后合入线上分支和下一个版本分支。
    • feature/xxx:团队开发各自从develop切出的功能分支,开发完成后合并回去,发sit联调,uat验收,发版。
    • bugfix:main切出的紧急修复分支,修复后合并至main和当前develop。
  2. 测试阶段
    • SIT(系统集成测试):前后端联调测试环境,验证功能集成与基础流程。
    • UAT(用户验收测试):预生产环境,业务方验证业务逻辑。关键点:数据与生产环境隔离但配置一致,避免环境差异问题。
  3. 发版准备
    • 发版材料:包含需求清单,DDL&DML,配置变更清单。提交变更实施文档、代码质量报告、版本号(从最新git记录的Copy Revision Number)
    • SQL变更:提变更单,先DDL后DML,设置发版窗口执行,记录到db文件上传git。
    • 针对本次变更的配置备份、数据备份,确保有完整的回滚步骤。
  4. 上线验证
    • 发版分支打Tag(如feature-v1.33.0,相当于是一个快照,后续再合代码要打新tag)
    • 持续集成(指定tag,发版前提前集成)
    • 检查提的sql是否变更成功(提醒先到uat执行一遍)
    • 持续部署,可分批部署到多节点,减小用户影响(提前到uat部署一遍)
      • 灰度发布:先切10%流量验证,逐步全量。
      • 蓝绿部署:并行两套环境,切换流量实现零宕机。
    • 流水线:集成+部署
    • 发版验证:避免业务高峰期发版,异常=》监控平台搜“error”排查,以及先回退旧版本(集成旧tag部署)
    • 发版成功:发版分支合到main和下一个版本分支,SQL变更提交到MOPS_SQL
  5. 事件管理
    • 事件指导致或可能导致服务中断或服务质量下降的任一事态
    • 以恢复业务为第一要务,72h内进行根因查找与5C闭环

CMDB 部署指令

  1. 下发介质(jar包)
    将服务的可执行文件(通常是一个 .jar )下发目标服务器。这个 .jar 文件是通过构建工具(如 Maven 或 Gradle)打包生成,包含了应用程序的所有代码、依赖库和资源文件。
  2. 停止旧服务
    ps aux | grep ${package_name} | grep java | grep -v grep | awk '{print $2}' | xargs kill -15
    停止正在运行的旧版本服务,释放端口和资源。ps aux:列出所有进程。grep ${package_name}:过滤出与服务相关的进程。kill -15:优雅地终止进程,避免强制终止(kill -9)可能导致数据丢失或资源未释放。
  3. 检查进程
    确认服务进程是否已经成功停止。ps -ef:列出所有进程及其详细信息。grep ${package_name}:过滤出与服务相关的进程。
  4. 备份文件
    在部署新版本之前,备份旧版本的 .jar 文件和相关配置文件,以便在新版本出现问题时可以快速回滚。
  5. 下发 OneAgent(监控工具)
  6. 配置服务(生成配置文件)
    通过 Shell 脚本动态生成服务的配置文件(如 application.yml),用于定义服务的端口、文件路径、Redis 配置等。可以根据环境(如开发、测试、生产)动态调整配置。
  7. 启动服务
    nohup /usr/bin/java ${C_CMDB_XXL_JOB_EXECUTOR_ONEAGENT_OPTS} -Xms8g -Xmx8g -jar -Dspring.config.location=${package_path}/application.yml -Djasypt.encryptor.password=abcdefg ${package_path}/${package_name}.jar > ${package_path}/${package_name}.log 2>&1 &
    启动 Java 服务,并将日志输出到指定文件。
    nohup:允许服务在后台运行,即使关闭终端,服务也不会停止。
    -Xms8g:设置 JVM 的初始堆内存为 8GB。
    -Xmx8g:设置 JVM 的最大堆内存为 8GB。
    -Dspring.config.location:指定 Spring Boot 的配置文件路径。
    -Djasypt.encryptor.password:指定加密配置的解密密码。
    ${package_path}/${package_name}.jar:指定要运行的 .jar 文件。
    日志输出:> ${package_path}/${package_name}.log:将标准输出重定向到日志文件。2>&1:将标准错误输出重定向到标准输出。
  8. ps检查服务是否启动成功

新增微服务

“springcloud微服务架构里,每个微服务是单独开发,部署的吗,如何互相发现、调用?如果要新增一个微服务,要做什么工作?有没有“主服务”的概念,所有微服务都要记在主服务的配置文件中?”https://yb.tencent.com/s/oL2XPesIhuCx

7.18 MOPS & CMDB运维日志

Helloworld

运维人员 -> 办公电脑 -> 访问入口 -> 堡垒机(安全审计核心) / 跳板机(简易通道) -> 内网 -> 物理机 / Linux后台(应用载体)

Linux基本命令:
netstat ; top; awk ; dstat; iostat; lsof; free, df;uptime;dmesg ;dig ; nslookup

vim/vi的基本快捷命令(gg, shift + g, :n ; dd, :%d ; yy, p ,u等)

终端的一些快捷命令(ctrl + a; ctrl + e)

Zookeeper磁盘占用过高的SOP

  1. 告警确认
    • 监控告警内容:磁盘使用率>80%
    • 初步排查:通过跳板机连接CMDB主机(FinalShell + SSH)逐层定位,确认Zookeeper目录为占用源头(如/apps/zookeeper/v2)
  2. 清理旧日志,并且再次运行 df -h 确认使用率下降。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     # 确认分区使用率
    98 2025-07-18 17:38:17 df -h
    # 逐步排查子目录 tab自动补齐路径
    99 2025-07-18 17:38:29 du sh /apps/svr/*
    100 2025-07-18 17:38:38 du sh /apps/svr/zookeeper-3.4.6/*
    101 2025-07-18 17:38:44 cd /apps/svr/zookeeper-3.4.6/data
    106 2025-07-18 17:39:16 du -sh *
    107 2025-07-18 17:39:22 cd version-2/
    # 分析日志文件(发现日均61MB未清理)
    108 2025-07-18 17:39:26 ll
    # 删除两个月前的日志 检查效果
    109 2025-07-18 17:39:52 find . -type f -name "snapshot.*" -mtime +60 -exec rm -f {} \;
    110 2025-07-18 17:39:57 ll
    112 2025-07-18 17:40:03 df -h
    123 2025-07-20 21:50:41 history
  3. 告警解除
  4. Zookeeper日志管理优化
    配置自动清理:zoo.cfg中启用参数 autopurge.purgeInterval=24(每24h清理),autopurge.snapRetainCount=7(保留7个快照)
    日志轮转,集成Logrotate:配置日志按大小/时间切割并压缩:/etc/logrotate.d/zookeeper 中设置 daily, rotate 30, compress
    自动化清理脚本:编写定时任务,每月清理旧日志(保留30天) => 0 3 * * * find /apps/zookeeper/version-2 -mtime +30 -delete

ops-subscribe微服务磁盘占用过高

  1. Java服务(devops部署)堆积日志的情况与中间件(zookeeper是eops部署/apps/svr目录)有所差异
  2. 清理多余日志
    1
    2
    3
    4
    5
    6
    7
    8
    9
    987    2025-12-04 17:13:46   df -h
    991 2025-12-04 17:15:44 du -sh /apps/devops/*
    992 2025-12-04 17:16:04 cd /apps/devops/ops-cmdb-subscribe/
    993 2025-12-04 17:16:12 du -sh *
    # nohup部署命令中指定的服务日志清空掉(但其实还有一份备份)
    994 2025-12-04 17:17:10 echo "" > ops-cmdb-subscribe-1.0.log
    # Java服务本身输出日志(application配置)
    996 2025-12-04 17:24:27 cd /apps/devops/log/ops-subscribe/2025-12-04/
    998 2025-12-04 17:24:39 ls -alh

CMDB回调并发量大导致MOPS飙升CPU

  1. 根本原因:回调任务包含查询接口,请求返回慢,并发大导致??cpu飙升,后续请求直接卡住,服务挂??不是io型任务开多线程没用
  2. 临时方案:1)关闭回调任务,积存任务消化完即可 2)重启mops服务
  3. 优化:1)优化cmdb查询接口,加索引 2)避免并发大?。缓存,,
  4. 研究。。。

CPU高:

  1. 内存fgc导致 —针对进程 oom?
    先dump,下载heap文件
    jmap -dump:live,format=b,file=heap.hprof 1651260
    通过Eclipse Memory Analyzer (MAT)工具分析heap文件
  2. 线程导致
    找出排查cpu高的线程对应的方法:
    1)top。找出对应的高cpu的pid
    2)top -Hp pid。打印出pid里的线程,找出对应的cpu高的线程tid
    3)jstack -l pid > jstack.txt。打印对应的进程堆栈信息
    4)printf “%x\n” 。找出对应16进制的线程id
    5)vi jstack.txt。搜索第4步的线程id,看其方法
  3. 机器资源不足。。

CMDB消费视图偶现API Runtimeout

1、调cmdb域名http://cmdbuat.midea.com/ops-data-access/view/direct,偶现“the upstream server is timing out”,nginx报错但不一定其本身出错
2、调网关http://10.16.115.110:7004/ops-data-access/view/direct,偶现“ZuulException”并且时间都是1min,怀疑是下游ops-data-access服务出错
3、直接调服务ip:port上的数据连接器接口:http://10.16.64.39:7119/view/direct,两个ip,发现其中这一个不行,怀疑是这个节点服务挂了/进程起来了但服务没起来,重启nohup java…,jps检查
=》思路:CMDB组件很多,逐步排查,一般是提供接口的服务本身出错,如果是nginx/网关出错的影响面会更大

8.1 Mops需求:DNS变更自动化

8.1:梳理变更场景,4种记录+2种平台,拆解为每种记录只有增删改三种操作,一步步实现即可
8.2-8.10:大假,昆明-大理-贵阳-深圳
8.11-8.15:收集+验证现状,还需拉会议评审
8.17:后续每天定 每日计划
0818:DNS变更,确定所有api/script(√),方案评审(×)
0819:DNS变更主流程(80%)
0820:DNS变更主流程(90%)
0821:管理端加失败工单入库按钮,当日上线
0822-0824:DNS变更开发
0825:DNS变更自测(√),CMDB安全组件安装流程确定(×)
0826:DNS变更sit(√),CMDB安全组件安装(×)
0827:DNS变更全流程报错机制完善,1.流程节点失败就报错 2.ticket.setExecutionLog(+=新日志) 那么可以全程操作溯源、、成功就直接加,失败throwE在catch里加e.getMessage()
0828:涉及定时任务调度/异步的要考虑UserContext空指针;上线
0908:一键回退主流程开发
0916:一键回退上线
1016:全面支持mx+txt申请变更回收,通过workspace让AI“模仿”cname自动化来实现
1030:支持智能解析,todo->cmdb字段回写+移动审批带出
11.18:产品化需求->Windows DNS自动化下发,适配进常规DNS下发流程(midea生产和产品化环境通过前端开放不同入口,实现执行不同部分代码,下发不同platform的DNS配置)
1202:变更一键回退优化(直接挂回原pool),支持申请回退(即回收掉)

  1. 当F5设备被配置为该域名的权威DNS服务器时,nslookup查询才会最终指向它。
    一个域名的权威DNS服务器信息(NS记录)是由其上一级域名注册商管理的(比如.com域名的注册商)。当你在注册商处将域名的NS记录指向你的F5设备(或其管理的DNS服务)后,一个完整的解析流程如下:
    本地输入 nslookup www.yourdomain.com =》本地DNS服务器会从根域名服务器开始,一路查询到.com服务器,最终获知你的域名的权威DNS服务器是你的F5设备 =》本地DNS服务器随后向你的F5设备发起查询,并获得F5上配置的IP地址(VIP)返回给用户。
  2. 如果不指定记录类型(直接 nslookup example.com),默认查询的是A记录。要查询特定类型,需使用 -qt=类型参数
  3. DNS与负载均衡(F5)的配合
    用户访问 app.example.com-> DNS解析返回F5的VIP(如 203.0.113.10) -> 用户请求到达F5 -> F5根据预设的负载均衡算法(如轮询、最小连接数等)将请求转发给后台的Web服务器池(如 10.1.1.101, 10.1.1.102)

8.31 use Workspace

  1. 基本介绍
    Workspace是一个基于云端的代码编辑环境,由Cursor提供支持。Cursor是一个AI驱动的代码编辑器,集成了Claude等先进的AI模型,为开发者提供智能编程辅助。在这个环境中,您可以编写代码、获取AI辅助、管理项目并执行基本的开发任务。
    与IntelliJ IDEA等传统IDE相比,Workspace/Cursor有以下主要区别:
    运行环境:Workspace运行在云端服务器上,而非本地机器
    资源位置:代码、依赖包和运行环境都位于远程服务器
    功能界面:相比完整IDE功能较为精简,但集成了强大的AI辅助能力;更简洁,专注于代码编辑和AI交互,类vscode
  2. 问答模式
    edit:结合本地rag,针对代码结构和业务逻辑,返回与工程相关且与上下文相关的答案
    chat:纯AI对话,回答仅针对上下文相关内容,不涉及对工程的理解
    agent:智能体的“大脑”与“手脚”,AI Agent的核心目标是​​将自然语言指令转化为一系列具体的、可执行的操作​​,直到任务完成。它不再是简单的聊天或代码补全,而是一个具备自主性的系统。实现从​​任务规划与分解,​​工具调用与执行,​​到自我验证与迭代。适合用来完成相对复杂的任务如:代码重构,错误修复(单文件用edit模式即可),自动化任务(实现文件批量操作、脚本生产)
  3. 规则&交互
    • AI规则:设置个人、工程规则,使AI输出遵循个性化要求;优先级:系统规则>用户规则>工程规则
    • MCP:连接的“通用协议”,可以理解为AI世界的​​“USB-C标准接口”​​。在MCP出现之前,每个Agent想要连接一个新工具(如数据库、GitHub API),都需要进行大量的定制化开发,而MCP定义了一套统一的通信规范,工具开发者只需按照此标准将工具封装成独立的​​MCP Server​​,任何支持MCP协议的Agent都可以“即插即用”这些工具,极大地降低了开发难度并促进了工具生态的繁荣。
    • “/”加run,fix,explain,/CR审查;“@”加devops中的需求、缺陷、任务至chat,、;“#”设置引用知识库
  4. 开发流程
    • 版本管理:图形化操作,或直接用git指令——git branch -a查看所有本地/远程origin分支,git checkout -b feature/xx origin/feature/xx从远程分支拉出本地分支,git branch -vv查看本地&远程分支关联情况
    • 配置Maven:ctrl+shift+p->打开setting(ui)->配置path to settings.xml 、依赖包会被下载到远程服务器的Maven本地仓库
    • 安装Extensions(最接近IntellijIdea2022.3.2的主题->Darcula Theme_v1.18.1_Rafael Renan Pacheco)
    • 设置启动参数和环境变量:在.vscode/launch.json加配置”configurations”: [{“xx”:”yy”}],相当于idea里edit Run/Debug Configuration
    • 运行/Debug:1)终端输入运行命令 2)chat输入/run,回答中返回可执行命令。点击执行
    • 本地调试:Postman发请求到https://caifeng7-31579-.devops.midea.com/xx
  5. AI coding实践
    • 从单纯的Programmer转为AI的协作伙伴,提供足够清晰的开发方案,让AI在充分理解后生成代码
    • 让AI参考现有资源:已有代码、API文档,以及建立和使用知识库;也可以通过MCP读外部文档
    • 拆解任务,逐个完成,分而治之,,
    • 尝试约束AI行为,明确输出要求,,配置工程规则,让AI了解项目(chat->setting->配置rules.md)
    • 复用交互模式,优化开发流程
  6. 快捷键
    Ctrl+F: 在当前文件中查找
    Ctrl+Shift+F: 全局搜索
    Ctrl+P/shift*2(安装idea快捷键插件): 查找文件
    Ctrl+Shift+P: 打开Command Palette
    Ctrl+I:生成代码建议
    Ctrl+B/Ctrl+左键:跳转类
    Ctrl+alt+B:跳转实现类
    Ctrl+J/Ctrl+`(反引号在tab键上面):打开终端窗口
    Ctrl+alt+J:打开chat框

10.20 OBCA准备

MySQL 实战 45 讲 (https://time.geekbang.org/column/intro/100020801)

  1. 不是要背下所有东西,而是在构建体系后,能快速回忆起来
  2. 一条sql查询如何执行?客户端-> Server层: 连接器-(-查询缓存命中则直接返回)词法/语法分析-优化器(执行计划生成,索引选择)-执行器(操作引擎,返回结果)-> 存储引擎(存储数据,提供读写接口)
  3. 一条sql更新如何执行?把原数据行从硬盘读到内存(或者在缓存命中)-> 写新数据到新行 -> 引擎将新数据更新到内存并且把这个update操作记录到 redo log(InnoDB独有物理日志->“在某个数据页上做了什么修改”,保证事务的​​持久性 Durability,提供 ​​crash-safe​​ 能力)此时redolog处于 prepare 状态随时可以提交事务 -> 执行器生成这个操作的 binlog(Mysql Server层实现的逻辑日志->“给 ID=2 这一行的 c 字段加 1 ”,用于​​主从复制​​和​​数据恢复​,如时间点恢复)并且写入磁盘 -> 执行器调用引擎的提交事务接口,引擎把刚刚写入的redolog改成提交commit状态,更新完成(二阶段提交以保证两份日志保持逻辑一致)-> 两份日志都成功写入磁盘后,被修改的数据页(脏页)并不会立即写入磁盘,而是由 MySQL 在“后台”选择一个合适的时机异步刷盘。
    ​”redolog是如何配合binlog工作的?”https://yuanbao.tencent.com/bot/app/share/chat/vVRlFaO0o3sg
  4. https://time.geekbang.org/column/article/68963 事务隔离。事务就是要保证一组数据库操作,要么全部成功,要么全部失败,InnoDB在引擎层支持事务。
  5. 索引。MySQL中索引是在存储引擎层实现的。InnoDB 使用了 B+ 树索引模型,所以数据都是存储在 B+ 树的数据模型中的。每一个索引在 InnoDB 里面对应一棵 B+ 树,N叉树的N以整数字段为例差不多是 1200,树高等于4的情况下就能够存储很多数据,以减少单次查询的磁盘访问次数。根据建立索引的字段不同,索引类型分为(1)主键索引,叶子节点存的是整行数据(2)非主键索引,叶子节点内容是主键的值,还需要回表到主键的B+树二次查询。
  6. https://time.geekbang.org/column/article/69636 根据业务需求建索引,包括了覆盖索引、前缀索引、索引下推,,在满足语句需求的情况下, 尽量少地访问资源是数据库设计的重要原则之一

OBCA 认证 (https://www.oceanbase.com/training/obca)

^^

11.20

冬藏春生.团队对话-职业生涯教练.孙小红 刚刚好找出这张照片,刚好这一天的头发服帖,刚好朋友拍出了不错的构图,脸上也满是生气,好像有勇气冲到一个新的level 但最近我都在跑医院,想着每个周末只是在修复自己的身体和精神,到了工作日又要回去摧残自己..这有什么意义吗 为了回归到这张照片,想了半天得出一个结论是,不断地修复自己到一个刚刚好的状态就是生活的意义,吗 有点虚无,说了但像什么也没说,什么又是一个刚刚好的状态呢 也许是我刚好能够面对相机,刚好拍下了这张照片 也许人置身生活的洪流,只能不断修复自己 也许可以找到互相修复的人

11.30 CMDB 项目运营

深度参与策略

接手CMDB,,从做需求->做系统 https://yuanbao.tencent.com/bot/app/share/chat/920NVAbsqwtm
最大化CMDB项目的学习价值,, https://yuanbao.tencent.com/bot/app/share/chat/SzQrsGlsuz88

  • 理解CMDB系统本质与行业实践
    • 核心价值:CMDB(配置管理数据库)是IT服务的“中枢神经”,存储所有配置项(CI)及其关系,唯一事实库,支撑运维自动化、变更管理等场景。
    • 主流竞品参考:ServiceNow CMDB,企业级SaaS方案,强在ITSM流程集成。腾讯Blue King。开源方案:iTop、CMDBuild。
    • 自研系统关键模块:数据采集 –> 数据建模 –> 关系拓扑 –> API服务–> 可视化平台
  • 通过CMDB项目深挖技术栈,Java底层实践场景:?
    • 高并发设计:自动发现引擎需处理海量设备扫描(学习Netty异步IO、Disruptor队列)。
    • JVM调优实战:配置项关系计算需避免Full GC(分析G1日志,调整Eden/Survivor比例)。
    • 分布式事务:CI数据跨服务同步(基于Seata AT模式或消息最终一致性)。
  • 云原生技术落地
    • 微服务架构:Apache(SSO登录)-NGINX(反向代理+静态资源)-eruka(服务发现)-zuul(网关分发请求)-各微服务-mongodb主数据库-es(同步数据用于检索)
    • 容器化部署:将CMDB模块拆分为微服务,用Docker打包,K8s调度(学习Pod滚动升级、HPA弹性伸缩)。
    • 可观测性建设:集成Prometheus监控API延迟,Grafana展示拓扑关系健康度。
  • 以CMDB为杠杆撬动技术纵深:CMDB是运维体系的“核心数据枢纽”,其复杂场景(数据一致性、分布式调度)是修炼Java底层和云原生的绝佳沙盒。
  • 📊 项目经验如何写入简历
    简历模块 平庸写法 高价值写法(量化+技术关键词)
    项目经验 参与CMDB需求开发 主导CMDB数据模型重构,设计弹性CI架构,支持200+动态属性扩展,模型变更效率提升40%
    技术亮点 使用Spring Cloud开发API 基于Quartz+Netty开发高并发自动发现引擎,单节点支持5000+设备/秒采集
    业务价值 提升系统稳定性 通过拓扑影响分析模块,故障定位时效从30min缩短至5min,年止损运维成本200万+

💡 简历筛选口诀:“技术深度×业务影响”双突出——避免写“增删改查”,聚焦架构设计、性能优化、跨系统集成。

CMDB 交接分享

  • 整体理解
    CMDB(配置管理数据库)是IT基础设施与应用配置项的集中存储库,为运维、自动化、各业务系统提供数据支撑。
    数据组织:以配置项(模型就是配置项相当于表)的形式组织各类数据,支持通过模型管理灵活变更字段,通过关系拓扑进一步展开数据间的关系。
    数据使用:支持白屏化检索、维护数据,导入导出,支持查看历史版本,涉及”管理员”字段(管理员信息维护数据字典)自动发起变更流程;对外提供数据连接器(配置项增删改查)、消费视图能力,通过API读写数据;数据订阅服务通过监控oplog触发回调任务;数据审计(数据传入传出、消费视图审计,数据归档)
    数据更新:通过定时任务+采集脚本实现配置项信息的自动发现。
    数据治理:数据质量(自动校验异常数据),IP治理,EAM对账(定时任务拉取数据获取差异并展示)
    系统管理:支持配置用户角色以获得不同权限,对界面上的用户操作有审计记录。
  • 服务运维
    内部部署:devops主机部署微服务,数据库mongo、es由DBA运维
    日常运维:看监控数据;从监控查到服务部署的主机,登陆,查看java服务,重启?
    私有化部署:微服务组件、数据库都以镜像打包,服务化部署,k8s运维
  • 系统架构与组件
    1. 用户通过访问CMDB域名解析到F5资源,经过F5跳转后进入系统。Apache主要负责单点登录功能,配置文件中可以设置跳过认证的URL。
    2. Nginx作为反向代理,将请求转发到网关。网关通过注册中心获取服务IP,并根据负载均衡策略选择微服务节点。前端资源部署通过流水线将打包文件放到指定文件夹,静态资源无需进程管理。
    3. CMDB主服务(OPS_CMDB)处理大部分页面请求,代码结构复杂,接口查询逻辑需通过页面查找。MongoDB :主数据库,集群模式,一主一从一隐藏,读写分离。
    4. 数据连接器服务提供外部API,用户通过登录获取token后访问。查询和写入数据需经过参数验证和限流控制(默认1000条)。数据入库前会经过多层级校验(如选项值、关联字段等),采用责任链模式实现。高频接口涉及大量衍生查询,需谨慎修改。消费视图提供(多)配置项数据关联+指定字段查询能力。
    5. 全文检索服务对接开放搜索,查询时通过缓存获取用户可访问的索引列表,支持高亮和加权排序。mongodb数据通过monscache同步es,根据模型字段值检索。
    6. 数据订阅服务通过MongoDB的OP Log捕获数据变更,发送到Kafka后由订阅服务消费并触发后续逻辑(如离职资产交接)。数据质量服务通过配置告警任务,筛出异常数据
    7. 定时任务服务通过注解开发新任务,采集代理服务通过Kafka下发脚本并分批处理返回数据。自动采集:xxljob->ops-syn-task->kafka->ansible->执行消息回调->kafka->syn-task入库
    8. 用户中心服务处理登录初始化,表头配置服务管理页面表格显示字段,均为低改动频率服务。
    9. 组件包版本管理:测试环境用snapshot可随意修改,生产环境需更新release版本号并重新打包部署。
    10. 远程Debug需在启动项添加参数,连接UAT环境IP和端口,适用于本地无法模拟的场景(如采集任务)。

CMDB 智能助手

https://www.vertice.cn/solution-details/26737.html
llm+rag+mcp

12.11 2025年度总结&成长对话

  • 个人贡献
    1. InfluxDB服务化建设(今年上半年)
      • 支持InfluxDB实例备份与恢复能力
      • 完成InfluxDB父子实例模式改造,新增InfluxDBMeta规格体系,实现节点级独立变配、重启能力
      • 针对Data节点迁移提出 “热分片截断-冷副本恢复” 双阶段法,解决开源工具增量数据丢失问题
    2. MOPS功能开发(下半年主要负责)
      • NBU备份自动化:支持基于NBU的文件、程序、归档与RMAN类型备份申请自动化下发,开发备份域配置管理界面
      • 负载均衡自动化:支持基于F5的负载均衡变更、回收自动化,完善提单校验、实时检测能力,流程中自动带出配置项
      • 域名解析自动化:全面支持基于F5的A, CNAME, MX, TXT类型的申请、变更、回收自动化与一键回退能力,支持“管理员配置+用户执行”两阶段下发(把从前管理员手中的下发权限交到用户手上)
      • Windows Dns:支持基于Windows Server的A, CNAME类型记录的申请、变更、回收自动化,在客户环境验证
      • 运营数据:任务数 、自动化下发数 、自动化率
    3. CMDB开发运维(最近交接)
      • 熟悉CMDB功能与运维场景,日常支持业务方数据运营
      • 治理CMDB表记录,同步到业务系统中(优化用户体验)
      • 调研CMDB智能助手,支持自然语言交互(初步设想实现基础的资源查询功能,后续支持数据统计、分析、甚至图表生成,灵活使用CMDB中的数据)
  • 团队赋能
    • MOPS需求, InfluxDB服务化设计文档输出(以及一篇数据库运维的文档)
    • 人肉提醒关注开发人效分和AI代码生成数(有人说可以写个脚本来做,我想了下也是可以实现的)
  • 服务客户
    • MOPS响应用户群问题,实现业务方需求和优化点,产品化客户答疑
    • CMDB值班运维,支持业务方运营
  • 制定2026年度重点工作计划。
    1、MOPS功能优化
    负载均衡自动化:支持一键回退能力,完善流程中配置项自动带出的能力。
    域名解析自动化:完善提交工单时的自动校验能力,避免因平台记录与实际配置不一致导致变更异常。
    2、CMDB项目运营
    负责日常开发运维,支持业务方数据运营,治理历史数据。设计开发CMDB智能助手,利用AI工具赋能,初步设想是支持自然语言交互和提供简单的数据查询能力。
  • 希望提升的1-3项核心能力项,计划如何提升。
    1、对系统有更加深入的理解。通过CMDB项目的运营,了解各微服务和组件是如何协同工作的,对接业务方需求时保证不影响服务的稳定性,面对告警可以快速找到解决思路。
    2、能够独立负责项目的开发。主动承担更加复杂的任务,以及开发需求的同时增加对业务方面的思考。
    3、学习AI领域的知识,通过CMDB智能助手项目深入学习通过AI赋能传统应用。
  • 面向未来1年的职业规划。
    【更高岗位或职级】:经过一年的多项目需求开发锻炼,交付任务数已经达到了团队平均水平,需要主动承担起更加复杂的项目,有独立思考和设计方案的能力。深度参与服务运维和产品化工作,日常开发中也要思考可优化的点。开发需求的同时,应该增加对业务的思考,对一个系统有更加深入的理解。
  • 上级反馈
    做好的:
    1、完成了influxdb的服务化基础能力开发
    2、完成了负载均衡、dns的自动化能力开发
    待改进:
    1、主动解决问题的能力需要加强
    2、需要加强基础能力的学习
    明确员工亟待提升的核心能力,并为其制定成长计划。=》独立自主解决问题的能力,希望能成长成为能够主导一个方向的负责人
  • expectation2me
    1、提高演讲汇报能力__周会主题AI分享,保持好奇心
    2、突破自己=>没有舒适区/合适的时间=>参与mariadb值班=>面对挑战性任务=>积累信心
    3、CMDB稳定性运营&Agent建设(ps.运营交给外包)
    2025:交付(任务数↑),修复(hospital,solotrip)
    2026:游泳+健身,足球,见朋友,年底tc

12.14 CMDB Agent调研

一:理论知识

  • 一个典型的Agent工作流程如下:
    用户输入自然语言请求。
    Agent将用户输入、对话历史、可用的工具描述(通过Function Calling定义)以及系统提示词组合成一个Prompt,发送给LLM。
    LLM根据Prompt判断是否需要调用工具。如果需要,LLM会返回一个函数调用请求(包括函数名和参数)。
    Agent解析LLM返回的函数调用请求,并执行对应的工具(Tool)。
    工具执行后返回结果,Agent将工具执行结果作为上下文,再次调用LLM,生成最终的自然语言响应。
    Agent将响应返回给用户。
    在这个过程中,RAG可以在第一步之前或之中介入,通过检索外部知识库来增强Prompt的上下文。
  • Spring AI 核心概念
    1. Spring AI 是Spring生态系统中的一个项目,旨在简化AI功能的集成。它提供了统一的API来调用各种AI模型。
    2. Spring AI 集成了以下功能来支持上述流程:
      ChatClient:统一接口,用于与各种LLM交互。
      Prompt Templates:支持参数化提示词模板,方便构建动态Prompt。
      Function Calling:支持定义工具(通过@Description注解等),并自动处理函数调用流程。
      RAG:提供了检索器(Retriever)和向量存储(VectorStore)的支持,可以方便地实现检索增强。
      Agents:提供了Agent的抽象和实现,比如通过Chain(链)来组合多个步骤,包括工具调用。
    3. 官方资源:
      https://spring.io/projects/spring-ai - 必读!
      https://docs.spring.io/spring-ai/reference/index.html
      视频教程(推荐):
      https://www.youtube.com/watch?v=示例 - 搜索”Spring AI Getting Started”
    4. 关键概念速成:
      // Spring AI 核心组件关系
      ChatClient ←→ PromptTemplate ←→ ChatResponse

      Function Calling ←→ Tools ←→ Your CMDB Service
  • CMDB中的具体应用场景
    1. 自然语言查询:”帮我找内存大于8G的Linux服务器”
      1
      2
      3
      // 1. LLM解析 → 需要调用queryHosts工具,参数: osType="Linux", minMemory=8
      // 2. Tool执行 → MongoDB查询: db.hosts.find({os: "Linux", memory: {$gte: 8}})
      // 3. LLM整合 → "找到3台符合条件的Linux服务器..."
    2. 统计分析:”统计不同操作系统的服务器数量”
      1
      2
      3
      // 1. LLM解析 → 需要调用queryHosts工具,参数: osType="Linux", minMemory=8
      // 2. Tool执行 → MongoDB查询: db.hosts.find({os: "Linux", memory: {$gte: 8}})
      // 3. LLM整合 → "找到3台符合条件的Linux服务器..."
    3. 智能建议:”我们的数据库性能有点慢”
      1
      2
      3
      // 1. RAG检索 → 相关性能优化文档
      // 2. LLM分析 → 结合CMDB数据给出具体建议
      // 3. 返回响应 → "建议检查数据库A和B的索引配置..."

二:竞品分析(理解产品形态)

可体验的竞品:

  1. 维诣科技CMDB助手 - https://www.vertice.cn/solution-details/26737.html 重点分析其交互模式
  2. ServiceNow Now Assist - https://www.servicenow.com/products/now-assist.html
  3. Azure Copilot for IT - https://azure.microsoft.com/en-us/products/copilot-for-it

竞品核心功能提取:

• 自然语言转查询:”内存大于8G的服务器” → MongoDB查询
• 结果格式化:表格、图表、自然语言总结
• 错误处理:查询无结果时的智能建议

三:Agent架构设计(针对MongoDB文档型CMDB)

  • 业界主流架构方案对比
方案 技术栈 优点 缺点 适用场景
Python独立Agent服务 Python + FastAPI/Flask + LangChain AI生态丰富,开发速度快,框架成熟 需要维护多语言栈,网络调用开销 大多数企业,特别是AI优先的团队
Spring AI集成 Java + Spring AI 技术栈统一,性能更好,与现有系统无缝集成 Spring AI相对较新,生态不如Python丰富 Java技术栈为主的企业,追求技术统一性
混合架构 Python Agent + Java业务层 兼顾AI能力和业务逻辑,职责清晰 架构复杂,运维成本高 大型企业,已有复杂Java系统
  • 技术栈选择:
    框架: Spring Boot 3.x + Spring AI
    AI服务: OpenAI API 或 本地ChatGLM
    数据库: MongoDB (你的现有数据)
    向量数据库: 可选,初期可用MongoDB Atlas搜索功能
    前端: 简单HTML页面 + WebSocket
  • demo搭建
    https://github.com/leo710aka/CMDB-Chat/blob/main/cmdb_chat.py (Python demo using LangGraph)

2026.01.05 CMDB Copilot

1.5:项目启动
1.7:datamax问数体验,开启多轮问答方案调研(确定表-确定字段-确定sql..)
1.9:DataAgent项目体验,SpringAiAlibaba,Apache2.0
1.11:DataAgent=》配置llm+embedding,初始化数据源embedding到本地vectorStore,,Graph多轮问数


02/2027

CV

  • 工作经历
    后端开发工程师-Java 2024.7~
  • 教育经历
    • 在校经历:曾获学校与企业奖学金, “三好学生”等荣誉,发表 EI 会议论文一篇。曾加入学院青马工程班学习,担任华工青年志愿者指导中心宣传部副部长,有丰富的志愿活动和学生组织经历。
    • 荣誉奖项:五粮液优秀学生奖学金(2023.10),华南理工大学三等奖学金(2022.09),广东省第十一届大运会“优秀志愿者”(22.06)
      2022—2023学年度 “三好学生”×,校级“优秀公益组织骨干”,”青马工程”班优秀学员
      2021—2022学年度 “三好学生”,“两优两红优秀共青团员”
  • 项目经验
    1. 运维平台(MOPS)自动化开发 & CMDB
      • 华为云/Azure 主机生命周期管理:实现云主机的创建、开关机、重启自动化,通过调 API 和作业平台接口,减少70%人工
      • NBU 备份自动化:通过 Ansible 脚本部署备份客户端,集成备份平台 API,提升备份任务效率 50%。
      • 负载均衡(F5)配置自动化:设计蓝绿发布流程,支持参数动态变更和回滚,处理并发场景下的数据一致性。海内外 全集团使用,自动化20%->80%
      • DNS 解析管理:支持 A、CNAME、MX 等记录类型的增删改,集成多平台(Windows DNS产品化),实现一键申请和回退。
      • 了解整个系统架构,springboot,,mq,java回收器,,
      • 参与 CMDB 数据同步和回调优化,解决高并发场景下的性能瓶颈。
    2. InfluxDB 服务化开发
      • 调研开发基于开源influxdb的服务化功能,对齐mariadb,支持创建回收、备份恢复、重启、节点迁移等功能
      • 备份恢复功能:集成 OSS 存储和 K8s 运维能力,实现实例级备份恢复,保障高可用性。
      • 集群管理:完成 InfluxDB 父子实例改造,支持 Data/Meta 节点独立变配和迁移。
      • 数据迁移与恢复:设计“热分片截断-冷副本恢复”方案,解决开源工具在增量数据场景下的丢失问题(通过 2000 points/s 压力测试验证)。
      • 了解k8s云原生环境运维开发?具备常见数据库运维能力,,oom,慢sql,主从切换异常,,
  • 专业技能
    • 后端开发:熟练掌握 Java、Spring Boot、Spring Cloud、MyBatis,熟悉微服务架构和设计模式。
    • 数据库与中间件:
    • 关系数据库:MySQL、Oracle(事务、索引优化、SQL调优)。
    • NoSQL:InfluxDB(集群部署、备份恢复、数据迁移)。
    • 消息队列:RabbitMQ(异步任务解耦)。
    • 运维与云原生:
    • 熟练使用 Kubernetes(Pod、StatefulSet、Service)、Docker 部署和管理应用。
    • 熟悉自动化运维工具:Ansible(脚本编写)、Jenkins(CI/CD流水线)。
    • 云平台:华为云、Azure(API集成与资源管理)。
    • 学习
    • 读《马斯克传》后感:.. 读《阿里巴巴Java开发手册》..
    • 学《mysql45讲》,通过OBCA??

0

  • 自我介绍。
    面试官您好,我是蔡枫,本科毕业于华南理工大学计算机学院,一年多以来在美的集团从事Java后端开发的工作。
    我主要接触两方面的工作,目前正在做的是自动化运维平台的开发,面向整个集团的用户提供主机、网络管理相关的服务,类似的竞品有嘉为蓝鲸,我们的工作就是把以往通过管理员手动下发的工作实现流程化、自动化,保证可追溯和甚至可逆。另外,还做了半年的数据库服务化开发,建设InfluxDB的“数据库即服务”(DBaaS)能力,基于开源Influxdb Cluster支持了备份恢复、变配、迁移等功能,但是后期随着对开源数据库的可靠性存在顾虑中断了。

  • 💻 项目一:自动化运维平台开发与产品化

    • 我主要负责MOPS开发,面向全集团提供主机、网络运维、备份管理等运维功能,目标是实现运维操作的自动化、流程化和可逆化。本身也是可对外输出的ToB产品,也接触到产品化定制需求的开发和环境部署。独立负责基于F5的负载均衡和域名解析两大模块的自动化功能全生命周期建设,主要是申请、变更、回收和一键回退的场景,基本实现了全自动化。
    • 具体工作与关键技术细节
      1. 自动化流水线设计:我设计了基于 “工单驱动” 的自动化流水线。将用户申请转化为标准化工单,支持 “立即、定时、两阶段” 等多种执行策略,将F5平台的参数与表字段一一对应,调用API、脚本实现策略下发。(特别的,负载均衡变更为创建新pool挂到原vs=》蓝绿发布,,记录变更前状态以保证回滚完全。。)
      2. 多系统集成与可靠性保障:深度集成CMDB(作为资源事实库)、作业平台(用于脚本下发)等系统。为确保流程可靠,我着重处理了异常控制和回滚机制。所有操作步骤都有明确的状态和日志记录,每一环节的操作都详细记录上下文到日志供排查;下发成功后,支持一定时效内和指定权限人发起一键回退。。
      3. 产品化与高可用设计:为支持产品化输出,我对功能进行了抽象和封装,使其能通过配置适配不同客户的环境。通过Powershell脚本另外支持了Windows平台的DNS自动化下发。
    • 市场竞品对比与成果衡量
      • 对标产品:这项工作在市场上类似嘉为蓝鲸的自动化运维平台或腾讯蓝鲸的相关模块。它们核心价值也在于将复杂的手动操作标准化、自动化,并确保过程可控。
      • 我的成果:
        效率提升:将F5配置和DNS解析这类操作的平均交付时间从天级缩短到分钟级,全年支持变更超千次。
        可靠性:通过完善的异常处理和回滚,将因配置失误导致的业务中断事件降低了90%以上。
        产品价值:直接支撑了该平台作为ToB产品成功落地,获得了客户验收。
  • 💾 项目二:InfluxDB数据库服务化能力建设

    • 我主导了InfluxDB数据库的服务化改造,在数据库管控平台(DataMars)中,建设InfluxDB的“数据库即服务”(DBaaS)能力,解决手动运维数据库效率低、易出错的问题。基于开源Influxdb Cluster,从0到1负责InfluxDB实例的备份恢复、在线变配、节点迁移/重搭等核心功能的调研、设计和开发。
    • 具体工作与关键技术细节
      1. 核心场景实现:
        备份恢复:调研并采用 influx_inspect export 逻辑备份与OSS对象存储结合方案,实现了数据库级和实例级的备份恢复,并集成到平台的工作流引擎中。
        在线变配:通过修改Kubernetes StatefulSet配置,实现了CPU、内存的原地变配,以及通过PVC(持久化存储声明)扩容实现存储空间的在线扩展。
        节点迁移与数据一致性保障:这是项目最大挑战。我设计并实现了 “热分片截断-冷副本恢复”双阶段迁移方案。在数据持续高速写入(2000 points/s)的场景下,通过先截断热分片引导新数据写入新节点,再从健康节点同步历史数据,有效解决了开源工具在迁移过程中可能丢失增量数据的问题,确保了数据一致性。
      2. 技术架构:功能深度集成到平台的apiserver、bakserver和agent组件中,通过K8S Operator模式对InfluxDB集群的生命周期进行管理。
    • 市场竞品对比与成果衡量
      • 对标产品:这类数据库服务化平台在业界类似云和恩墨zCloud、腾讯云DBbridge等数据库管理平台,核心是实现数据库资源的池化、按需供给和全生命周期智能化管理。
      • 我的成果:事实上基本没有用户,随着发现开源数据库的功能不完善,开发也中断了。
    • 在面试中介绍时,你可以遵循“背景-行动-结果-对比”的结构:
      • 开头总结:用一句话点明项目核心价值。
      • 具体阐述:重点突出你如何解决关键问题,特别是高可用、数据一致性、自动化闭环方面的设计。
      • 量化成果:用数据(如效率提升百分比、可靠性指标)证明你的贡献。
      • 展现视野:通过提及竞品,表明你不仅埋头编码,更抬头看路,了解行业最佳实践。
  • 技术亮点与难点

    1. InfluxDB 节点迁移(2025年4月)
      • 难点:开源工具在数据同步时可能丢失增量数据,需自定义解决方案。
      • 解决:设计“热分片截断+冷副本恢复”双阶段方案,通过多线程压测验证数据一致性。
      • 价值:为分布式数据库的容灾提供了可复用的方法论。
    2. 负载均衡/F5 配置自动化(2025年7月)
      • 难点:并发变更时资源竞争导致配置异常。
      • 解决:引入状态机管理工单流程,通过校验机制和回滚逻辑保证安全性。
      • 价值:支持每年 1000+ 次变更需求,错误率下降至 1% 以下。
      • ?!工程化思维:注重文档、自动化、可维护性(如制定 SOP、设计回滚方案)。
  • 为什么要跳槽?

  • 工作一年以来对Java开发的理解。
    整体比较符合预期,就是解决实际问题的根据,利用算法&数据结构,实现具体的需求。目前不可避免的陷入在很小的领域(很具体的功能)编写杂七杂八的业务逻辑,但这是总来有执行者来做的工作,我觉得关键是前期方案设计时保证整体的可靠性和通用性(自动化场景1 2 3,平台1 2 3),做需求时总结出sop,或者直接交给AI来做

  • 一个挑战。

    1. 自动化运维,负载均衡vs<-pool<-server三层结构,改造为支持并发。。立即,定时,同时都有,怎么考虑,,
    2. influxdb服务化,做迁移的时候,把指令全试了一遍
  • 一次排查问题。
    cpu飙升,发现是一个接口有io操作,并发大了就卡住了。。
    首先,停掉回写接口,把cpu降下来,恢复服务
    分析,不是计算型的,所以多线程没用,要考虑优化io查询,cmdb加索引。。
    其次,如何降低并发,加缓存?异步??

  • 处理线上问题,处理偶现问题
    。。

  • 为什么tob,为什么2c?中台?
    不局限tob/c,但是要持续学习,保持好奇。做中台就像一个螺丝钉,不断修修补补,比较无趣(运维场景深度待挖掘)

  • 对AI的使用
    AI Coding使用的主要场景有 1、有过往代码可参考的新需求 2、有API文档的需求
    运维Agent

1

  • 字节跳动·巨量广告
    • 面试辅导
      为什么捞出一年经验的校招生,有什么期待?