<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Technique on 有点稳</title><link>https://blog.nicelylit.net/tags/technique/</link><description>Recent content in Technique on 有点稳</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Fri, 15 Aug 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.nicelylit.net/tags/technique/index.xml" rel="self" type="application/rss+xml"/><item><title>大模型（一）</title><link>https://blog.nicelylit.net/posts/%E5%A4%A7%E6%A8%A1%E5%9E%8B%E4%B8%80/</link><pubDate>Fri, 15 Aug 2025 00:00:00 +0000</pubDate><guid>https://blog.nicelylit.net/posts/%E5%A4%A7%E6%A8%A1%E5%9E%8B%E4%B8%80/</guid><description>&lt;h3 id="大模型是什么"&gt;大模型是什么？
&lt;/h3&gt;&lt;p&gt;大模型是大语言模型（Large Language Model, LLM）的简称，基于海量数据和庞大参数规模得到的机器学习模型，能够理解和生成自然语言和代码等内容。&lt;/p&gt;
&lt;h3 id="大模型有什么核心特点"&gt;大模型有什么核心特点？
&lt;/h3&gt;&lt;p&gt;大模型的核心特点是参数规模大、通用性强、上下文理解。&lt;/p&gt;
&lt;p&gt;大模型的参数规模在十亿到万亿量级，比如GPT-4有1.8万亿。有些模型参数会带在名字里，比如Qwen-72B指的是千问通用大模型的720亿参数的版本。&lt;/p&gt;
&lt;p&gt;大模型的通用性在于任务无关性、小样本学习和多模态能力。大模型预训练学习广泛的知识，可以适用于多种任务，问答、翻译、编程等。大模型无需额外训练，仅通过示例就可以执行新任务。多模态大模型可以同时处理文本、图像、语音等输入。&lt;/p&gt;
&lt;p&gt;大模型支持长文本交互，能结合上下文生成连贯的回答。大模型能识别上下文代词的指代以及省略，维持主题避免重复或矛盾，提取分散在多段落中的关键信息。大模型的上下文理解能力得益于注意力机制和位置编码，但也有长程衰减的特点，注意力权重下降。上下文有窗口限制，比如GPT-4支持128K个token，超出会被丢弃。&lt;/p&gt;
&lt;p&gt;大模型的局限性体现在幻觉、数据偏见和算力要求高。幻觉是在上下文模糊的情况下产生的一种虚构内容的现象。训练数据中如果有偏见那么大模型也会产生偏见。目前训练和部署都需要大量的GPU资源。&lt;/p&gt;
&lt;h3 id="大模型有哪些应用场景呢"&gt;大模型有哪些应用场景呢？
&lt;/h3&gt;&lt;p&gt;大模型凭借其强大的语义理解和生成能力，将会影响到各行各业的创新和协作，就目前看，主要是以下四个大类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自然语言处理：知识问答／智能客服、机器翻译、情感分析，可结合语音处理的技术提供更贴近生活的用户体验&lt;/li&gt;
&lt;li&gt;代码生成和辅助：代码补全、文件编辑、代码生成、代码理解和转换、注释生成、测试用例生成、错误修复、设计建议，可通过代理调用其他服务扩展大模型的能力&lt;/li&gt;
&lt;li&gt;内容创作：营销文案、广告创意、新闻快讯、剧本大纲、字幕生成、编辑校对、文字润色，可结合图像、语音、视频处理的技术生成多模态的内容&lt;/li&gt;
&lt;li&gt;分析诊断：疾病辅助诊断、辅助数学证明、科研论文阅读、智能顾问、自适应学习、合规审查、风险分析&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="大模型有哪些核心能力呢"&gt;大模型有哪些核心能力呢？
&lt;/h3&gt;&lt;p&gt;GPT-5直接给出了16项能力（Capability），是DeepSeek给出的两倍，看上去也不太好说哪个就能包含或者推导出另一个，难以剔除，只能进行分层（Level）和分组（Group），GPT-5给出的结果基本没有太多可挑剔的，它直接对能力分了七层和六组，不过我还是觉得太多了，索性让它把六组做了分层，它给出了三个方案，我选择了大小适中的方案介绍。&lt;/p&gt;
&lt;p&gt;四个分层是&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;L1: 表示与变换&lt;/li&gt;
&lt;li&gt;L2: 推理与决策&lt;/li&gt;
&lt;li&gt;L3: 编排与行动&lt;/li&gt;
&lt;li&gt;L4: 治理与保障&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;四层中，前三层的关系是上一层是下一层的基础，而第四层需要贯穿整个三层。六个分组是&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;G1: 语言与表示&lt;/li&gt;
&lt;li&gt;G2: 语义变换&lt;/li&gt;
&lt;li&gt;G3: 认知推理&lt;/li&gt;
&lt;li&gt;G4: 交互控制&lt;/li&gt;
&lt;li&gt;G5: 外界接入与行动&lt;/li&gt;
&lt;li&gt;G6: 治理与保障&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;六个分组到四个层的归属关系是这样的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;L1: G1, G2&lt;/li&gt;
&lt;li&gt;L2: G3&lt;/li&gt;
&lt;li&gt;L3: G4, G5&lt;/li&gt;
&lt;li&gt;L4: G6&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;详细来看看16项能力的描述和示例。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;C1: 语言理解（NLU）- 读懂意图、上下文、指代、情感、语义相似度；意图识别、问答、分类、相似句召回&lt;/li&gt;
&lt;li&gt;C2: 语言生成（NLG）- 连贯生成与风格控制、改写；邮件/文案撰写、语气转换、SEO内容&lt;/li&gt;
&lt;li&gt;C3: 翻译与跨语言 - 多语互译、术语一致、语域迁移；技术文档本地化、多语客服&lt;/li&gt;
&lt;li&gt;C4: 长上下文与记忆 - 超长文档处理与跨段一致性；长合同问答、项目历史跟进&lt;/li&gt;
&lt;li&gt;C5: 多模态理解与生成 - 图像/音频/视频/表格理解与描述；图表解读、截图问答、图像说明&lt;/li&gt;
&lt;li&gt;C6: 信息抽取与结构化 - 实体/关系抽取、要点表格化；合同要点提取、舆情三元组抽取&lt;/li&gt;
&lt;li&gt;C7: 摘要与压缩 - 多粒度总结、对比摘要、主题归纳；会议纪要、论文速览、新闻汇编&lt;/li&gt;
&lt;li&gt;C8: 推理与规划 - 常识/因果/数学推理，任务分解与计划；解题思路、行程规划、流程优化&lt;/li&gt;
&lt;li&gt;C9: 数据分析与轻量可视化 - 描述统计、趋势洞察、异常解读；报表解读、A/B结果解释&lt;/li&gt;
&lt;li&gt;C10: 指令跟随与对话管理 - 按自然语言步骤执行，保持多轮上下文；流程性任务执行、对话机器人&lt;/li&gt;
&lt;li&gt;C11: 个性化与风格控制 - 角色设定、语气/长度/格式可控；法律/学术风格、对话式教程&lt;/li&gt;
&lt;li&gt;C12: 检索与知识增强（RAG）- 结合外部文档检索提升事实性与时效；企业知识库问答、条文引用&lt;/li&gt;
&lt;li&gt;C13: 工具使用（函数与插件调用）- 调用API/数据库/计算器/浏览器等；下单、查库存、运行SQL、网页查证&lt;/li&gt;
&lt;li&gt;C14: 代码能力 - 生成、重构、补全、调试、解释；API示例、单测补全、错误定位&lt;/li&gt;
&lt;li&gt;C15: 代理与自动化 - 拆解-执行-回顾的自主循环；竞品调研到成稿的一体化执行&lt;/li&gt;
&lt;li&gt;C16: 安全与可控性 - 敏感识别、合规约束、审计可追踪；内容审核、PII识别、策略对齐&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它给的示例中，大部分我还都知道是什么内容，像语域迁移、舆情三元组、PII识别的概念都是头次听说，它的知识储备的确让人类的个体望尘莫及啊。最后，16项能力到六个分组的归属关系是这样的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;G1: C1, C2, C3, C4, C5&lt;/li&gt;
&lt;li&gt;G2: C6, C7&lt;/li&gt;
&lt;li&gt;G3: C8, C9&lt;/li&gt;
&lt;li&gt;G4: C10, C11&lt;/li&gt;
&lt;li&gt;G5: C12, C13, C14, C15&lt;/li&gt;
&lt;li&gt;G6: C16&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="大模型能力的评价维度有哪些"&gt;大模型能力的评价维度有哪些？
&lt;/h3&gt;&lt;p&gt;大模型训练和推理过程中都需要指标去评价，从而帮人去认识大模型的能力和能力边界，以达成选择和优化的目的。不同的阶段和方法会涉及到非常多的指标，但一般能从六个维度来看：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;准确性：输出是否正确、与证据一致、逻辑自洽，比如语言理解和生成中分类或者选择的准确率、推理和数学问题解答的正确率、知识生成的幻觉率、代码测试用例的通过率等。&lt;/li&gt;
&lt;li&gt;稳定性：在扰动、不同随机性、长链路下保持一致且不崩溃，比如度量决策稳定性的温度、扰动一致性评分、对抗测试输出相似度等。&lt;/li&gt;
&lt;li&gt;时效性：对近期事实/变化的掌握与更新能力，比如近期实时回答的正确率、线上模型主题分布和训练分布漂移等。&lt;/li&gt;
&lt;li&gt;成本与性能：服务成本与性能效率，比如首token的延时、平均token生成速率、单次推理成本、能耗比等。&lt;/li&gt;
&lt;li&gt;安全与合规：有害内容、越权、隐私与法规风险，比如毒性内容触发率、个人身份信息泄漏率等。&lt;/li&gt;
&lt;li&gt;用户体验：用户主观满意与交互效率，用户满意度、净推荐值、会话留存率、平均会话长度等。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="大模型的局限与缓解方法"&gt;大模型的局限与缓解方法？
&lt;/h3&gt;&lt;p&gt;从大模型能力的四个分层上来看局限性和缓解策略：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;表示与转换：符号接地问题（Symbol Grounding Problem）是说抽象的概念与概念的符号如何能对接上真实的对象或者指代的符号。这个局限性一方面来自于多模态的表示不足，另一方面来自于大模型不具备真实世界的体验，而依赖于统计模式。从梅拉尼·米歇尔的观点看，人工智能还缺乏直觉知识，也就是人们普遍习以为常但并未被记录成文字的知识。表示不足容易造成幻觉，目前缓解的办法是通过内容对齐、检索增强、不可回答时拒答、结合知识图谱等。&lt;/li&gt;
&lt;li&gt;推理与决策：因果推理薄弱，有长推理漂移与数学/逻辑错误。这个局限性来自于用统计的相关性代替因果逻辑。从梅拉尼·米歇尔的观点看，人工智能还缺乏抽象、类比、元认知。抽象是说通过抽取不同事物之间的共性特征而构建新的概念。类比是抽取共性的基础上进行预测。元认知是一种反思观察思维过程的过程与抽象。在大模型涌现出思维链能力后，这个局限性有所缓解，其他的缓解办法还有引入工具计算、分步验证、断言检查、规划-执行-回顾等。&lt;/li&gt;
&lt;li&gt;外界接入与行动：物理执行缺失，感知外界变化滞后，实时交互延时。这个局限性来自于文本的符号世界与物理世界的割裂，传感器和执行器难以闭环。数据训练虽然成本高、周期长，但跟传感器和执行器的接入和演进速度来比，已经算是低成本和极快的迭代速度了。缓解办法是发展模型上下文协议（MCP）增强模型接入工具的能力。&lt;/li&gt;
&lt;li&gt;安全保障：隐私泄漏、偏见与毒性输出、对抗攻击脆弱。这个局限性来自于安全目标的不可计算性。缓解办法是数据脱敏、价值观的统一、内容过滤、对抗性测试等。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="大模型能力落地范式有哪些"&gt;大模型能力落地范式有哪些？
&lt;/h3&gt;&lt;p&gt;大模型落地的范式有五种：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;纯生成&lt;/li&gt;
&lt;li&gt;知识增强生成&lt;/li&gt;
&lt;li&gt;工具与程序增强&lt;/li&gt;
&lt;li&gt;编排与工作流&lt;/li&gt;
&lt;li&gt;模型定制&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;纯生成，也就是通过提示词工程，提供少量样本参考，做结构化的生成。这种方式直接通过调用通用或者推理大模型的API，选择合适的初始化配置，结合着提示词优化就可以实现，成本较低。适合简单问答，不需要实时信息，没有特殊安全与隐私合规的需求。&lt;/p&gt;
&lt;p&gt;知识增强生成，也就是在用户和大模型之间，加入额外的系统对用户原始请求或者大模型的答案来增强知识，从而增加大模型回复的准确性。具有代表性的是检索增强生成（RAG），通过信息检索技术，在文档库中检索相关的文档片段，作为额外的知识，一起传给大模型，来降低幻觉，提升信息的时效性。这种方式适合专业领域知识并未公开但可以内部检索的需求，还有时效新闻来不及训练的需求。&lt;/p&gt;
&lt;p&gt;工具与程序增强，也就是让大模型具备使用外部工具和执行程序的能力，大模型作为代理人去使用工具完成任务或者补充精确计算结果。这种方式适合编程这种环境相对封闭的需求，还有简化企业内部工具使用的需求。&lt;/p&gt;
&lt;p&gt;编排与工作流，也就是让大模型作为多个代理人角色承担计划、执行、回顾等多种任务，自动完成完整的工作流。这种方式适合自动化运营和批量报表生产。&lt;/p&gt;
&lt;p&gt;模型定制，也就是通过指令对齐、模型微调让大模型能适应特定任务或者领域。这种方式需要额外训练，对数据规模和成本要求较高，适合法律、医疗、编程等专业领域。&lt;/p&gt;
&lt;h3 id="大模型的原理和核心技术"&gt;大模型的原理和核心技术？
&lt;/h3&gt;&lt;p&gt;大模型的核心思想是通过海量数据+巨量参数+自监督学习实现通用智能，其原理和核心技术体现在算力、算法和数据三个方面。&lt;/p&gt;
&lt;p&gt;算力：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;张量核心与混合精度&lt;/li&gt;
&lt;li&gt;稀疏计算技术&lt;/li&gt;
&lt;li&gt;显存分层与内存优化&lt;/li&gt;
&lt;li&gt;通信栈和互联硬件优化&lt;/li&gt;
&lt;li&gt;并行分片技术&lt;/li&gt;
&lt;li&gt;CUDA生态和编译优化&lt;/li&gt;
&lt;li&gt;芯片液冷和动态频率调节&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;算法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;缩放定律与涌现能力&lt;/li&gt;
&lt;li&gt;深度学习理论&lt;/li&gt;
&lt;li&gt;神经网络理论&lt;/li&gt;
&lt;li&gt;Transformer架构&lt;/li&gt;
&lt;li&gt;向量化表示&lt;/li&gt;
&lt;li&gt;训练扩展技术&lt;/li&gt;
&lt;li&gt;微调对齐技术&lt;/li&gt;
&lt;li&gt;参数压缩技术&lt;/li&gt;
&lt;li&gt;参数调节技巧&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;数据：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据规模与计算资源配比&lt;/li&gt;
&lt;li&gt;相似文本检测去重&lt;/li&gt;
&lt;li&gt;低质量文本过滤&lt;/li&gt;
&lt;li&gt;文本解析与规范化&lt;/li&gt;
&lt;li&gt;数据增强技术&lt;/li&gt;
&lt;li&gt;打包和加载技术&lt;/li&gt;
&lt;li&gt;数据采样与混合策略&lt;/li&gt;
&lt;li&gt;数据治理与可观测技术&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>微服务（一）</title><link>https://blog.nicelylit.net/posts/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%B8%80/</link><pubDate>Mon, 09 Jun 2025 00:00:00 +0000</pubDate><guid>https://blog.nicelylit.net/posts/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%B8%80/</guid><description>&lt;h2 id="概述"&gt;概述
&lt;/h2&gt;&lt;h3 id="什么是微服务"&gt;什么是微服务？
&lt;/h3&gt;&lt;p&gt;微服务是一种软件架构风格，相较于单体架构（整体式架构），应用被拆分为多个小型、独立服务，每个服务围绕特定业务功能构建，独立开发、部署、扩展和维护，服务间通过轻量级的通信机制协作，来组合完成完整应用。微服务和微服务架构是一个意思。每个微服务由各个小型独立团队负责。&lt;/p&gt;
&lt;h3 id="为什么需要微服务"&gt;为什么需要微服务？
&lt;/h3&gt;&lt;p&gt;微服务架构从单体架构（整体式架构）演进而来，经历了从单体架构到面向服务（SOA）架构，再到微服务架构的变化。微服务架构使应用程序更易于扩展和更快地开发，从而加速创新并缩短新功能的上市时间。&lt;/p&gt;
&lt;p&gt;微服务架构具有自治和专用的特点。自治加快了应用的发布速度，让开发变得敏捷、功能扩展更灵活、工具选择更自由、部署更轻松。专用降低了应用功能的耦合性，提高了代码模块的重用，也缩小了故障影响提升了可用性，让应用更具弹性和可伸缩性。&lt;/p&gt;
&lt;h3 id="微服务和云原生是什么关系"&gt;微服务和云原生是什么关系？
&lt;/h3&gt;&lt;p&gt;微服务架构是云原生架构的基石，除了微服务之外，云原生的关键技术还包括容器、Serverless和DevOps。微服务架构的核心目的是通过模块化来提升应用研发的效率，而云原生的核心目的是最大化地利用云平台的特性来实现高效的资源利用、快速迭代和自动化运维，两者相辅相成。&lt;/p&gt;
&lt;h3 id="构建微服务有哪些典型的服务组件"&gt;构建微服务有哪些典型的服务组件？
&lt;/h3&gt;&lt;p&gt;典型的微服务组件可以从七个角度来看：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;业务核心组件：服务实例、服务接口&lt;/li&gt;
&lt;li&gt;通信组件：API网关、RPC通信（同步）、消息队列（异步）、定时任务（异步）、注册中心&lt;/li&gt;
&lt;li&gt;数据管理组件：独立数据库、分布式缓存、时间流处理&lt;/li&gt;
&lt;li&gt;运维监控组件：容器和编排、配置中心、日志与监控&lt;/li&gt;
&lt;li&gt;安全组件：身份认证与授权、服务网格&lt;/li&gt;
&lt;li&gt;弹性与容错组件：域名解析、负载均衡、限流器、熔断器、重试与降级&lt;/li&gt;
&lt;li&gt;开发与交付组件：持续交付、基础设施即代码&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="参考阅读"&gt;参考阅读
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;a class="link" href="https://aws.amazon.com/cn/microservices/" target="_blank" rel="noopener"
 &gt;什么是微服务？&lt;/a&gt;AWS&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.aliyun.com/getting-started/what-is/what-is-microservice" target="_blank" rel="noopener"
 &gt;什么是微服务？&lt;/a&gt;阿里云&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.ruanyifeng.com/blog/2022/04/microservice.html" target="_blank" rel="noopener"
 &gt;微服务是什么？&lt;/a&gt;阮一峰&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.amazonaws.cn/knowledge/what-is-cloud-native/" target="_blank" rel="noopener"
 &gt;什么是云原生？&lt;/a&gt;AWS&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.amazonaws.cn/knowledge/what-is-cloud-native/" target="_blank" rel="noopener"
 &gt;云原生架构&lt;/a&gt; AWS&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.aliyun.com/getting-started/what-is/what-is-cloud-native#3749b362e7doq" target="_blank" rel="noopener"
 &gt;什么是云原生？&lt;/a&gt;阿里云&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://cloud.google.com/learn/what-is-cloud-native?hl=zh-CN" target="_blank" rel="noopener"
 &gt;什么是云原生？&lt;/a&gt;Google Cloud&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>虚拟化技术（二）</title><link>https://blog.nicelylit.net/posts/%E8%99%9A%E6%8B%9F%E5%8C%96%E6%8A%80%E6%9C%AF%E4%BA%8C/</link><pubDate>Sat, 31 May 2025 00:00:00 +0000</pubDate><guid>https://blog.nicelylit.net/posts/%E8%99%9A%E6%8B%9F%E5%8C%96%E6%8A%80%E6%9C%AF%E4%BA%8C/</guid><description>&lt;h3 id="虚拟化有哪些核心概念"&gt;虚拟化有哪些核心概念？
&lt;/h3&gt;&lt;h4 id="服务器的虚拟化"&gt;服务器的虚拟化
&lt;/h4&gt;&lt;p&gt;虚拟化的核心就是虚拟机监视器（Virtual Machine Monitor, VMM/Hypervisor），它是一个虚拟化层，将硬件抽象成虚拟计算资源，分配给虚拟机使用。硬件是一台物理机，有些情况下也被称作宿主机（Host Machine）。虚拟机运行在VMM之上，也被称作客户机（Guest Machine）。在虚拟机上才会安装操作系统（OS），用以通过服务和应用供用户操作完成一些特定的任务。VMM直接运行在硬件上的也被称作裸金属型的。此外，还有一种运行在操作系统上的被称作宿主型的。&lt;/p&gt;
&lt;p&gt;服务器的虚拟化的抽象资源包括处理器（CPU或者GPU）、内存和I/O，CPU和内存用于通用计算，GPU用于图形计算、并行计算、智能计算，I/O用于扩展外部设备，包括存储和网络等。从功能上看，虚拟机监视器提供虚拟机的创建、资源的隔离和调度、虚拟化的设备管理等三项功能。此外，为保障虚拟资源的执行效率，降低虚拟化的损耗，VMM的很大一部分工作是性能优化，许多的架构设计方案都是为了达成这个目标。&lt;/p&gt;
&lt;h5 id="cpu的虚拟化"&gt;CPU的虚拟化
&lt;/h5&gt;&lt;p&gt;物理CPU虚拟化的产物是虚拟CPU，或者vCPU，物理CPU也被称作pCPU。CPU的核心功能是接受指令请求和处理指令，串行接受指令请求和处理指令的单元是线程。模拟出vCPU的主要工作就是构造出线程的部件和功能，包括控制器、运算器、寄存器和高速缓冲存储器等部件，取指令、翻译指令和执行指令等功能。vCPU的数量取决于三个因素，物理CPU的数量、一个物理CPU内的核心数、一个核心的超线程数。&lt;/p&gt;
&lt;p&gt;每个虚拟机可以被分配所有的vCPU，也可以分配部分，VMM负责vCPU的调度，也就是把vCPU上的指令转换为物理CPU上的指令。依据虚拟化方法的不同，有全虚拟化、硬件辅助虚拟化和半虚拟化。虚拟化方法需要VMM和虚拟机甚至是客户机的操作系统能够配合和兼容。全虚拟化也就是完全在软件层面模拟接受指令请求和处理指令的过程，这种情况下陷入内核执行的指令数量很多，因此性能较差。硬件辅助虚拟化是针对特权指令才陷入到特权级别执行，在CPU中实现了虚拟机的上下文切换和状态管理，提升了性能。半虚拟化需要修改操作系统来支持hypercall，使得客户机的操作系统也能运行在物理CPU的特权模式下。&lt;/p&gt;
&lt;h5 id="内存的虚拟化"&gt;内存的虚拟化
&lt;/h5&gt;&lt;p&gt;内存虚拟化的产物是虚拟内存，但实际上虚拟内存在没提虚拟化的时候，就已经有了。虚拟内存是为了给每个进程分配逻辑一致的独立的地址空间，有别于物理内存。在内存的虚拟化中是为了给每个虚拟机分配逻辑一致的独立的地址空间，在进程地址空间之外又加了一层，这样算下来是四个地址：客户机的虚拟地址（GVA）、客户机的物理地址（GPA）、VMM的虚拟地址（HVA）、VMM的物理地址（HPA）。不管几层，虚拟化方法的核心功能都是类似的，都是地址映射，实现机制就是通过页表分页管理地址映射，提高效率的方法就是减少映射转换的次数。&lt;/p&gt;
&lt;p&gt;可被虚拟化的内存资源数量受到GPU支持能力、主板内存插槽数量、单条内存容量、内存类型等因素的限制。虚拟内存的容量受到物理内存容量和内存超分配技术的限制。&lt;/p&gt;
&lt;h5 id="io的虚拟化"&gt;I/O的虚拟化
&lt;/h5&gt;&lt;p&gt;除去CPU和内存外，其他的设备都算作I/O，I/O往往是通过接口外挂上去后，由设备控制器与CPU和内存进行控制权、状态和数据的交换的。控制是双向的，由设备发起的是中断请求，由CPU发起的是设备访问。中断请求和设备访问都会下发指令，使得另一方的状态发生变化，同时携带要传递的数据。为提高CPU的效率，对于大量的数据移动，会通过DMA完成。&lt;/p&gt;
&lt;p&gt;虚拟化的目的是为了分隔资源和利用资源，梳理来看这里面的资源有设备、接口、总线和中断处理器/RTC/DMA等四项。虚拟化设备需要单独拎出来看，不同的设备虚拟化的方法有所不同，共性是接入CPU和内存的方式，以及通信和控制的方式。接口用于接入设备，物理实体上是各种端口和插槽，从通信机制上看，一种是端口I/O，另一种是内存映射I/O。总线用于设备和CPU、内存间的通信，连接了设备和CPU、内存。接口和总线的虚拟化，就是接入配置和通信机制的虚拟化。通信机制的核心部分是中断处理器、RTC和DMA完成的，虚拟化通信机制的主要部分就是虚拟化它们。&lt;/p&gt;
&lt;p&gt;具体到虚拟化的解决方案所要讨论的，就是VMM中有没有必要实现某种资源的虚拟化，某种资源的虚拟化可否放在用户空间实现。&lt;/p&gt;
&lt;p&gt;虚拟I/O的设备数量受限于物理主机的I/O带宽（网络带宽、存储带宽等）、VMM的参数配置（资源类型、设备配置等）、物理设备虚拟化的支持情况、虚拟设备的类型和数量（虚拟网卡、虚拟控制器等）等因素。&lt;/p&gt;
&lt;h5 id="gpu的虚拟化"&gt;GPU的虚拟化
&lt;/h5&gt;&lt;p&gt;从硬件上看，GPU通常是显卡的一部分，显卡属于外部设备，需要跟CPU和内存配合工作。CUDA编程让GPU能够支持通用的并行计算（GPGPU），在CUDA编程之前GPU主要通过图形接口执行图形渲染任务。随着GPU被人工智能领域用来训练深度学习的神经网络，这样的计算也开始被称作智能计算。&lt;/p&gt;
&lt;p&gt;物理GPU虚拟化的产物是vGPU，将vGPU分配不同的虚拟机使用，为了保障性能，也有直通的资源独占的方式。由于显卡的外设属性，也需要考虑设备驱动，可GPU又不同于其他的外设，具备计算的能力，因此GPU的核心在处理计算任务的时候也被看作是服务器，而不仅仅是向CPU发起中断请求的客户端。在英伟达vCUDA核心的设计上，有三个模块客户端、服务端和管理端。客户端是安装在虚拟机上的显卡驱动程序，负责对CUDA应用程序API的拦截、解析、包装、代理请求和代理响应。服务端是位于一个特权虚拟机中，负责接受管理端的资源注册，以及为客户端的请求提供服务。管理端才是GPU的管理器，位于特权域VMM中，负责GPU的动态调度、负载均衡和故障恢复。&lt;/p&gt;
&lt;p&gt;物理GPU的数量受限于主板显卡的卡槽数量、显卡的类型、总线带宽和电源供应等因素。虚拟GPU的数量受限于物理显卡的数量、VMM的配置和调度策略、GPU和内存资源等因素。&lt;/p&gt;
&lt;h4 id="存储的虚拟化"&gt;存储的虚拟化
&lt;/h4&gt;&lt;p&gt;存储虚拟化需要从两个角度来看，一个是用户的使用角度，另一个是物理设备的管理。&lt;/p&gt;
&lt;p&gt;从用户使用角度看，有直接挂载磁盘的块存储，也有直接挂载文件系统的文件存储，还有更扁平化的对象存储。&lt;/p&gt;
&lt;p&gt;块存储相当于一块空白的磁盘，支持创建、初始化、挂载、卸载等操作。创建的结果是一个虚拟磁盘，初始化的结果是要对虚拟磁盘进行分区或者格式化，并创建文件系统。在分布式环境中，创建和初始化的结果跨越了单机的限制，但实质上与本地磁盘管理要做的事情类似，都是元数据的管理。虚拟磁盘的挂载和卸载也是元数据的操作。除了元数据操作外，实际数据的读写需要遵从一些分布式的网络存储协议，并且要做好元数据中分区、块和实际物理存储之间的映射关系。操作系统使用的存储协议需要考虑网络环境，iSCSI（Internet Small Computer System Interface）是基于IP的存储协议，适用于局域网和广域网连接的块存储；Fibre Channel是专用于存储区域网络的高速传输协议；NVMe-oF是基于NVMe的网络协议。&lt;/p&gt;
&lt;p&gt;文件存储不再增加分区和块的概念，元数据中直接管理文件和文件夹。网络文件存储协议有NFS（Network File System）、CIFS/SMB（Common Internet File System/Server Message Block）和AFP（Apple Filing Protocol）。对象存储相比文件存储更加扁平化，元数据管理存储空间（Bucket）和对象。对象存储首先是亚马逊AWS的S3现实，也被称作S3协议。&lt;/p&gt;
&lt;p&gt;从物理设备管理的角度看，存储虚拟化分三个层次，最底层是存储资源的标准化接入，中间层是统一的数据管理，再上层是虚拟存储整合成资源池。存储的资源主要是磁盘，从介质上是两类，机械硬盘（Hard Drive Disk, HDD）和固态硬盘（Solid State Drive, SSD），此外，还有混合固态硬盘和磁带。存储资源接入主机可以是单块内置或外置，也可以是多块构成的存储阵列。机械硬盘接入主要通过SATA接口，也可以通过SAS（Serial Attached SCSI）扩展器，或者网络协议iSCSI和FC。固态硬盘接入主要通过PCIe槽位，利用NVMe访问和传输协议控制硬盘读写。同一块硬盘通过分区形成不同的存储盘，多块存储盘的物理分区通过逻辑卷组形成跨磁盘的逻辑卷（虚拟分区）。集中的块存储服务通过专门的网络结构和网络协议搭建形成SAN（Storage Area Network）存储。集中的文件存储服务通过瘦服务器将磁盘阵列管理起来形成NAS（Network Attached Storage）存储。通过主机服务器来访问存储的架构是以服务器为中心的架构，成为直连DAS（Directed Attached Storage）存储。虚拟主机也可以接入本地存储镜像。&lt;/p&gt;
&lt;h4 id="网络的虚拟化"&gt;网络的虚拟化
&lt;/h4&gt;&lt;p&gt;网络由网络节点和传输介质组成，此外在节点之间传输信息需要协议进行控制数据传输。对网络进行虚拟化就是对网络节点、传输介质和传输协议进行设计和实现。虚拟化的网络称作Overlay网络，物理网络称作Underlay网络。&lt;/p&gt;
&lt;p&gt;网络节点按照功能分主要有五种客户终端、主机服务器、交换机、路由器、网关。对于网络实现来讲终端和服务器都能归结到网卡（NIC）上。传输介质有同轴电缆、双绞线、光纤、无线电波等。传输协议按照网络分层是底层在外层，上层在里层，一层包一层，封装和拆包的过程恰好相反。&lt;/p&gt;
&lt;p&gt;虚拟化后的网络节点也被称作网元，都通过软件定义实现。虚拟主机通过挂载虚拟网卡进行网络通信，两台虚拟机之间通过虚拟交换机通信，虚拟网卡和虚拟交换机之间通过虚拟链路通信。跨物理机的虚拟机之间的通信除了需要隧道封装技术外，还需要经过虚拟地址和物理地址的映射转换的NAT网关。Overlay的隧道封装技术主流的包括两种GRE（Generic Routing Encapsulation）和VxLAN（Virtual eXtensible LAN）。&lt;/p&gt;</description></item><item><title>虚拟化技术（一）</title><link>https://blog.nicelylit.net/posts/%E8%99%9A%E6%8B%9F%E5%8C%96%E6%8A%80%E6%9C%AF%E4%B8%80/</link><pubDate>Fri, 04 Apr 2025 00:00:00 +0000</pubDate><guid>https://blog.nicelylit.net/posts/%E8%99%9A%E6%8B%9F%E5%8C%96%E6%8A%80%E6%9C%AF%E4%B8%80/</guid><description>&lt;h3 id="为什么需要虚拟化"&gt;为什么需要虚拟化？
&lt;/h3&gt;&lt;p&gt;虚拟化可以对同一物理资源进行隔离处理，分给不同的用户使用，避免资源的闲置，提高资源的利用率。虚拟化是云计算的核心技术，云基础设施服务提供商对虚拟化的资源进行池化管理，通过资源的隔离和编排使得租用的用户能够在分钟级的时间内低成本获取到所需的资源，也提升了业务部署的灵活性。&lt;/p&gt;
&lt;p&gt;归纳起来有以下几点：1) 提升资源利用率，2) 降低成本，3) 屏蔽硬件差异，4) 提供资源隔离，5) 部署更灵活，6) 提升容灾能力。&lt;/p&gt;
&lt;h3 id="虚拟化技术为何得以持续发展"&gt;虚拟化技术为何得以持续发展？
&lt;/h3&gt;&lt;p&gt;资源的标准化和规模化提升了资源的获取效率和资源的利用率，相较于非标准化和小规模的资源建设和使用来说有了利润。算力是大数据处理、信息服务、人工智能的要素之一，应用场景涉及的领域广阔。云基础设施服务提供商能专注在标准化和规模化算力和平台建设上，成为整个社会进入智能化的推动引擎，而各领域的消费者能够专注在业务开发上面而减轻设施的维护开销。&lt;/p&gt;
&lt;h3 id="什么是虚拟化"&gt;什么是虚拟化？
&lt;/h3&gt;&lt;p&gt;虚拟化是一种资源管理技术，它将单台物理计算资源抽象、转换后呈现，分割成多台虚拟机、操作系统或者容器。&lt;/p&gt;
&lt;p&gt;虚拟化的资源类型可以从多种层次来看，最为核心和基础的是计算（CPU/GPU/内存）、存储（磁盘）、网络、I/O。从云服务商的资产管理角度看，有服务器、数据中心。从消费者角度看，有应用、数据、桌面。&lt;/p&gt;
&lt;p&gt;多数时候人们所说的虚拟化就是指服务器的虚拟化，简单理解就是在一台物理机上运行多台虚拟机。&lt;/p&gt;
&lt;h3 id="虚拟化和容器化有什么区别"&gt;虚拟化和容器化有什么区别？
&lt;/h3&gt;&lt;p&gt;两者之所以值得比较，是因为虚拟化和容器化的结果都是一个可供应用运行的计算环境。从虚拟的层次来看，虚拟化通常是直接对物理资源的虚拟化，而容器化是&lt;a class="link" href="https://en.wikipedia.org/wiki/Virtualization#Containerization" target="_blank" rel="noopener"
 &gt;操作系统级别的虚拟化&lt;/a&gt;，也有一种说法是&lt;a class="link" href="https://aws.amazon.com/what-is/virtualization/?nc1=h_ls" target="_blank" rel="noopener"
 &gt;应用级别的虚拟化&lt;/a&gt;。虚拟机上可以安装容器，但反之却不可以。&lt;/p&gt;
&lt;p&gt;容器化来自于操作系统的一个功能，内核允许存在多个隔离的用户空间的实例，这个实例被称作容器，或者分区，或者虚拟环境（VEs），又或者监狱（FreeBSD jails）。运行在操作系统中的程序可以看到计算机所有的资源，包括连接的设备、文件和文件夹、网络共享、CPU性能等，而运行在容器中的程序只能看到容器的内容和分配给容器的设备。从使用场景来看，容器化更轻量，更易扩展，更容易移植。容器化的代表是Docker。&lt;/p&gt;
&lt;h3 id="虚拟化和模拟仿真有什么区别"&gt;虚拟化和模拟、仿真有什么区别？
&lt;/h3&gt;&lt;p&gt;虚拟化（Virtualization）、模拟（Simulation）和仿真（Emulation）都是为了构建一个运行环境，一般都是为了构建一个区别于物理实体的逻辑实体。不同之处在于构建的目的，虚拟化是为了提升硬件资源的利用率，通常是用于生产环境的，而模拟和仿真是为了测试和研究，性能往往较差。&lt;/p&gt;</description></item><item><title>MaxCompute SQL的数组字段的合并</title><link>https://blog.nicelylit.net/posts/maxcompute-sql%E7%9A%84%E6%95%B0%E7%BB%84%E5%AD%97%E6%AE%B5%E7%9A%84%E5%90%88%E5%B9%B6/</link><pubDate>Sun, 09 Feb 2025 00:00:00 +0000</pubDate><guid>https://blog.nicelylit.net/posts/maxcompute-sql%E7%9A%84%E6%95%B0%E7%BB%84%E5%AD%97%E6%AE%B5%E7%9A%84%E5%90%88%E5%B9%B6/</guid><description>&lt;p&gt;在处理字段分组聚合时，如果需要多层次的聚合，有时还需要在新的层次进行该字段的合并，但SQL语言并没有提供直接的语法和简单的函数进行支持，经过&lt;code&gt;MAP_UNION&lt;/code&gt;的去重操作，结合其他的一些数组转字典的操作，可以实现该功能。具体来说，已知表1中有两行数据&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;c1&lt;/th&gt;
 &lt;th&gt;c2&lt;/th&gt;
 &lt;th&gt;c3&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;s1&lt;/td&gt;
 &lt;td&gt;d1&lt;/td&gt;
 &lt;td&gt;r1,r2&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;s1&lt;/td&gt;
 &lt;td&gt;d2&lt;/td&gt;
 &lt;td&gt;r1,r3&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;怎么得到表2&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;c1&lt;/th&gt;
 &lt;th&gt;c2&lt;/th&gt;
 &lt;th&gt;c3&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;s1&lt;/td&gt;
 &lt;td&gt;d1,d2&lt;/td&gt;
 &lt;td&gt;r1,r2,r3&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;得到表2的数据，最直接的思路是通过&lt;code&gt;GROUP BY&lt;/code&gt;进行分组聚合，c2列可以用过&lt;code&gt;COLLECT_SET&lt;/code&gt;函数外加&lt;code&gt;ARRAY_JOIN&lt;/code&gt;实现。对于c3列，需要先&lt;code&gt;SPLIT&lt;/code&gt;成数组，然后再分组合并。查询&lt;a class="link" href="https://help.aliyun.com/zh/maxcompute/user-guide/built-in-functions/?spm=a2c4g.11186623.help-menu-27797.d_2_1_3_2.ca5647a5Ye54gn&amp;amp;scm=20140722.H_455448._.OR_help-T_cn~zh-V_1" target="_blank" rel="noopener"
 &gt;MaxCompute SQL的函数手册&lt;/a&gt;，在数组方面并没有这样的功能。随后看到&lt;code&gt;MAP_UNION&lt;/code&gt;的键可以去重，转而想到把数组转换成字典，合并字典的键后，再提取键转为数组，具体的代码可以参考：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WITH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test_table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s1&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;d1&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;r1,r2&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;UNION&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s1&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;d2&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;r1,r3&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ARRAY_JOIN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;COLLECT_SET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ARRAY_JOIN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MAP_KEYS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MAP_UNION&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MAP_FROM_ARRAYS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SPLIT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ARRAY_REPEAT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SIZE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SPLIT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)))))),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test_table&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;GROUP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;另外一种思路是设法让表1回到表3的状态，然后再对c3通过&lt;code&gt;COLLECT_SET&lt;/code&gt;函数外加&lt;code&gt;ARRAY_JOIN&lt;/code&gt;来实现。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;c1&lt;/th&gt;
 &lt;th&gt;c2&lt;/th&gt;
 &lt;th&gt;c3&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;s1&lt;/td&gt;
 &lt;td&gt;d1&lt;/td&gt;
 &lt;td&gt;r1&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;s1&lt;/td&gt;
 &lt;td&gt;d1&lt;/td&gt;
 &lt;td&gt;r2&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;s1&lt;/td&gt;
 &lt;td&gt;d2&lt;/td&gt;
 &lt;td&gt;r1&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;s1&lt;/td&gt;
 &lt;td&gt;d2&lt;/td&gt;
 &lt;td&gt;r3&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;在MaxCompute SQL中，可以用&lt;a class="link" href="https://help.aliyun.com/zh/maxcompute/user-guide/lateral-view" target="_blank" rel="noopener"
 &gt;&lt;code&gt;LATERAL VIEW&lt;/code&gt;&lt;/a&gt;语句结合&lt;a class="link" href="https://help.aliyun.com/zh/maxcompute/user-guide/explode?spm=a2c4g.11186623.help-menu-search-27797.d_0" target="_blank" rel="noopener"
 &gt;&lt;code&gt;EXPLODE&lt;/code&gt;&lt;/a&gt;函数来实现。具体的代码可以参考：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WITH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test_table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s1&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;d1&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;r1,r2&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;UNION&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s1&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;d2&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;r1,r3&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ARRAY_JOIN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;COLLECT_SET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ARRAY_JOIN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;COLLECT_SET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;TRIM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c3_item&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test_table&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;LATERAL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VIEW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EXPLODE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SPLIT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c3_item&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;GROUP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Git初识</title><link>https://blog.nicelylit.net/posts/git%E5%88%9D%E8%AF%86/</link><pubDate>Wed, 06 May 2015 00:00:00 +0000</pubDate><guid>https://blog.nicelylit.net/posts/git%E5%88%9D%E8%AF%86/</guid><description>&lt;h5 id="为什么要进行版本控制"&gt;为什么要进行版本控制？
&lt;/h5&gt;&lt;p&gt;我们需要记录对一些文档的编辑历史，特别是当多人合作编辑同一个文档时。有了这些编辑历史的记录，不仅能够方便查看更改，同时也能够回滚到过去的某个版本。&lt;/p&gt;
&lt;h5 id="版本控制系统有哪些应用"&gt;版本控制系统有哪些应用？
&lt;/h5&gt;&lt;p&gt;版本控制多用在代码管理中，但也有其他的应用，比如Google Docs、Wikipedia History等。&lt;/p&gt;
&lt;h5 id="版本控制系统经历了怎样的演进"&gt;版本控制系统经历了怎样的演进？
&lt;/h5&gt;&lt;p&gt;简单说是从本地化版本控制系统（Local Version Control System）到中心化版本控制系统（Centralized Version Control System），再到分布式版本控制系统（Distributed Version Control System）。&lt;/p&gt;
&lt;p&gt;最初的版本控制用于本地的文档管理，通过一个数据库来记录修改前后的差异，被称作本地化版本控制系统（Local Version Control System, LVCS）。这种系统无法支持多人间的协作，进而产生了中心化版本控制系统（Centralized Version Control System, CVCS），将版本管理的数据库移到服务器端。CVCS中，客户端程序都只能够与服务器端进行同步，一旦服务器出现故障，所有的客户端程序都无法使用，服务器端的存储结构和历史记录也都可能丢失。分布式版本控制系统（Distributed Version Control System, DVCS），通过在每个客户端都克隆一个完整的服务器存储结构，从而解决了前面的问题。&lt;/p&gt;
&lt;h5 id="每种不同的版本控制系统有哪些代表"&gt;每种不同的版本控制系统有哪些代表？
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;LVCS：RCS&lt;/li&gt;
&lt;li&gt;CVCS：CSV, Subversion, Perforce&lt;/li&gt;
&lt;li&gt;DVCS：Git, Mercurial, Bazaar or Darcs&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="分布式的版本控制系统是否等于本地化的版本控制系统加上中心化的版本控制系统"&gt;分布式的版本控制系统是否等于本地化的版本控制系统加上中心化的版本控制系统？
&lt;/h5&gt;&lt;p&gt;功能上可以这样讲，但实现逻辑有着很大的不同。（&lt;strong&gt;怎样的实现逻辑呢？&lt;/strong&gt;）不管是本地化还是中心化的VCS，主要记录的是修改文件之间的差异（又称补丁，differences or patches）。若要获得某个版本，就等于将很多的差异文件相加。分布式的VCS，记录的是每次提交的完整文件，常被称作快照（snapshots）。（&lt;strong&gt;这两种方式各自有哪些优缺点呢？&lt;/strong&gt;）记录差异的优点在于磁盘空间消耗小，但获得不同的版本需要较多的运算。记录快照的优点在于获得不同的版本与对比版本差异计算都很快，缺点在于磁盘空间消耗大。由于磁盘空间现如今都不会是瓶颈，所以这个缺点基本可以忽略。分布式的版本控制系统带来的好处更多，所以越来越流行，特别是Git。&lt;/p&gt;
&lt;h5 id="git是怎样记录文件的"&gt;Git是怎样记录文件的？
&lt;/h5&gt;&lt;p&gt;Git用SHA-1算法产生的40位长的校验码（checksum）记录所有的文件。具体讲是对每个被提交过的文件执行SHA-1算法，生成校验码作为该文件的名称或者身份，Git主要管理这些校验码。实际上不仅每个文件被执行SHA-1算法，每次的提交（commit）操作也会生成一个校验码，所以只要是提交过的内容，都有办法进行恢复。&lt;/p&gt;
&lt;h5 id="git的基本结构是怎样的"&gt;Git的基本结构是怎样的？
&lt;/h5&gt;&lt;p&gt;Git管理的文件会有三种状态：已提交（committed）、已修改（modified）、已跟进（staged）。已提交是指文件已经被保存在了本地的仓库中。已修改是指已提交过的文件有了新的修改但还没有提交。已跟进是准备提交前的一种状态。对应于三种状态，Git内部被分为三个区域，本地工作区（Working Directory）、跟进区又称缓存区（Staging Area）、本地仓库（Git directory）。已提交的文件记录在了本地仓库，已修改的文件仅位于本地工作区，而已跟进的文件位于跟进区。本地工作区是我们工作交互的区域，编辑修改的文件都位于这个区域，而提交前需要先做一步跟进，放在跟进区才能够提交。&lt;/p&gt;
&lt;h5 id="怎么样获取git"&gt;怎么样获取Git？
&lt;/h5&gt;&lt;p&gt;&lt;a class="link" href="http://git-scm.com/download/linux" target="_blank" rel="noopener"
 &gt;Linux&lt;/a&gt;: sudo yum install git （Redhat系列） sudo apt-get install git （Debian系列） &lt;a class="link" href="http://git-scm.com/download/mac" target="_blank" rel="noopener"
 &gt;Mac&lt;/a&gt;和&lt;a class="link" href="http://git-scm.com/download/windows" target="_blank" rel="noopener"
 &gt;Windows&lt;/a&gt;: 直接从Git网站下载安装包或者在GitHub网站下载安装包&lt;/p&gt;
&lt;h5 id="初次使用git需要做哪些配置呢"&gt;初次使用Git需要做哪些配置呢？
&lt;/h5&gt;&lt;p&gt;Git对每次的提交都会记录提交者的名字和邮箱，所以初次使用需要进行配置。此外，Git的许多命令都会调用编辑器进行交互，所以也需要配置默认的编辑器。&lt;/p&gt;
&lt;h5 id="怎么做这些配置呢"&gt;怎么做这些配置呢？
&lt;/h5&gt;&lt;p&gt;配置前需要简单明确Git对用户的配置信息有三个层次的管理：&lt;code&gt;/etc/gitconfig&lt;/code&gt;、&lt;code&gt;~/.gitconfig&lt;/code&gt;、&lt;code&gt;.git/config&lt;/code&gt;。三个层次后一个层次覆盖前一个，比如在&lt;code&gt;~/.gitconfig&lt;/code&gt;和&lt;code&gt;/etc/gitconfig&lt;/code&gt;配置了同一个属性，&lt;code&gt;~/.gitconfig&lt;/code&gt;会生效。&lt;code&gt;/etc/gitconfig&lt;/code&gt;的修改会影响所有系统用户，&lt;code&gt;~/.gitconfig&lt;/code&gt;只影响当前用户，&lt;code&gt;.git/config&lt;/code&gt;只影响当前的项目包。具体可以直接编辑这三个文件，或者通过命令行完成。举例：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --global user.name &lt;span class="s2"&gt;&amp;#34;Jon Doe&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;配置文件中都是以键值对存储配置，例如&lt;code&gt;user.name=&amp;quot;Jon Doe&amp;quot;&lt;/code&gt;。&lt;code&gt;--global&lt;/code&gt;表示设置在&lt;code&gt;~/.gitconfig&lt;/code&gt;中，&lt;code&gt;--system&lt;/code&gt;表示设置在&lt;code&gt;/etc/gitconfig&lt;/code&gt;中。&lt;/p&gt;
&lt;h5 id="如何确定当前项目包的配置情况呢"&gt;如何确定当前项目包的配置情况呢？
&lt;/h5&gt;&lt;p&gt;执行命令&lt;code&gt;git config --list&lt;/code&gt;。&lt;/p&gt;
&lt;h5 id="git中怎么获得命令的帮助"&gt;Git中怎么获得命令的帮助？
&lt;/h5&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git &lt;span class="nb"&gt;help&lt;/span&gt; &amp;lt;verb&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这段文字改写自《Pro Git》一书的第二版第一章Introduction部分。阅读过程中，发现写得非常流畅，是本值得力荐的好书。这里的改写仅用作回顾，不推荐直接学习，原书中有很多图示的说明更加直观。&lt;/p&gt;</description></item></channel></rss>