<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>ZooKeeper on 小盒子的技术分享</title><link>https://xiaobox.github.io/tags/zookeeper/</link><description>Recent content in ZooKeeper on 小盒子的技术分享</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Fri, 14 Mar 2025 09:19:52 +0000</lastBuildDate><atom:link href="https://xiaobox.github.io/tags/zookeeper/index.xml" rel="self" type="application/rss+xml"/><item><title>数据库选型终极指南：从数据类型到应用场景，一篇就够了</title><link>https://xiaobox.github.io/p/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/</link><pubDate>Fri, 14 Mar 2025 09:19:52 +0000</pubDate><guid>https://xiaobox.github.io/p/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/cover.jpg" alt="Featured image of post 数据库选型终极指南：从数据类型到应用场景，一篇就够了" /&gt;&lt;h2 id="引言"&gt;&lt;a href="#%e5%bc%95%e8%a8%80" class="header-anchor"&gt;&lt;/a&gt;引言
&lt;/h2&gt;&lt;p&gt;在当今的数字化时代，数据已成为企业和组织的核心资产。无论是金融交易记录、社交媒体互动、物联网传感器数据，还是企业内部的业务流程信息，都需要通过数据库进行存储、管理和分析。然而，面对市场上数十种主流的数据库技术（如 MySQL、MongoDB、Elasticsearch、HBase、Hive等），如何选择适合自身业务需求的数据库系统，成为许多技术决策者面临的难题。本文将深入探讨数据库的核心分类、技术特性、应用场景以及选择策略，帮助读者构建系统化的选型框架。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="数据库的分类"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e5%ba%93%e7%9a%84%e5%88%86%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;数据库的分类
&lt;/h2&gt;&lt;p&gt;在进行数据库的选择前，你需要至少知道它的&lt;strong&gt;分类&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;在数据库技术的演进过程中，数据存储模型和应用需求的多样性催生了不同类型的数据库系统。这些系统根据其核心设计理念、数据组织方式以及适用场景的差异，形成了多个分类。&lt;/p&gt;
&lt;h3 id="关系型数据库rdbms结构化数据的基石"&gt;&lt;a href="#%e5%85%b3%e7%b3%bb%e5%9e%8b%e6%95%b0%e6%8d%ae%e5%ba%93rdbms%e7%bb%93%e6%9e%84%e5%8c%96%e6%95%b0%e6%8d%ae%e7%9a%84%e5%9f%ba%e7%9f%b3" class="header-anchor"&gt;&lt;/a&gt;关系型数据库（RDBMS）：结构化数据的基石
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;关系型数据库的根基是关系代数和集合论&lt;/strong&gt;，通过二维表（Table）组织数据。每个表由行（记录）和列（字段）构成，通过主键（Primary Key）唯一标识记录，外键（Foreign Key）实现表间的关联。其核心优势在于ACID事务支持，即原子性（Atomicity）、一致性（Consistency）、隔离性（Isolation）、持久性（Durability），适用于对数据一致性要求极高的场景（如金融交易）&lt;/p&gt;
&lt;p&gt;适用场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;需要强一致性的业务系统（银行核心系统、ERP）。&lt;/li&gt;
&lt;li&gt;多表关联查询频繁的OLTP（联机事务处理）场景（电商订单管理）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;局限性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;表结构预定义，修改成本高（如新增字段需 ALTER TABLE）。&lt;/li&gt;
&lt;li&gt;水平扩展困难，分库分表复杂度高（需处理分布式事务和跨分片查询）。&lt;/li&gt;
&lt;li&gt;不适合存储半结构化数据（如JSON文档、嵌套数组）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;代表数据库：&lt;code&gt;MySQL&lt;/code&gt;、&lt;code&gt;PostgreSQL&lt;/code&gt;、&lt;code&gt;Oracle&lt;/code&gt;、&lt;code&gt;SQL Server&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="nosql-数据库灵活性与扩展性的革命"&gt;&lt;a href="#nosql-%e6%95%b0%e6%8d%ae%e5%ba%93%e7%81%b5%e6%b4%bb%e6%80%a7%e4%b8%8e%e6%89%a9%e5%b1%95%e6%80%a7%e7%9a%84%e9%9d%a9%e5%91%bd" class="header-anchor"&gt;&lt;/a&gt;NoSQL 数据库：灵活性与扩展性的革命
&lt;/h3&gt;&lt;p&gt;NoSQL（Not Only SQL）的诞生是为了解决关系型数据库在扩展性、灵活性和高性能场景下的不足。根据数据模型的差异，NoSQL 可进一步细分为四类：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 文档型数据库（Document Database）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;数据模型：以文档为基本单元，通常采用JSON或BSON格式存储，支持嵌套结构和动态字段&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;user_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;张三&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;orders&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;order_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;amount&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;150.0&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;order_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2002&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;amount&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;300.0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;查询能力：支持基于文档属性的查询，部分数据库（如MongoDB）提供类SQL的聚合管道（Aggregation Pipeline）和索引优化。&lt;/p&gt;
&lt;p&gt;适用场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;内容管理系统（CMS）中文章的多版本存储。&lt;/li&gt;
&lt;li&gt;用户配置文件的动态字段管理（如社交平台用户的个性化标签）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;局限性：跨文档事务支持较弱（MongoDB 4.0后支持多文档事务，但性能损耗较大）。&lt;/p&gt;
&lt;p&gt;代表数据库：&lt;code&gt;MongoDB&lt;/code&gt;、&lt;code&gt;Couchbase&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 键值型数据库（Key-Value Store）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;数据模型：最简单的 NoSQL 模型，数据以键值对（Key-Value）形式存储，Value可以是任意二进制数据。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;Key: &amp;#34;user:101:profile&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;Value: &amp;#34;{&amp;#39;name&amp;#39;: &amp;#39;李四&amp;#39;, &amp;#39;last_login&amp;#39;: &amp;#39;2023-10-01&amp;#39;}&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;高性能特性：通过哈希表实现O(1)时间复杂度的读写操作，适合缓存和高并发场景。&lt;/p&gt;
&lt;p&gt;适用场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;会话存储（Session Storage）：快速存取用户登录状态。&lt;/li&gt;
&lt;li&gt;分布式缓存（如Redis缓存热门商品信息）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;局限性：缺乏复杂查询能力（仅能通过Key检索），需业务层处理数据关联逻辑。&lt;/p&gt;
&lt;p&gt;代表数据库：&lt;code&gt;Redis&lt;/code&gt;、&lt;code&gt;Memcached&lt;/code&gt;、&lt;code&gt;Amazon DynamoDB&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. 列族数据库（Wide-Column Store）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;数据模型：数据按列族（Column Family）组织，每行可动态添加列，适合稀疏矩阵存储。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;Row Key: &amp;#34;device_001&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;Columns: 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;metrics:temperature&amp;#34; -&amp;gt; 25.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;metrics:humidity&amp;#34; -&amp;gt; 60%
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;location:city&amp;#34; -&amp;gt; &amp;#34;北京&amp;#34; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;存储优势：基于LSM树（Log-Structured Merge Tree）的存储引擎，优化高吞吐写入（如日志、传感器数据）。&lt;/p&gt;
&lt;p&gt;适用场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;时间序列数据（物联网设备监控）。&lt;/li&gt;
&lt;li&gt;海量数据的随机读写（如HBase存储网页爬虫数据）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;局限性：复杂查询需依赖Row Key设计，二级索引支持有限。&lt;/p&gt;
&lt;p&gt;代表数据库：&lt;code&gt;Apache HBase&lt;/code&gt;、&lt;code&gt;Cassandra&lt;/code&gt;、&lt;code&gt;Google Bigtable&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. 图数据库（Graph Database）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;数据模型：以图论为基础，通过节点（Node）、边（Edge）、属性（Property）表示实体及其关系。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;Node: User(id=101, name=&amp;#34;王五&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;Edge: User101 -[FRIEND]-&amp;gt; User102 (since=2020)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;/ul&gt;
&lt;p&gt;局限性：非关系场景下性能无明显优势，学习曲线陡峭。&lt;/p&gt;
&lt;p&gt;代表数据库：&lt;code&gt;Neo4j&lt;/code&gt;、&lt;code&gt;Amazon Neptune&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="大数据生态数据库分布式与批量处理的支柱"&gt;&lt;a href="#%e5%a4%a7%e6%95%b0%e6%8d%ae%e7%94%9f%e6%80%81%e6%95%b0%e6%8d%ae%e5%ba%93%e5%88%86%e5%b8%83%e5%bc%8f%e4%b8%8e%e6%89%b9%e9%87%8f%e5%a4%84%e7%90%86%e7%9a%84%e6%94%af%e6%9f%b1" class="header-anchor"&gt;&lt;/a&gt;大数据生态数据库：分布式与批量处理的支柱
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;1. 分布式列式存储（HBase）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;技术架构：基于HDFS的分布式存储，通过Region分片实现水平扩展，ZooKeeper协调元数据。&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;/ul&gt;
&lt;p&gt;适用场景：实时查询TB级数据（如电信通话记录检索）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 数据仓库（Hive）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;技术原理：将结构化数据映射为HDFS文件，通过 HiveQL（类SQL）转换为MapReduce或Tez任务。&lt;/p&gt;
&lt;p&gt;核心能力：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;离线批量处理（小时级延迟）。&lt;/li&gt;
&lt;li&gt;复杂ETL流程（数据清洗、转换）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;适用场景：历史数据报表生成（如零售业月度销售分析）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. 实时数仓（ClickHouse、Doris）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;技术突破：向量化执行引擎、列式存储、预聚合，实现亚秒级响应。&lt;/p&gt;
&lt;p&gt;适用场景：交互式OLAP分析（如广告投放效果实时看板）。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/001-609ddd79.png"&gt;&lt;/p&gt;
&lt;h3 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h3&gt;&lt;p&gt;我们做一个整体的对比&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/002-4df3e69a.png"&gt;&lt;/p&gt;
&lt;p&gt;随着技术发展，数据库的界限逐渐模糊。例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;多模型数据库：如PostgreSQL通过扩展支持JSONB（文档模型）和Citus（分布式能力）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;HTAP&lt;/code&gt;(Hybrid Transactional/Analytical Processing)数据库：TiDB、Oracle Exadata支持OLTP与OLAP混合负载。&lt;/li&gt;
&lt;li&gt;AI驱动数据库：利用机器学习优化查询计划（如Google AlloyDB）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;随着 AI 技术的兴起，&lt;code&gt;向量数据库&lt;/code&gt;也是非常热门的一类数据库。数据库的分类也并非绝对的技术壁垒，而是反映了不同场景下的核心矛盾权衡：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;结构化 vs 灵活性&lt;/strong&gt;：关系型牺牲灵活性换取严格约束，文档型反之。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;一致性 vs 扩展性&lt;/strong&gt;：CP系统（如ZooKeeper）优先保障一致性，AP系统（如Cassandra）优先保障可用性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实时性 vs 吞吐量&lt;/strong&gt;：HBase优化单点查询延迟，Hive优化批量吞吐量。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;理解这些分类背后的哲学，才能避免“技术选型中的锤子效应”（手里只有一把锤子，看所有问题都是钉子），从而在复杂业务场景中构建合理的数据存储架构。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="数据类型"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e7%b1%bb%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;数据类型
&lt;/h2&gt;&lt;p&gt;在进行数据库的选择前，你要处理的数据类型是你必须要明确的。&lt;/p&gt;
&lt;p&gt;结构化、半结构化和非结构化数据在存储、查询和处理方式上存在本质差异，直接影响了技术选型的路径。&lt;/p&gt;
&lt;p&gt;在数据管理的实践中，数据类型是决定数据库选型的关键因素之一。结构化、半结构化和非结构化数据在存储、查询和处理方式上存在本质差异，直接影响了技术选型的路径。以下从数据特征、处理需求到典型数据库选择展开系统性分析。&lt;/p&gt;
&lt;h3 id="结构化数据秩序与约束的领域"&gt;&lt;a href="#%e7%bb%93%e6%9e%84%e5%8c%96%e6%95%b0%e6%8d%ae%e7%a7%a9%e5%ba%8f%e4%b8%8e%e7%ba%a6%e6%9d%9f%e7%9a%84%e9%a2%86%e5%9f%9f" class="header-anchor"&gt;&lt;/a&gt;结构化数据：秩序与约束的领域
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;1. 核心特征&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;严格模式（Schema）：数据字段预先定义，类型明确（如整数、日期、枚举值）。&lt;/li&gt;
&lt;li&gt;二维表结构：数据以行和列的形式组织，遵循第一范式（1NF）到第三范式（3NF）的规范。&lt;/li&gt;
&lt;li&gt;强关联性：通过外键建立表间关系，支持JOIN操作实现跨表查询。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;示例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;银行账户表：&lt;code&gt;账户ID (主键) | 户主姓名 | 余额 | 开户日期&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;电商订单表：&lt;code&gt;订单ID | 用户ID (外键) | 商品ID (外键) | 订单金额 | 支付状态&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2. 数据库选择&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;首选：关系型数据库（RDBMS）。它的选型逻辑：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;事务完整性：需要ACID保障的场景（如转账操作）。&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;MySQL/PostgreSQL：适用于中小规模OLTP系统。&lt;/li&gt;
&lt;li&gt;Oracle：企业级高并发、高可靠性需求（如金融核心系统）。&lt;/li&gt;
&lt;li&gt;TiDB：分布式架构下仍需强一致性的场景（如跨境支付平台）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. 反模式案例&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;错误尝试：将用户行为日志（半结构化JSON）存入MySQL。这样做的问题是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;需要为动态字段创建稀疏列，导致存储空间浪费。&lt;/li&gt;
&lt;li&gt;频繁ALTER TABLE修改表结构，引发锁表风险。&lt;/li&gt;
&lt;li&gt;查询嵌套字段需解析JSON字符串，性能低下。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="半结构化数据灵活性与动态性的平衡"&gt;&lt;a href="#%e5%8d%8a%e7%bb%93%e6%9e%84%e5%8c%96%e6%95%b0%e6%8d%ae%e7%81%b5%e6%b4%bb%e6%80%a7%e4%b8%8e%e5%8a%a8%e6%80%81%e6%80%a7%e7%9a%84%e5%b9%b3%e8%a1%a1" class="header-anchor"&gt;&lt;/a&gt;半结构化数据：灵活性与动态性的平衡
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;1. 核心特征&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;松散模式：字段可动态增减，数据类型允许一定灵活性。&lt;/li&gt;
&lt;li&gt;层次化结构：数据以树形或网状形式组织（如JSON、XML）。&lt;/li&gt;
&lt;li&gt;自描述性：数据本身携带元信息（如字段名称、嵌套关系）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;示例：用户配置文件&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;user_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;preferences&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;theme&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;dark&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;notifications&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;email&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;sms&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;last_activity&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;login&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2023-10-05T08:30:00Z&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;purchase&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;item_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;SKU123&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;设备传感器元数据：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;device&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;D001&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;location&lt;/span&gt; &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;39.9042&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;lon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;116.4074&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;sensors&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;sensor&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;temperature&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;unit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;°C&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;sensor&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;humidity&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;unit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;%&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;sensors&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;device&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;2. 数据库选择&lt;/strong&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;/ul&gt;
&lt;p&gt;代表方案：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;MongoDB：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;适用场景：CMS内容管理、物联网设备元数据存储。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;优势：BSON二进制存储、聚合管道、地理位置索引。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;限制：事务跨文档操作成本高（需4.0+版本）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cassandra：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;适用场景：时间序列数据（如日志事件流）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;优势：高写入吞吐、多数据中心复制。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;限制：查询必须指定分区键，二级索引效率低。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Elasticsearch：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;适用场景：日志分析、全文检索（如电商商品搜索）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;优势：倒排索引、近实时搜索、分词器定制。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;限制：写入吞吐受分片数限制，不支持事务。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. 混合架构实践&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;典型组合：MySQL + MongoDB + Elasticsearch。 数据流示例：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用户注册信息（结构化）存入MySQL。&lt;/li&gt;
&lt;li&gt;用户行为轨迹（半结构化JSON）写入MongoDB。&lt;/li&gt;
&lt;li&gt;关键字段（如用户ID、行为类型）同步到Elasticsearch供快速检索。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="非结构化数据海量与多元化的挑战"&gt;&lt;a href="#%e9%9d%9e%e7%bb%93%e6%9e%84%e5%8c%96%e6%95%b0%e6%8d%ae%e6%b5%b7%e9%87%8f%e4%b8%8e%e5%a4%9a%e5%85%83%e5%8c%96%e7%9a%84%e6%8c%91%e6%88%98" class="header-anchor"&gt;&lt;/a&gt;非结构化数据：海量与多元化的挑战
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;1. 核心特征&lt;/strong&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;/ul&gt;
&lt;p&gt;示例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;媒体文件：监控摄像头的1080P视频流（MP4格式）。&lt;/li&gt;
&lt;li&gt;办公文档：PDF合同、Word报告。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2. 数据库选择&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;核心矛盾：非结构化数据的管理重点不是“查询”，而是“存储与访问”。它的选型逻辑：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;存储效率：需支持大文件分块存储（如HDFS的128MB块）。&lt;/li&gt;
&lt;li&gt;元数据管理：通过附加结构化信息实现快速检索。&lt;/li&gt;
&lt;li&gt;访问接口：提供HTTP API或对象存储接口（如S3兼容）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;代表方案：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;对象存储：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Amazon S3/阿里云OSS：存储图片、视频等静态资源。&lt;/li&gt;
&lt;li&gt;MinIO：自建私有化对象存储方案。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="3"&gt;
&lt;li&gt;分布式文件系统：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;HDFS：用于Hadoop生态的原始文件存储。&lt;/li&gt;
&lt;li&gt;Ceph：统一存储池支持块、文件、对象接口。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="5"&gt;
&lt;li&gt;专用数据库扩展：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;MongoDB GridFS：将大文件分块存储为文档。&lt;/li&gt;
&lt;li&gt;PostgreSQL大对象（LOB）：通过TOAST机制存储二进制数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. 元数据关联策略&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;典型架构是：对象存储 + 关系型数据库。分两步：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;数据流：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;上传视频文件到S3，获得存储路径&lt;code&gt;s3://bucket/video_001.mp4&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;在MySQL中创建记录：&lt;/li&gt;
&lt;/ul&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="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;media_files&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="ln"&gt;2&lt;/span&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s3_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uploader_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;resolution&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="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;VALUES&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="ln"&gt;4&lt;/span&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="mi"&gt;1001&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;s3://bucket/video_001.mp4&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;501&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&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;1920x1080&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;
&lt;li&gt;查询过程：&lt;/li&gt;
&lt;/ol&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="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 查找用户501上传的高清视频
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&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;s3_path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;media_files&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="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uploader_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;501&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;1920x1080&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="总结-1"&gt;&lt;a href="#%e6%80%bb%e7%bb%93-1" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h3&gt;&lt;p&gt;总结一下不同数据类型的特点&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/003-ff369010.png"&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;/ul&gt;
&lt;p&gt;说了这么多，虽然对于数据是什么类型有了比较清楚的定义和区分，但是数据到底是结构化的还是非结构化的，其实&lt;strong&gt;主要是看 “数据的组织方式”和“处理方式”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这里举个例子，比如 &lt;code&gt;用户评论&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;如果我们只是想简单的读写用户评论，可以把它用关系型数据库存储，当作一个表中的一个字段:&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;在评论内容（CommentContent）这个字段中，我们可以存储用户的评论文本。对于包含的表情、图片等多媒体元素，也有一些常见的处理方法。例如，把表情转换为编码存储，而图片可以存储在文件服务器上，并在数据库中保存链接地址。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;如果把用户评论当成非结构化数据，那么它的&lt;strong&gt;处理方式&lt;/strong&gt;就会更加复杂。&lt;/p&gt;
&lt;p&gt;用户评论的内容通常是文本信息，但其实不容易进行有效的结构化处理。评论的长度、格式、语言等都可能差异很大，甚至某些评论可能包含表情符号或者图片等多媒体元素。这些元素都无法通过预定义的数据模型进行有效地分类和组织，因此我们将其当做非结构化数据来处理。&amp;ndash;这里主要是指数据的&lt;strong&gt;组织方式&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;以下是一些具体的例子：&lt;/p&gt;
&lt;ol&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;p&gt;具体实现架构如下：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/004-560fe49f.png"&gt;&lt;/p&gt;
&lt;p&gt;用户评论的存储与分析系统需结合多种技术实现高效处理。在存储层设计中，推荐采用混合存储架构以满足非结构化数据的持久化需求。核心存储使用MongoDB文档数据库保存完整的评论内容（如文本、表情编码、图片链接等），其灵活的JSON结构支持动态字段扩展，例如可包含用户设备信息、地理位置等元数据。同时，MongoDB的水平扩展能力和聚合查询功能可有效支持大规模数据管理。对于评论中的图片、视频等二进制文件，则通过对象存储（如Amazon S3或阿里云OSS）存储，结合预签名URL实现安全访问，避免数据库性能损耗。辅助索引层采用Elasticsearch同步关键字段，通过倒排索引和中文分词技术（如IK分词）实现秒级全文检索，并支持模糊搜索与高亮显示。&lt;/p&gt;
&lt;p&gt;在场景化应用中，情感分析可通过多种技术实现：对于中文评论，SnowNLP或Hugging Face的BERT模型能精准识别情感倾向，例如通过预训练模型对“电池续航太差”等文本输出负面标签及置信度评分。评论分类则结合监督学习（如SVM、BERT）与无监督方法（如K-Means聚类），通过FastAPI构建实时分类服务或使用Spark进行批量处理。全文搜索功能由Elasticsearch支撑，通过MongoDB Connector实现实时数据同步，支持用户快速定位包含特定关键词的评论内容。主题模型则利用LDA、BERTopic等算法从海量评论中提取高频主题（如“屏幕质量”“物流服务”），并通过WordCloud等工具可视化呈现，帮助业务方洞察用户关注焦点。整个架构通过混合存储与多技术协同，在保证性能的同时实现成本优化。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="应用场景"&gt;&lt;a href="#%e5%ba%94%e7%94%a8%e5%9c%ba%e6%99%af" class="header-anchor"&gt;&lt;/a&gt;应用场景
&lt;/h2&gt;&lt;p&gt;数据库选型的核心是：理解业务数据的生命周期，把握各类数据库的能力边界，在架构灵活性与技术可控性之间寻找最佳平衡点。任何脱离具体业务场景的数据库对比都是无效的，优秀的架构设计应当像精密钟表般，让每个齿轮（数据库）在最适合的位置发挥最大效能。&lt;/p&gt;
&lt;p&gt;结合典型应用场景，什么场景应该用什么数据库呢？其实在一个业务场景下需要多种类数据库结合使用，总结如下：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/005-00b9fa8f.png"&gt;&lt;/p&gt;
&lt;p&gt;我们以单个数据库为维度再分别讨论一下：&lt;/p&gt;
&lt;h3 id="关系型mysql"&gt;&lt;a href="#%e5%85%b3%e7%b3%bb%e5%9e%8bmysql" class="header-anchor"&gt;&lt;/a&gt;关系型:MySQL
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/006-22a3aff1.png"&gt;&lt;/p&gt;
&lt;p&gt;MySQL：高并发事务系统（如电商订单处理）&lt;/p&gt;
&lt;p&gt;核心场景：电商平台的订单系统，需要保证每笔交易的原子性（如扣减库存、生成订单、支付记录必须同时成功或回滚）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择MySQL&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ACID事务支持：通过InnoDB引擎实现强一致性，确保订单状态的准确性。&lt;/li&gt;
&lt;li&gt;复杂查询能力：支持多表JOIN（如查询用户历史订单及商品详情）。&lt;/li&gt;
&lt;li&gt;成熟生态：主从复制、分库分表工具（如ShardingSphere）支持高可用和扩展。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;对比其他数据库&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;：不支持跨文档事务（早期版本），不适合强一致性场景。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Redis&lt;/strong&gt;：内存数据库，无法持久化复杂事务逻辑。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：每秒处理10万笔订单的电商平台，通过MySQL分库分表（按用户ID哈希）实现横向扩展。&lt;/p&gt;
&lt;h3 id="搜索引擎es"&gt;&lt;a href="#%e6%90%9c%e7%b4%a2%e5%bc%95%e6%93%8ees" class="header-anchor"&gt;&lt;/a&gt;搜索引擎：ES
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/007-559c2219.png"&gt;&lt;/p&gt;
&lt;p&gt;Elasticsearch：实时商品搜索与日志分析&lt;/p&gt;
&lt;p&gt;核心场景：电商平台商品搜索，用户输入关键词（如“防水运动鞋”）后毫秒级返回结果。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择Elasticsearch&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;倒排索引&lt;/strong&gt;：快速匹配关键词，支持分词、同义词扩展、模糊查询。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;聚合分析&lt;/strong&gt;：统计商品类目的平均评分、价格区间分布。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;近实时（NRT）&lt;/strong&gt;：新上架商品1秒内可被搜索。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;对比其他数据库&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MySQL&lt;/strong&gt;：全文索引性能差，无法支持高并发搜索。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;：文本搜索功能简单，缺乏分词器和相关性排序。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某跨境电商平台，每日处理1亿次搜索请求，通过ES集群（分片+副本）实现99.9%的查询响应时间&amp;lt;50ms。&lt;/p&gt;
&lt;h3 id="文档型mongodb"&gt;&lt;a href="#%e6%96%87%e6%a1%a3%e5%9e%8bmongodb" class="header-anchor"&gt;&lt;/a&gt;文档型：MongoDB
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/008-6afc9d95.png"&gt;&lt;/p&gt;
&lt;p&gt;MongoDB：内容管理系统（CMS）与动态配置存储**&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心场景&lt;/strong&gt;：新闻发布平台的文章存储，每篇文章包含标题、正文、多级评论、动态标签。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择MongoDB&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;灵活文档模型&lt;/strong&gt;：存储嵌套结构的JSON数据（如评论树形结构）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;水平扩展&lt;/strong&gt;：通过Sharding自动分配数据到多个分片。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;局部更新&lt;/strong&gt;：修改文章某个字段无需重写整个文档。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;对比其他数据库&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MySQL&lt;/strong&gt;：需要拆分为多张表（文章表、评论表），JOIN查询效率低。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HBase&lt;/strong&gt;：适合结构化扫描，不适合嵌套数据查询。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某媒体平台存储1000万篇文章，每篇文章包含动态标签（如“科技, 2023趋势”），通过MongoDB的文档结构直接存储。&lt;/p&gt;
&lt;h3 id="键值存储redis"&gt;&lt;a href="#%e9%94%ae%e5%80%bc%e5%ad%98%e5%82%a8redis" class="header-anchor"&gt;&lt;/a&gt;键值存储：Redis
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/009-116b15b9.png"&gt;&lt;/p&gt;
&lt;p&gt;Redis：高频访问缓存与会话管理&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心场景&lt;/strong&gt;：社交平台的热门帖子缓存，用户访问时优先从缓存读取，减少数据库压力。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择Redis&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;内存存储&lt;/strong&gt;：读写延迟&amp;lt;1ms，支持每秒百万级操作。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据结构丰富&lt;/strong&gt;：使用Sorted Set存储热门帖子排行榜，Hash存储用户会话信息。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;持久化可选&lt;/strong&gt;：RDB快照或AOF日志保障数据安全。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;对比其他数据库&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MySQL&lt;/strong&gt;：磁盘存储，无法满足毫秒级响应。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;：内存占用高，不适合纯缓存场景。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某论坛每日活跃用户500万，通过Redis缓存前1000热门帖子，命中率90%，数据库负载下降70%。&lt;/p&gt;
&lt;h3 id="宽列存储hbasecassandra"&gt;&lt;a href="#%e5%ae%bd%e5%88%97%e5%ad%98%e5%82%a8hbasecassandra" class="header-anchor"&gt;&lt;/a&gt;宽列存储：HBase、Cassandra
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/010-9e144a87.png"&gt;&lt;/p&gt;
&lt;p&gt;HBase：海量时序数据存储（如物联网设备监控）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心场景&lt;/strong&gt;：电力公司存储智能电表每秒采集的电流、电压数据。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择HBase&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;列族存储&lt;/strong&gt;：按列压缩时序数据，节省存储空间。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;随机读写&lt;/strong&gt;：按设备ID+时间戳快速查询某时刻数据。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HDFS集成&lt;/strong&gt;：数据自动下沉至HDFS实现低成本归档。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;对比其他数据库&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cassandra&lt;/strong&gt;：适合跨数据中心写入，但单点查询性能不如HBase。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MySQL&lt;/strong&gt;：无法支持每秒百万级数据写入。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某物联网平台每日新增1TB传感器数据，通过HBase的RowKey设计（设备ID+时间戳）实现毫秒级查询。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/011-87d2288b.png"&gt;&lt;/p&gt;
&lt;p&gt;Cassandra：多数据中心日志同步（如全球化应用）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心场景&lt;/strong&gt;：跨国社交应用的聊天日志存储，要求数据在欧美亚三地就近写入且最终一致。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择Cassandra&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;多活架构&lt;/strong&gt;：数据自动复制到多个数据中心，写入本地即成功。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;高吞吐写入&lt;/strong&gt;：LSM树引擎支持每秒百万级写入。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;无单点故障&lt;/strong&gt;：去中心化架构避免主从瓶颈。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;对比其他数据库&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;HBase&lt;/strong&gt;：依赖HDFS和ZooKeeper，扩展性受限。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MySQL&lt;/strong&gt;：主从复制跨地域延迟高。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某IM应用每日处理50亿条消息，通过Cassandra实现三地数据中心写入延迟&amp;lt;10ms。&lt;/p&gt;
&lt;h3 id="数据仓库hive"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e4%bb%93%e5%ba%93hive" class="header-anchor"&gt;&lt;/a&gt;数据仓库：Hive
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/012-a845c0c5.png"&gt;&lt;/p&gt;
&lt;p&gt;Hive：离线数据仓库与ETL批处理&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心场景&lt;/strong&gt;：零售企业每月销售数据的批量清洗与报表生成。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择Hive&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SQL兼容&lt;/strong&gt;：通过HiveQL实现类SQL查询，降低学习成本。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;海量数据批处理&lt;/strong&gt;：基于MapReduce或Tez引擎处理TB级数据。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;低成本存储&lt;/strong&gt;：数据存储在HDFS，支持压缩格式（ORC、Parquet）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;对比其他数据库&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ClickHouse&lt;/strong&gt;：适合实时分析，但存储成本高。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MySQL&lt;/strong&gt;：无法处理PB级数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某电商每月分析10TB历史订单数据，通过Hive生成“年度区域销售趋势”报表，耗时2小时。&lt;/p&gt;
&lt;h3 id="列式存储clickhouse"&gt;&lt;a href="#%e5%88%97%e5%bc%8f%e5%ad%98%e5%82%a8clickhouse" class="header-anchor"&gt;&lt;/a&gt;列式存储：ClickHouse
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/013-c7953de3.png"&gt;&lt;/p&gt;
&lt;p&gt;ClickHouse：实时OLAP与用户行为分析&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心场景&lt;/strong&gt;：广告平台的实时点击流分析，每日处理千亿级事件，生成实时报表。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择ClickHouse&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;列式存储&lt;/strong&gt;：压缩率高，适合聚合计算（如SUM、COUNT）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;向量化执行&lt;/strong&gt;：利用CPU SIMD指令加速查询。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实时写入&lt;/strong&gt;：支持Kafka直接导入数据，延迟低至秒级。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;对比其他数据库&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hive&lt;/strong&gt;：批处理模式，查询延迟分钟级。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MySQL&lt;/strong&gt;：无法支撑海量数据聚合。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某广告平台分析每日200亿次点击事件，通过ClickHouse集群实现“过去1小时各渠道转化率”秒级响应。&lt;/p&gt;
&lt;h3 id="图数据库neo4j"&gt;&lt;a href="#%e5%9b%be%e6%95%b0%e6%8d%ae%e5%ba%93neo4j" class="header-anchor"&gt;&lt;/a&gt;图数据库：Neo4j
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/014-d3af3ea6.png"&gt;&lt;/p&gt;
&lt;p&gt;Neo4j：社交网络关系挖掘（如好友推荐）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心场景&lt;/strong&gt;：社交平台的“六度关系”分析，计算用户A到用户B的最短路径。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择Neo4j&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;图遍历优化&lt;/strong&gt;：通过原生图存储引擎高效遍历多跳关系。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cypher查询语言&lt;/strong&gt;：直观表达复杂关系模式（如查找共同好友）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实时更新&lt;/strong&gt;：支持动态添加节点和边。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;对比其他数据库&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MySQL&lt;/strong&gt;：需递归JOIN，性能随跳数指数级下降。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;：无法直接表达关系网络。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某社交平台分析10亿用户关系，Neo4j可在毫秒级返回“用户A的三度人脉中可能认识的人”。&lt;/p&gt;
&lt;h3 id="总结-2"&gt;&lt;a href="#%e6%80%bb%e7%bb%93-2" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;事务强一致&lt;/strong&gt; → MySQL&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实时搜索&lt;/strong&gt; → Elasticsearch&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;动态文档&lt;/strong&gt; → MongoDB&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;高频缓存&lt;/strong&gt; → Redis&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实时OLAP&lt;/strong&gt; → ClickHouse&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;时序海量存储&lt;/strong&gt; → HBase&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;全球化写入&lt;/strong&gt; → Cassandra&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;关系网络&lt;/strong&gt; → Neo4j&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;离线批处理&lt;/strong&gt; → Hive&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/015-95068fb0.png"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="最后总结"&gt;&lt;a href="#%e6%9c%80%e5%90%8e%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;最后总结
&lt;/h2&gt;&lt;p&gt;**数据模型的本质差异是选型的第一道分水岭。**关系型数据库（如MySQL、PostgreSQL）建立在严格的二维表结构之上，通过外键约束和范式理论保障数据完整性。这种结构特别适合需要复杂关联查询的财务系统、ERP等业务场景。例如银行转账操作需要严格遵循ACID事务原则，MySQL的InnoDB引擎通过行级锁和MVCC机制实现事务隔离，配合主从复制架构可以满足多数金融级需求。但在物联网设备日志存储场景下，每天千万级的写入请求会导致关系型数据库的索引维护成本急剧上升，此时文档型数据库MongoDB的BSON自由格式和分片集群优势便显现出来。MongoDB的写操作默认不等待磁盘确认，通过内存映射文件实现高速写入，特别适合内容管理系统或实时分析场景中半结构化数据的快速摄入。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;分布式架构的CAP权衡直接影响系统可用性。&lt;/strong&gt; Elasticsearch作为分布式搜索引擎，其倒排索引结构对文本检索的优化已达到毫秒级响应，在电商商品搜索、日志分析等场景具有不可替代性。但ES的强一致性模型可能导致集群脑裂风险，需要结合zen discovery机制进行节点状态管理。相比之下，HBase作为Hadoop生态的列式存储，通过RegionServer的水平扩展和LSM树的写入优化，能够承载PB级数据量的实时读写。某智慧城市项目曾使用HBase存储数十亿条交通卡口数据，利用其行键有序分布特性实现车辆轨迹的快速回溯，这是传统关系型数据库难以企及的吞吐能力。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;计算与存储的分离趋势重构了数据分析范式。&lt;/strong&gt; Hive建立在HDFS之上的元数据管理机制，通过类SQL语法实现大数据集的离线分析，其分区表和桶表的设计显著提升了TB级数据查询效率。某电商平台的历史订单分析采用Hive进行月度销售统计，配合Tez执行引擎将任务耗时从小时级压缩到分钟级。但Hive的高延迟特性使其不适合实时查询场景，这正是ClickHouse等OLAP数据库的突破方向。需要特别注意的是，数据湖架构的兴起使得Delta Lake、Hudi等解决方案开始融合事务管理和批流一体处理，这对传统数仓选型提出了新的挑战。&lt;/p&gt;
&lt;p&gt;**事务完整性与系统弹性的平衡艺术。**当业务需要跨数据库操作时，如电商订单系统同时涉及MySQL库存扣减和MongoDB订单日志记录，分布式事务管理就成为关键挑战。Saga模式通过补偿机制实现最终一致性，而Seata框架的AT模式能在业务侵入性较低的情况下保障事务边界。但在高并发场景下，这类方案的性能损耗可能达到20%-30%，这就需要架构师在一致性级别和系统吞吐之间做出权衡。例如社交平台的点赞功能更适合使用Redis的原子计数器，完全放弃强一致性以换取百万级QPS的处理能力。&lt;/p&gt;
&lt;p&gt;**硬件成本与运维复杂度的隐藏成本。**云原生时代，AWS Aurora通过计算存储分离架构实现了MySQL兼容数据库的自动扩缩容，其存储层可自动扩展到128TB，这种托管服务显著降低了运维负担。但对于需要定制化优化的场景，如金融行业的风控模型计算，仍需要基于物理机部署的Oracle RAC集群来保障IOPS性能。开源方案的隐性成本同样不容忽视，Elasticsearch集群的JVM堆内存配置直接影响索引性能，不当的分片设置可能导致磁盘空间浪费，这需要运维团队积累足够的调优经验。&lt;/p&gt;
&lt;p&gt;在具体选型实践中，建议采用四维评估法：首先明确数据结构化程度（结构化、半结构化、非结构化），其次分析读写比例和并发量级，再次确定一致性要求（强一致、最终一致），最后考量扩展性和生态集成需求。例如智能穿戴设备数据采集场景，设备标识符作为MongoDB文档的天然主键，时间序列数据采用嵌套文档存储，既避免了关系型数据库的表关联开销，又利用TTL索引实现自动过期清理。而在用户画像分析场景，HBase 的宽表结构可以存储数千个用户标签，配合Phoenix的SQL层实现灵活查询，这种架构组合充分发挥了列式存储的高压缩比优势。&lt;/p&gt;
&lt;p&gt;最后我们用一个简单的流程图来说明一下这个选型过程：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/016-d55b1bf4.png"&gt;&lt;/p&gt;</description></item><item><title>ZooKeeper 并没有直接采用 Paxos 算法</title><link>https://xiaobox.github.io/p/2022-05-23-zookeeper-bing-mei-you-zhi-jie-cai-yong-paxos-suan-fa/</link><pubDate>Mon, 23 May 2022 07:58:58 +0000</pubDate><guid>https://xiaobox.github.io/p/2022-05-23-zookeeper-bing-mei-you-zhi-jie-cai-yong-paxos-suan-fa/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2022-05-23-zookeeper-bing-mei-you-zhi-jie-cai-yong-paxos-suan-fa/cover.jpg" alt="Featured image of post ZooKeeper 并没有直接采用 Paxos 算法" /&gt;&lt;p&gt;ZooKeeper 并没有直接采用 Paxos 算法，而是采用一种被称为 ZAB（ZooKeeper Atomic Broadcast）的一致性协议&lt;/p&gt;
&lt;p&gt;Paxos 算法是基于消息传递的分布式一致性算法，很多大型的网络技术公司和开源框架都采用 Paxos 算法作为其各自的底层解决方案，比如 Chubby 、 Megastore 以及 MySQL Group Replication 。Paxos 算法运行在服务器发生宕机故障的时候，能够保证数据的完整性，不要求可靠的消息传递，可容忍消息丢失、延迟、乱序以及重复，保证服务的高可用性。&lt;/p&gt;
&lt;p&gt;ZAB 协议并不像 Paxos 算法那样，一种通用的分布式一致性算法，而是一种特别为 ZooKeeper 设计的崩溃可恢复的原子消息广播算法&lt;/p&gt;
&lt;p&gt;当 Leader 服务器不可用或者已经不存在过半服务器与该 Leader 服务器保持正常通信时，在重新开始新一轮的原子广播事务操作之前，ZAB 会进入恢复模式选举新的 Leader 服务器，使集群彼此达到一个一致的状态，从消息广播模式进入到崩溃恢复模式。当集群过半机器都与新的 Leader 服务器完成了状态同步操作后 ZAB 协议会退出恢复模式&lt;/p&gt;
&lt;p&gt;两者相同之处是，在执行事务会话的处理中，两种算法最开始都需要一台服务器或者线程针对该会话，在集群中发起提案或是投票。只有当集群中的过半数服务器对该提案投票通过后，才能执行接下来的处理。&lt;/p&gt;
&lt;p&gt;而 Paxos 算法与 ZAB 协议不同的是，Paxos 算法的发起者可以是一个或多个。当集群中的 Acceptor 服务器中的大多数可以执行会话请求后，提议者服务器只负责发送提交指令，事务的执行实际发生在 Acceptor 服务器。这与 ZooKeeper 服务器上事务的执行发生在 Leader 服务器上不同。Paxos 算法在数据同步阶段，是多台 Acceptor 服务器作为数据源同步给集群中的多台 Learner 服务器，而 ZooKeeper 则是单台 Leader 服务器作为数据源同步给集群中的其他角色服务器。&lt;/p&gt;
&lt;h2 id="参考"&gt;&lt;a href="#%e5%8f%82%e8%80%83" class="header-anchor"&gt;&lt;/a&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.cnblogs.com/aspirant/p/13423780.html" target="_blank" rel="noopener"
 &gt;https://www.cnblogs.com/aspirant/p/13423780.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/ZooKeeper%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E4%B8%8E%E5%AE%9E%E6%88%98-%E5%AE%8C/30%20ZAB%20%E4%B8%8E%20Paxos%20%E7%AE%97%E6%B3%95%E7%9A%84%E8%81%94%E7%B3%BB%E4%B8%8E%E5%8C%BA%E5%88%AB.md" target="_blank" rel="noopener"
 &gt;https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/ZooKeeper%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E4%B8%8E%E5%AE%9E%E6%88%98-%E5%AE%8C/30%20ZAB%20%E4%B8%8E%20Paxos%20%E7%AE%97%E6%B3%95%E7%9A%84%E8%81%94%E7%B3%BB%E4%B8%8E%E5%8C%BA%E5%88%AB.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Redis 分布式解决方案</title><link>https://xiaobox.github.io/p/2022-01-25-redis-fen-bu-shi-jie-jue-fang-an/</link><pubDate>Tue, 25 Jan 2022 10:12:53 +0000</pubDate><guid>https://xiaobox.github.io/p/2022-01-25-redis-fen-bu-shi-jie-jue-fang-an/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2022-01-25-redis-fen-bu-shi-jie-jue-fang-an/cover.jpg" alt="Featured image of post Redis 分布式解决方案" /&gt;&lt;h2 id="概述"&gt;&lt;a href="#%e6%a6%82%e8%bf%b0" class="header-anchor"&gt;&lt;/a&gt;概述
&lt;/h2&gt;&lt;p&gt;在 Redis 3.0 之前，集群方案一般为两种：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;客户端分区方案&lt;/li&gt;
&lt;li&gt;代理方案&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;3.0 之后官方提供了专有的集群方案 Redis Cluster。&lt;/p&gt;
&lt;p&gt;将数据集分散到多个节点上，每个节点负责整体的一部分，即为数据分区。分区就会涉及到分区规则，Redis 常用的是哈希分区规则，哈希分区规则比较常见的有&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;节点取余分区&lt;/li&gt;
&lt;li&gt;一致性 hash 算法&lt;/li&gt;
&lt;li&gt;虚拟槽分区&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="客户端分区"&gt;&lt;a href="#%e5%ae%a2%e6%88%b7%e7%ab%af%e5%88%86%e5%8c%ba" class="header-anchor"&gt;&lt;/a&gt;客户端分区
&lt;/h2&gt;&lt;p&gt;也叫客户端分片（Smart Client）如下图所示，为一个客户端分区方案。&lt;/p&gt;
&lt;p&gt;通过 sentinel 实现集群高可用，分区逻辑在客户端实现&lt;/p&gt;
&lt;p&gt;优点是：分区逻辑可控。缺点是：需要自己处理数据路由、高可用、故障转移等问题。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2022-01-25-redis-fen-bu-shi-jie-jue-fang-an/001-7ca19af4.jpg"&gt;&lt;/p&gt;
&lt;p&gt;分区规则可用 节点取余 hash&lt;/p&gt;
&lt;h3 id="节点取余-hash"&gt;&lt;a href="#%e8%8a%82%e7%82%b9%e5%8f%96%e4%bd%99-hash" class="header-anchor"&gt;&lt;/a&gt;节点取余 hash
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2022-01-25-redis-fen-bu-shi-jie-jue-fang-an/002-60e64509.jpg"&gt;&lt;/p&gt;
&lt;p&gt;节点取余方式优点：&lt;/p&gt;
&lt;ul&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;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2022-01-25-redis-fen-bu-shi-jie-jue-fang-an/003-4041d899.jpg"&gt;&lt;/p&gt;
&lt;h2 id="代理方案"&gt;&lt;a href="#%e4%bb%a3%e7%90%86%e6%96%b9%e6%a1%88" class="header-anchor"&gt;&lt;/a&gt;代理方案
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2022-01-25-redis-fen-bu-shi-jie-jue-fang-an/004-31f53808.jpg"&gt;&lt;/p&gt;
&lt;p&gt;代理分区方案一般由中间件实现 例如早已开源的 Codis，下图是 Codis 的架构图：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2022-01-25-redis-fen-bu-shi-jie-jue-fang-an/005-2f45da00.jpg"&gt;&lt;/p&gt;
&lt;p&gt;codis-proxy 是无状态的，可以比较容易的搭多个实例，达到高可用性和横向扩展。&lt;/p&gt;
&lt;p&gt;对 Java 用户来说，可以使用基于 Jedis 的实现 Jodis ，来实现 proxy 层的 HA：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;它会通过监控 zookeeper 上的注册信息来实时获得当前可用的 proxy 列表，既可以保证高可用性；&lt;/li&gt;
&lt;li&gt;也可以通过轮流请求所有的 proxy 实现负载均衡。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这种方案有很多优点，因为支持原生 redis 协议，所以客户端不需要升级，对业务比较友好。并且升级相对平滑，可以起多个 Proxy 后，逐个进行升级。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;Codis 是一个分布式 Redis 解决方案，对于上层的应用来说，连接到 Codis Proxy 和连接原生的 Redis Server 没有显著区别 （不支持的命令列表）, 上层应用可以像使用单机的 Redis 一样使用，Codis 底层会处理请求的转发，不停机的数据迁移等工作，所有后边的一切事情，对于前面的客户端来说是透明的，可以简单的认为后边连接的是一个内存无限大的 Redis 服务。&lt;/p&gt;
&lt;p&gt;”&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;但是缺点是，因为会多一次跳转，会有性能开销。&lt;/p&gt;
&lt;p&gt;这里我们再讨论另外一种 分区规则：一致性 hash 算法&lt;/p&gt;
&lt;h3 id="一致性-hash-算法"&gt;&lt;a href="#%e4%b8%80%e8%87%b4%e6%80%a7-hash-%e7%ae%97%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;一致性 hash 算法
&lt;/h3&gt;&lt;p&gt;上面讨论的节点取余分区方式的主要缺点是：&lt;code&gt;数据节点伸缩时，导致数据迁移&lt;/code&gt;，换句话说，当缓存服务器数量发生变化时，可能会导致大量缓存同一时间失效，几乎所有缓存的位置都会发生改变。 所以 &lt;code&gt;迁移数量和添加节点数据有关，建议翻倍扩容&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;一致性 hash 算法在一定程度上解决了这个问题，它的实现思路是：为系统中每个节点分配一个 token, 范围是 0 到 2 的 32 次方，这些 token 构成一个哈希环，如下图所示。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2022-01-25-redis-fen-bu-shi-jie-jue-fang-an/006-95964eb6.jpg"&gt;&lt;/p&gt;
&lt;p&gt;每一个数据节点分配一个 token 范围值，这个节点就负责保存这个范围内的数据。数据读写执行节点查找操作时，先根据 key 计算 hash 值，然后顺时针找到第一个大于等于该哈希值的 token 节点（沿顺时针方向遇到的第一个服务器）。&lt;/p&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;/ul&gt;
&lt;p&gt;上述缺点中第二、三点尤其重要，原因是缓存分布的极度不均匀（负载不均衡），这种情况被称之为 &lt;code&gt;hash 环的偏斜&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;应该怎样防止 hash 环的偏斜呢？一致性 hash 算法中使用“虚拟节点”解决了这个问题。&lt;/p&gt;
&lt;p&gt;“虚拟节点”是”实际节点”（实际的物理服务器）在 hash 环上的复制品，一个实际节点可以对应多个虚拟节点。&lt;/p&gt;
&lt;p&gt;例如：我们以 2 个副本 NodeA、NodeB 为例，为每台服务器计算三个虚拟节点，于是可以分别计算 “Node A#1”、“Node A#2”、“Node A#3”、“Node B#1”、“Node B#2”、“Node B#3”的哈希值，于是形成六个虚拟节点：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2022-01-25-redis-fen-bu-shi-jie-jue-fang-an/007-c0d261e1.jpg"&gt;&lt;/p&gt;
&lt;p&gt;当然，如果你需要，也可以虚拟出更多的虚拟节点。引入虚拟节点的概念后，缓存的分布就均衡多了。hash 环上的节点就越多，缓存被均匀分布的概率就越大。&lt;/p&gt;
&lt;h2 id="redis-cluster"&gt;&lt;a href="#redis-cluster" class="header-anchor"&gt;&lt;/a&gt;Redis Cluster
&lt;/h2&gt;&lt;p&gt;在简介 Redis Cluster 之前，先聊一聊它采用的分区规则，即&lt;code&gt;虚拟槽分区&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="虚拟槽分区"&gt;&lt;a href="#%e8%99%9a%e6%8b%9f%e6%a7%bd%e5%88%86%e5%8c%ba" class="header-anchor"&gt;&lt;/a&gt;虚拟槽分区
&lt;/h3&gt;&lt;p&gt;Redis Cluster 采用虚拟槽分区，所有的键根据哈希函数映射到 &lt;code&gt;0～16383&lt;/code&gt; 个整数槽内，计算公式 &lt;code&gt;slot = CRC16(key) &amp;amp; 16383&lt;/code&gt;，每个节点负责维护一部分槽以及槽所映射的键值数据。采用大范围槽的主要目的是为了方便数据拆分和集群扩展&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2022-01-25-redis-fen-bu-shi-jie-jue-fang-an/008-36d1d421.jpg"&gt;&lt;/p&gt;
&lt;p&gt;当前集群有 5 个节点，每个节点平均大约负责 3276 个槽。由于采用高质量的哈希算法，每个槽所映射的数据通常比较均匀，将数据平均划分到 5 个节点进行数据分区。&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;/ul&gt;
&lt;h3 id="redis-cluster-1"&gt;&lt;a href="#redis-cluster-1" class="header-anchor"&gt;&lt;/a&gt;Redis Cluster
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Redis Cluster 集群节点最小配置 6 个节点以上（3 主 3 从），其中主节点提供读写操作，从节点作为备用节点，不提供请求，只作为故障转移使用。&lt;/li&gt;
&lt;li&gt;自动将数据进行分片，每个 master 上放一部分数据&lt;/li&gt;
&lt;li&gt;提供内置的高可用支持，部分 master 不可用时，还是可以继续工作的&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2022-01-25-redis-fen-bu-shi-jie-jue-fang-an/009-082dad68.jpg"&gt;&lt;/p&gt;
&lt;p&gt;集群由 N 组主从 Redis Instance 组成。主可以没有从，但是没有从 意味着主宕机后主负责的 Slot 读写服务不可用。一个主可以有多个从，主宕机时，某个从会被提升为主，具体哪个从被提升为主，协议类似于 Raft。&lt;/p&gt;
&lt;p&gt;如何检测主宕机？&lt;/p&gt;
&lt;p&gt;Redis Cluster 采用 quorum+心跳的机制。从节点的角度看，节点会定期给其他所有的节点发送 Ping，cluster-node-timeout（可配置，秒级）时间内没有收到对方的回复，则单方面认为对端节点宕机，将该节点标为 PFAIL 状态。通过节点之间交换信息收集到 quorum 个节点都认为这个节点为 PFAIL，则将该节点标记为 FAIL，并且将其发送给其他所有节点，其他所有节点收到后立即认为该节点宕机。从这里可以看出，主宕机后，至少 cluster-node-timeout 时间内该主所负责的 Slot 的读写服务不可用。&lt;/p&gt;
&lt;p&gt;与 Sentinal 的区别？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Redis Sentinal 着眼于高可用，在 master 宕机时会自动将 slave 提升为 master，继续提供服务。&lt;/li&gt;
&lt;li&gt;Redis Cluster 着眼于扩展性，在单个 redis 内存不足时，使用 Cluster 进行分片存储。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考"&gt;&lt;a href="#%e5%8f%82%e8%80%83" class="header-anchor"&gt;&lt;/a&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://codeantenna.com/a/qWY48A0q83" target="_blank" rel="noopener"
 &gt;https://codeantenna.com/a/qWY48A0q83&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/CodisLabs/codis" target="_blank" rel="noopener"
 &gt;https://github.com/CodisLabs/codis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.zsythink.net/archives/1182" target="_blank" rel="noopener"
 &gt;https://www.zsythink.net/archives/1182&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://mp.weixin.qq.com/s/aIP9jHPysTn1LNzz9F85zQ" target="_blank" rel="noopener"
 &gt;https://mp.weixin.qq.com/s/aIP9jHPysTn1LNzz9F85zQ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Kubernetes监控体系总结</title><link>https://xiaobox.github.io/p/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/</link><pubDate>Mon, 15 Nov 2021 12:21:02 +0000</pubDate><guid>https://xiaobox.github.io/p/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/cover.jpg" alt="Featured image of post Kubernetes监控体系总结" /&gt;&lt;h2 id="基本概念"&gt;&lt;a href="#%e5%9f%ba%e6%9c%ac%e6%a6%82%e5%bf%b5" class="header-anchor"&gt;&lt;/a&gt;基本概念
&lt;/h2&gt;&lt;h3 id="cadvisor"&gt;&lt;a href="#cadvisor" class="header-anchor"&gt;&lt;/a&gt;cAdvisor
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/001-46ee78b3.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Docker 是一个开源的应用容器引擎，让开发者可以打包他们的应用以及依赖包到一个可移植的容器中，然后发布到任何流行的 Linux/Windows/Mac 机器上。容器镜像正成为一个新的标准化软件交付方式。为了能够获取到 Docker 容器的运行状态，用户可以通过 Docker 的 stats 命令获取到当前主机上运行容器的统计信息，可以查看容器的 CPU 利用率、内存使用量、网络 IO 总量以及磁盘 IO 总量等信息。&lt;/p&gt;
&lt;p&gt;显然如果我们想对监控数据做存储以及可视化的展示，那么 docker 的 stats 是不能满足的。&lt;/p&gt;
&lt;p&gt;为了解决 docker stats 的问题（存储、展示），谷歌开源的 cadvisor 诞生了，cadvisor 不仅可以搜集一台机器上所有运行的容器信息，还提供基础查询界面和 http 接口，方便其他组件如 Prometheus 进行数据抓取，或者 cAdvisor + influxDB + grafana 搭配使用。cAdvisor 可以对节点机器上的资源及容器进行实时监控和性能数据采集，包括 CPU 使用情况、内存使用情况、网络吞吐量及文件系统使用情况&lt;/p&gt;
&lt;p&gt;监控原理&lt;/p&gt;
&lt;p&gt;cAdvisor 使用 Go 语言开发，利用 Linux 的 cgroups 获取容器的资源使用信息，在 K8S 中集成在 Kubelet 里作为默认启动项，官方标配。&lt;/p&gt;
&lt;p&gt;Docker 是基于 Namespace、Cgroups 和联合文件系统实现的&lt;/p&gt;
&lt;p&gt;Cgroups 不仅可以用于容器资源的限制，还可以提供容器的资源使用率。不管用什么监控方案，底层数据都来源于 Cgroups&lt;/p&gt;
&lt;p&gt;Cgroups 的工作目录 /sys/fs/cgroup 下包含了 Cgroups 的所有内容。Cgroups 包含了很多子系统，可以对 CPU，内存，PID，磁盘 IO 等资源进行限制和监控。&lt;/p&gt;
&lt;p&gt;cAdvisor 运行原理，如下图&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/002-3731be65.jpg"&gt;&lt;/p&gt;
&lt;h3 id="prometheus"&gt;&lt;a href="#prometheus" class="header-anchor"&gt;&lt;/a&gt;Prometheus
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/003-9dea7ba3.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Prometheus 是一套开源的监控报警系统。主要特点包括多维数据模型、灵活查询语句 PromQL 以及数据可视化展示等&lt;/p&gt;
&lt;p&gt;架构图&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/004-b737ebd1.jpg"&gt;&lt;/p&gt;
&lt;p&gt;基本原理&lt;/p&gt;
&lt;p&gt;Prometheus 的基本原理是通过 HTTP 协议周期性抓取被监控组件的状态，任意组件只要提供对应的 HTTP 接口就可以接入监控。不需要任何 SDK 或者其他的集成过程。这样做非常适合做虚拟化环境监控系统，比如 VM、Docker、Kubernetes 等。输出被监控组件信息的 HTTP 接口被叫做 exporter 。目前互联网公司常用的组件大部分都有 exporter 可以直接使用，比如 Varnish、Haproxy、Nginx、MySQL、Linux 系统信息（包括磁盘、内存、CPU、网络等等）。&lt;/p&gt;
&lt;p&gt;服务过程&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prometheus Daemon 负责定时去目标上抓取 metrics（指标）数据，每个抓取目标需要暴露一个 http 服务的接口给它定时抓取。Prometheus 支持通过配置文件、文本文件、Zookeeper、Consul、DNS SRV Lookup 等方式指定抓取目标。Prometheus 采用 PULL 的方式进行监控，即服务器可以直接通过目标 PULL 数据或者间接地通过中间网关来 Push 数据。&lt;/li&gt;
&lt;li&gt;Prometheus 在本地存储抓取的所有数据，并通过一定规则进行清理和整理数据，并把得到的结果存储到新的时间序列中。&lt;/li&gt;
&lt;li&gt;Prometheus 通过 PromQL 和其他 API 可视化地展示收集的数据。Prometheus 支持很多方式的图表可视化，例如 Grafana、自带的 Promdash 以及自身提供的模版引擎等等。Prometheus 还提供 HTTP API 的查询方式，自定义所需要的输出。&lt;/li&gt;
&lt;li&gt;PushGateway 支持 Client 主动推送 metrics 到 PushGateway，而 Prometheus 只是定时去 Gateway 上抓取数据。&lt;/li&gt;
&lt;li&gt;Alertmanager 是独立于 Prometheus 的一个组件，可以支持 Prometheus 的查询语句，提供十分灵活的报警方式。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="operator"&gt;&lt;a href="#operator" class="header-anchor"&gt;&lt;/a&gt;Operator
&lt;/h3&gt;&lt;p&gt;Operator 是 CoreOS 推出的旨在简化复杂有状态应用管理的框架，它是一个感知应用状态的控制器，通过扩展 Kubernetes API 来自动创建、管理和配置应用实例。&lt;/p&gt;
&lt;p&gt;Operator 基于 CustomResourceDefinition(CRD) 扩展了新的应用资源，并通过控制器来保证应用处于预期状态。比如 etcd operator 通过下面的三个步骤模拟了管理 etcd 集群的行为：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;通过 Kubernetes API 观察集群的当前状态；&lt;/li&gt;
&lt;li&gt;分析当前状态与期望状态的差别；&lt;/li&gt;
&lt;li&gt;调用 etcd 集群管理 API 或 Kubernetes API 消除这些差别。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/005-15eafb88.jpg"&gt;&lt;/p&gt;
&lt;h3 id="prometheus-operator"&gt;&lt;a href="#prometheus-operator" class="header-anchor"&gt;&lt;/a&gt;Prometheus Operator
&lt;/h3&gt;&lt;p&gt;为了在 Kubernetes 能够方便的管理和部署 Prometheus，我们使用 ConfigMap 了管理 Prometheus 配置文件。每次对 Prometheus 配置文件进行升级时，我们需要手动移除已经运行的 Pod 实例，从而让 Kubernetes 可以使用最新的配置文件创建 Prometheus。而如果当应用实例的数量更多时，通过手动的方式部署和升级 Prometheus 过程繁琐并且效率低下。&lt;/p&gt;
&lt;p&gt;从本质上来讲 Prometheus 属于是典型的有状态应用，而其又包含了一些自身特有的运维管理和配置管理方式。而这些都无法通过 Kubernetes 原生提供的应用管理概念实现自动化。为了简化这类应用程序的管理复杂度，CoreOS 率先引入了 Operator 的概念，并且首先推出了针对在 Kubernetes 下运行和管理 Etcd 的 Etcd Operator。并随后推出了 Prometheus Operator。&lt;/p&gt;
&lt;p&gt;从概念上来讲 Operator 就是针对管理特定应用程序的，在 Kubernetes 基本的 Resource 和 Controller 的概念上，以扩展 Kubernetes api 的形式。帮助用户创建，配置和管理复杂的有状态应用程序。从而实现特定应用程序的常见操作以及运维自动化。&lt;/p&gt;
&lt;p&gt;在 Kubernetes 中我们使用 Deployment、DamenSet，StatefulSet 来管理应用 Workload，使用 Service，Ingress 来管理应用的访问方式，使用 ConfigMap 和 Secret 来管理应用配置。我们在集群中对这些资源的创建，更新，删除的动作都会被转换为事件 (Event)，Kubernetes 的 Controller Manager 负责监听这些事件并触发相应的任务来满足用户的期望。这种方式我们成为声明式，用户只需要关心应用程序的最终状态，其它的都通过 Kubernetes 来帮助我们完成，通过这种方式可以大大简化应用的配置管理复杂度。&lt;/p&gt;
&lt;p&gt;而除了这些原生的 Resource 资源以外，Kubernetes 还允许用户添加自己的自定义资源 (Custom Resource)。并且通过实现自定义 Controller 来实现对 Kubernetes 的扩展。&lt;/p&gt;
&lt;p&gt;如下所示，是 Prometheus Operator 的架构示意图：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/006-69c36f88.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Prometheus 的本职就是一组用户自定义的 CRD 资源以及 Controller 的实现，Prometheus Operator 负责监听这些自定义资源的变化，并且根据这些资源的定义自动化的完成如 Prometheus Server 自身以及配置的自动化管理工作。&lt;/p&gt;
&lt;p&gt;简言之，Prometheus Operator 能够帮助用户自动化的创建以及管理 Prometheus Server 以及其相应的配置。&lt;/p&gt;
&lt;h3 id="hpa"&gt;&lt;a href="#hpa" class="header-anchor"&gt;&lt;/a&gt;HPA
&lt;/h3&gt;&lt;p&gt;Horizontal Pod Autoscaler ，K8S 中的一个概念，可以自动调整 Pod 的数量，以达到指定的目标值。&lt;/p&gt;
&lt;p&gt;Pod 水平自动扩缩（Horizontal Pod Autoscaler） 可以基于 CPU 利用率自动扩缩 ReplicationController、Deployment、ReplicaSet 和 StatefulSet 中的 Pod 数量。除了 CPU 利用率，也可以基于其他应程序提供的 &lt;code&gt;自定义度量指标&lt;/code&gt;来执行自动扩缩。Pod 自动扩缩不适用于无法扩缩的对象，比如 DaemonSet。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/007-8dbad0a8.jpg"&gt;&lt;/p&gt;
&lt;h3 id="heapster"&gt;&lt;a href="#heapster" class="header-anchor"&gt;&lt;/a&gt;Heapster
&lt;/h3&gt;&lt;p&gt;Heapster 是容器集群监控和性能分析工具，天然的支持 Kubernetes 和 CoreOS。&lt;/p&gt;
&lt;p&gt;Heapster 首先从 K8S Master 获取集群中所有 Node 的信息，然后通过这些 Node 上的 kubelet 获取有用数据，而 kubelet 本身的数据则是从 cAdvisor 得到。所有获取到的数据都被推到 Heapster 配置的后端存储中，并还支持数据的可视化。现在后端存储 + 可视化的方法，如 InfluxDB + grafana。&lt;/p&gt;
&lt;p&gt;Heapster 可以收集 Node 节点上的 cAdvisor 数据，还可以按照 kubernetes 的资源类型来集合资源，比如 Pod、Namespace 域，可以分别获取它们的 CPU、内存、网络和磁盘的 metric。默认的 metric 数据聚合时间间隔是 1 分钟。&lt;/p&gt;
&lt;p&gt;注意 ：Kubernetes 1.11 不建议使用 Heapster，就 SIG Instrumentation 而言，这是为了转向新的 Kubernetes 监控模型的持续努力的一部分。仍使用 Heapster 进行自动扩展的集群应迁移到 metrics-server 和自定义指标 API。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/008-cd80d35d.jpg"&gt;&lt;/p&gt;
&lt;h3 id="metrics-server"&gt;&lt;a href="#metrics-server" class="header-anchor"&gt;&lt;/a&gt;Metrics Server
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/009-f72ed8af.jpg"&gt;&lt;/p&gt;
&lt;p&gt;kubernetes 集群资源监控之前可以通过 &lt;code&gt;heapster&lt;/code&gt; 来获取数据，在 &lt;code&gt;1.11&lt;/code&gt; 开始开始逐渐废弃 &lt;code&gt;heapster&lt;/code&gt; 了，采用 &lt;code&gt;metrics-server&lt;/code&gt; 来代替，&lt;code&gt;metrics-server&lt;/code&gt; 是集群的核心监控数据的聚合器，它从 kubelet 公开的 Summary API 中采集指标信息，&lt;code&gt;metrics-server&lt;/code&gt; 是扩展的 APIServer，依赖于 kube-aggregator，因为我们需要在 APIServer 中开启相关参数。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Metrics Server&lt;/code&gt; 并不是 kube-apiserver 的一部分，而是通过 Aggregator 这种插件机制，在独立部署的情况下同 kube-apiserver 一起统一对外服务的。&lt;/p&gt;
&lt;p&gt;Aggregator&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;通过聚合层扩展 Kubernetes API使用聚合层（Aggregation Layer），用户可以通过额外的 API 扩展 Kubernetes， 而不局限于 Kubernetes 核心 API 提供的功能。这里的附加 API 可以是现成的解决方案比如 metrics server, 或者你自己开发的 API。聚合层不同于 定制资源（Custom Resources）。后者的目的是让 kube-apiserver 能够认识新的对象类别（Kind）。&lt;/p&gt;
&lt;p&gt;”&lt;/p&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;聚合层聚合层在 kube-apiserver 进程内运行。在扩展资源注册之前，聚合层不做任何事情。要注册 API，用户必须添加一个 APIService 对象，用它来“申领” Kubernetes API 中的 URL 路径。自此以后，聚合层将会把发给该 API 路径的所有内容（例如 /apis/myextension.mycompany.io/v1/…） 转发到已注册的 APIService。&lt;/p&gt;
&lt;p&gt;”&lt;/p&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;APIService 的最常见实现方式是在集群中某 Pod 内运行 扩展 API 服务器。如果你在使用扩展 API 服务器来管理集群中的资源，该扩展 API 服务器（也被写成“extension-apiserver”） 一般需要和一个或多个控制器一起使用。apiserver-builder 库同时提供构造扩展 API 服务器和控制器框架代码。&lt;/p&gt;
&lt;p&gt;”&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;这里，Aggregator APIServer 的工作原理，可以用如下所示的一幅示意图来表示清楚 ：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/010-8e03d754.jpg"&gt;&lt;/p&gt;
&lt;p&gt;因为 k8s 的 api-server 将所有的数据持久化到了 etcd 中，显然 k8s 本身不能处理这种频率的采集，而且这种监控数据变化快且都是临时数据，因此需要有一个组件单独处理他们，于是 metric-server 的概念诞生了。&lt;/p&gt;
&lt;p&gt;Metrics server 出现后，新的 Kubernetes 监控架构将变成下图的样子&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;核心流程（黑色部分）：这是 Kubernetes 正常工作所需要的核心度量，从 Kubelet、cAdvisor 等获取度量数据，再由 metrics-server 提供给 Dashboard、HPA 控制器等使用。&lt;/li&gt;
&lt;li&gt;监控流程（蓝色部分）：基于核心度量构建的监控流程，比如 Prometheus 可以从 metrics-server 获取核心度量，从其他数据源（如 Node Exporter 等）获取非核心度量，再基于它们构建监控告警系统。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/011-c53d6287.jpg"&gt;&lt;/p&gt;
&lt;p&gt;注意：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;metrics-sevrer 的数据存在内存中。&lt;/li&gt;
&lt;li&gt;metrics-server 主要针对 node、pod 等的 cpu、网络、内存等系统指标的监控&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="kube-state-metrics"&gt;&lt;a href="#kube-state-metrics" class="header-anchor"&gt;&lt;/a&gt;kube-state-metrics
&lt;/h3&gt;&lt;p&gt;已经有了 cadvisor、heapster、metric-server，几乎容器运行的所有指标都能拿到，但是下面这种情况却无能为力：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;我调度了多少个 replicas？现在可用的有几个？&lt;/li&gt;
&lt;li&gt;多少个 Pod 是 running/stopped/terminated 状态？&lt;/li&gt;
&lt;li&gt;Pod 重启了多少次？&lt;/li&gt;
&lt;li&gt;我有多少 job 在运行中&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;而这些则是 kube-state-metrics 提供的内容，它基于 client-go 开发，轮询 Kubernetes API，并将 Kubernetes 的结构化信息转换为 metrics。&lt;/p&gt;
&lt;p&gt;kube-state-metrics 与 metrics-server 对比&lt;/p&gt;
&lt;p&gt;我们服务在运行过程中，我们想了解服务运行状态，pod 有没有重启，伸缩有没有成功，pod 的状态是怎么样的等，这时就需要 kube-state-metrics，它主要关注 deployment,、node 、 pod 等内部对象的状态。而 metrics-server 主要用于监测 node，pod 等的 CPU，内存，网络等系统指标。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;metric-server（或 heapster）是从 api-server 中获取 cpu、内存使用率这种监控指标，并把他们发送给存储后端，如 influxdb 或云厂商，他当前的核心作用是：为 HPA 等组件提供决策指标支持。&lt;/li&gt;
&lt;li&gt;kube-state-metrics 关注于获取 k8s 各种资源的最新状态，如 deployment 或者 daemonset，之所以没有把 kube-state-metrics 纳入到 metric-server 的能力中，是因为他们的关注点本质上是不一样的。metric-server 仅仅是获取、格式化现有数据，写入特定的存储，实质上是一个监控系统。而 kube-state-metrics 是将 k8s 的运行状况在内存中做了个快照，并且获取新的指标，但他没有能力导出这些指标&lt;/li&gt;
&lt;li&gt;换个角度讲，kube-state-metrics 本身是 metric-server 的一种数据来源，虽然现在没有这么做。&lt;/li&gt;
&lt;li&gt;另外，像 Prometheus 这种监控系统，并不会去用 metric-server 中的数据，他都是自己做指标收集、集成的（Prometheus 包含了 metric-server 的能力），但 Prometheus 可以监控 metric-server 本身组件的监控状态并适时报警，这里的监控就可以通过 kube-state-metrics 来实现，如 metric-serverpod 的运行状态。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/012-0394707a.jpg"&gt;&lt;/p&gt;
&lt;h3 id="custom-metrics-apiserver"&gt;&lt;a href="#custom-metrics-apiserver" class="header-anchor"&gt;&lt;/a&gt;custom-metrics-apiserver
&lt;/h3&gt;&lt;p&gt;kubernetes 的监控指标分为两种&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Core metrics（核心指标）：从 Kubelet、cAdvisor 等获取度量数据，再由 metrics-server 提供给 Dashboard、HPA 控制器等使用。&lt;/li&gt;
&lt;li&gt;Custom Metrics（自定义指标）：由 Prometheus Adapter 提供 API custom.metrics.k8s.io，由此可支持任意 Prometheus 采集到的指标。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下是官方 metrics 的项目介绍：&lt;/p&gt;
&lt;p&gt;Resource Metrics API（核心 api）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Heapster&lt;/li&gt;
&lt;li&gt;Metrics Server&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Custom Metrics API：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prometheus Adapter&lt;/li&gt;
&lt;li&gt;Microsoft Azure Adapter&lt;/li&gt;
&lt;li&gt;Google Stackdriver&lt;/li&gt;
&lt;li&gt;Datadog Cluster Agent&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;核心指标只包含 node 和 pod 的 cpu、内存等，一般来说，核心指标作 HPA 已经足够，但如果想根据自定义指标：如请求 qps/5xx 错误数来实现 HPA，就需要使用自定义指标了，目前 Kubernetes 中自定义指标一般由 Prometheus 来提供，再利用 &lt;code&gt;k8s-prometheus-adpater&lt;/code&gt; 聚合到 apiserver，实现和核心指标（metric-server) 同样的效果。&lt;/p&gt;
&lt;p&gt;HPA 请求 metrics 时，kube-aggregator(apiservice 的 controller) 会将请求转发到 adapter，adapter 作为 kubernentes 集群的 pod，实现了 Kubernetes resource metrics API 和 custom metrics API，它会根据配置的 rules 从 Prometheus 抓取并处理 metrics，在处理（如重命名 metrics 等）完后将 metric 通过 custom metrics API 返回给 HPA。最后 HPA 通过获取的 metrics 的 value 对 Deployment/ReplicaSet 进行扩缩容。&lt;/p&gt;
&lt;p&gt;adapter 作为 extension-apiserver（即自己实现的 pod)，充当了代理 kube-apiserver 请求 Prometheus 的功能。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2021-11-15-kubernetes-jian-kong-ti-xi-zong-jie/013-bee9d39d.jpg"&gt;&lt;/p&gt;
&lt;p&gt;其实 k8s-prometheus-adapter 既包含自定义指标，又包含核心指标，即如果安装了 prometheus，且指标都采集完整，k8s-prometheus-adapter 可以替代 metrics server。&lt;/p&gt;
&lt;h2 id="prometheus-部署方案"&gt;&lt;a href="#prometheus-%e9%83%a8%e7%bd%b2%e6%96%b9%e6%a1%88" class="header-anchor"&gt;&lt;/a&gt;Prometheus 部署方案
&lt;/h2&gt;&lt;p&gt;prometheus operator&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus-operator/prometheus-operator" target="_blank" rel="noopener"
 &gt;https://github.com/prometheus-operator/prometheus-operator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;kube-prometheus&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/prometheus-operator/kube-prometheus" target="_blank" rel="noopener"
 &gt;https://github.com/prometheus-operator/kube-prometheus&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在集群外部署&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.qikqiak.com/post/monitor-external-k8s-on-prometheus/" target="_blank" rel="noopener"
 &gt;https://www.qikqiak.com/post/monitor-external-k8s-on-prometheus/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;kube-prometheus 既包含了 Operator，又包含了 Prometheus 相关组件的部署及常用的 Prometheus 自定义监控，具体包含下面的组件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Prometheus Operator：创建 CRD 自定义的资源对象&lt;/li&gt;
&lt;li&gt;Highly available Prometheus：创建高可用的 Prometheus&lt;/li&gt;
&lt;li&gt;Highly available Alertmanager：创建高可用的告警组件&lt;/li&gt;
&lt;li&gt;Prometheus node-exporter：创建主机的监控组件&lt;/li&gt;
&lt;li&gt;Prometheus Adapter for Kubernetes Metrics APIs：创建自定义监控的指标工具（例如可以通过 nginx 的 request 来进行应用的自动伸缩）&lt;/li&gt;
&lt;li&gt;kube-state-metrics：监控 k8s 相关资源对象的状态指标&lt;/li&gt;
&lt;li&gt;Grafana：进行图像展示&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="我们的做法"&gt;&lt;a href="#%e6%88%91%e4%bb%ac%e7%9a%84%e5%81%9a%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;我们的做法
&lt;/h2&gt;&lt;p&gt;我们的做法，其实跟 kube-prometheus 的思路差不多，只不过我们没有用 Operator ，是自己将以下这些组件的 yaml 文件用 helm 组织了起来而已：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;kube-state-metrics&lt;/li&gt;
&lt;li&gt;prometheus&lt;/li&gt;
&lt;li&gt;alertmanager&lt;/li&gt;
&lt;li&gt;grafana&lt;/li&gt;
&lt;li&gt;k8s-prometheus-adapter&lt;/li&gt;
&lt;li&gt;node-exporter&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;当然 kube-prometheus 也有 helm charts 由 prometheus 社区提供：https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack&lt;/p&gt;
&lt;p&gt;这么干的原因是：这样的灵活度是最高的，虽然在第一次初始化创建这些脚本的时候麻烦了些。不过还有一个原因是我们当时部署整个基于 prometheus 的监控体系时，kube-prometheus 这个项目还在早期，没有引起我们的关注。如果在 2021 年年初或 2020 年年底的时候创建的话，可能就会直接上了。&lt;/p&gt;
&lt;h2 id="参考"&gt;&lt;a href="#%e5%8f%82%e8%80%83" class="header-anchor"&gt;&lt;/a&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.opskumu.com/cadvisor.html" target="_blank" rel="noopener"
 &gt;https://blog.opskumu.com/cadvisor.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://prometheus.io/" target="_blank" rel="noopener"
 &gt;https://prometheus.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale/" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.cnblogs.com/chenqionghe/p/10494868.html" target="_blank" rel="noopener"
 &gt;https://www.cnblogs.com/chenqionghe/p/10494868.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.qikqiak.com/post/k8s-operator-101/" target="_blank" rel="noopener"
 &gt;https://www.qikqiak.com/post/k8s-operator-101/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kubernetes.io/zh/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/" target="_blank" rel="noopener"
 &gt;https://kubernetes.io/zh/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://segmentfault.com/a/1190000017875641" target="_blank" rel="noopener"
 &gt;https://segmentfault.com/a/1190000017875641&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://segmentfault.com/a/1190000038888544" target="_blank" rel="noopener"
 &gt;https://segmentfault.com/a/1190000038888544&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://yasongxu.gitbook.io/" target="_blank" rel="noopener"
 &gt;https://yasongxu.gitbook.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://mp.weixin.qq.com/s/p4FAFKHi8we4mrD7OIk7IQ" target="_blank" rel="noopener"
 &gt;https://mp.weixin.qq.com/s/p4FAFKHi8we4mrD7OIk7IQ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://kubernetes.feisky.xyz/apps/index/operator" target="_blank" rel="noopener"
 &gt;https://kubernetes.feisky.xyz/apps/index/operator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://yunlzheng.gitbook.io/prometheus-book/part-iii-prometheus-shi-zhan/operator/what-is-prometheus-operator" target="_blank" rel="noopener"
 &gt;https://yunlzheng.gitbook.io/prometheus-book/part-iii-prometheus-shi-zhan/operator/what-is-prometheus-operator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>spring及spring cloud框架主要组件介绍</title><link>https://xiaobox.github.io/p/2020-04-23-spring-ji-spring-cloud-kuang-jia-zhu-yao-zu-jian-jie-shao/</link><pubDate>Thu, 23 Apr 2020 02:01:05 +0000</pubDate><guid>https://xiaobox.github.io/p/2020-04-23-spring-ji-spring-cloud-kuang-jia-zhu-yao-zu-jian-jie-shao/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2020-04-23-spring-ji-spring-cloud-kuang-jia-zhu-yao-zu-jian-jie-shao/cover.jpg" alt="Featured image of post spring及spring cloud框架主要组件介绍" /&gt;&lt;p&gt;&lt;strong&gt;spring 顶级项目&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring IO platform&lt;/strong&gt;:用于系统部署，是可集成的，构建现代化应用的版本平台，具体来说当你使用maven dependency引入spring jar包时它就在工作了。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Boot&lt;/strong&gt;:旨在简化创建产品级的 Spring 应用和服务，简化了配置文件，使用嵌入式web服务器，含有诸多开箱即用微服务功能，可以和spring cloud联合部署。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Framework&lt;/strong&gt;:即通常所说的spring 框架，是一个开源的Java/Java EE全功能栈应用程序框架，其它spring项目如spring boot也依赖于此框架。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Cloud&lt;/strong&gt;：微服务工具包，为开发者提供了在分布式系统的配置管理、服务发现、断路器、智能路由、微代理、控制总线等开发工具包。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring XD&lt;/strong&gt;：是一种运行时环境（服务器软件，非开发框架），组合spring技术，如spring batch、spring boot、spring data，采集大数据并处理。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Data&lt;/strong&gt;：是一个数据访问及操作的工具包，封装了很多种数据及数据库的访问相关技术，包括：jdbc、Redis、MongoDB、Neo4j等。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Batch&lt;/strong&gt;：批处理框架，或说是批量任务执行管理器，功能包括任务调度、日志记录/跟踪等。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Security&lt;/strong&gt;：是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Integration&lt;/strong&gt;：面向企业应用集成（EAI/ESB）的编程框架，支持的通信方式包括HTTP、FTP、TCP/UDP、JMS、RabbitMQ、Email等。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Social&lt;/strong&gt;：一组工具包，一组连接社交服务API，如Twitter、Facebook、LinkedIn、GitHub等，有几十个。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring AMQP&lt;/strong&gt;：消息队列操作的工具包，主要是封装了RabbitMQ的操作。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring HATEOAS&lt;/strong&gt;：是一个用于支持实现超文本驱动的 REST Web 服务的开发库。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Mobile&lt;/strong&gt;：是Spring MVC的扩展，用来简化手机上的Web应用开发。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring for Android&lt;/strong&gt;：是Spring框架的一个扩展，其主要目的在乎简化Android本地应用的开发，提供RestTemplate来访问Rest服务。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Web Flow&lt;/strong&gt;：目标是成为管理Web应用页面流程的最佳方案，将页面跳转流程单独管理，并可配置。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring LDAP&lt;/strong&gt;：是一个用于操作LDAP的Java工具包，基于Spring的JdbcTemplate模式，简化LDAP访问。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Session&lt;/strong&gt;：session管理的开发工具包，让你可以把session保存到redis等，进行集群化session管理。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Web Services&lt;/strong&gt;：是基于Spring的Web服务框架，提供SOAP服务开发，允许通过多种方式创建Web服务。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Shell&lt;/strong&gt;：提供交互式的Shell可让你使用简单的基于Spring的编程模型来开发命令，比如Spring Roo命令。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Roo&lt;/strong&gt;：是一种Spring开发的辅助工具，使用命令行操作来生成自动化项目，操作非常类似于Rails。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Scala&lt;/strong&gt;：为Scala语言编程提供的spring框架的封装（新的编程语言，Java平台的Scala于2003年底/2004年初发布）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring BlazeDS Integration&lt;/strong&gt;：一个开发RIA工具包，可以集成Adobe Flex、BlazeDS、Spring以及Java技术创建RIA。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Loaded&lt;/strong&gt;：用于实现java程序和web应用的热部署的开源工具。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring REST Shell&lt;/strong&gt;：可以调用Rest服务的命令行工具，敲命令行操作Rest服务。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;spring cloud子项目包括&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Cloud Config&lt;/strong&gt;：配置管理开发工具包，可以让你把配置放到远程服务器，目前支持本地存储、Git以及Subversion。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Cloud Bus&lt;/strong&gt;：事件、消息总线，用于在集群（例如，配置变化事件）中传播状态变化，可与Spring Cloud Config联合实现热部署。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Cloud Netflix&lt;/strong&gt;：针对多种Netflix组件提供的开发工具包，其中包括Eureka、Hystrix、Zuul、Archaius等。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Netflix Eureka&lt;/strong&gt;：云端负载均衡，一个基于 REST 的服务，用于定位服务，以实现云端的负载均衡和中间层服务器的故障转移。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Netflix Hystrix&lt;/strong&gt;：容错管理工具，旨在通过控制服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Netflix Zuul&lt;/strong&gt;：边缘服务工具，是提供动态路由，监控，弹性，安全等的边缘服务。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Netflix Archaius&lt;/strong&gt;：配置管理API，包含一系列配置管理API，提供动态类型化属性、线程安全配置操作、轮询框架、回调机制等功能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Cloud for Cloud Foundry&lt;/strong&gt;：通过Oauth2协议绑定服务到CloudFoundry，CloudFoundry是VMware推出的开源PaaS云平台。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Cloud Sleuth&lt;/strong&gt;：日志收集工具包，封装了Dapper,Zipkin和HTrace操作。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;**Spring Cloud Data Flow：**大数据操作工具，通过命令行方式操作数据流。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Cloud Security&lt;/strong&gt;：安全工具包，为你的应用程序添加安全控制，主要是指OAuth2。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Cloud Consul&lt;/strong&gt;：封装了Consul操作，consul是一个服务发现与配置工具，与Docker容器可以无缝集成。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Cloud Zookeeper&lt;/strong&gt;：操作Zookeeper的工具包，用于使用zookeeper方式的服务注册和发现。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Cloud Stream&lt;/strong&gt;：数据流操作开发包，封装了与Redis,Rabbit、Kafka等发送接收消息。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spring Cloud CLI&lt;/strong&gt;：基于 Spring Boot CLI，可以让你以命令行方式快速建立云组件。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2020-04-23-spring-ji-spring-cloud-kuang-jia-zhu-yao-zu-jian-jie-shao/001-bf98d7fd.jpg"&gt;&lt;/p&gt;
&lt;p&gt;关注公众号 获取更多精彩内容&lt;/p&gt;</description></item><item><title>ZooKeeper简要总结</title><link>https://xiaobox.github.io/p/2020-04-11-zookeeper-jian-yao-zong-jie/</link><pubDate>Sat, 11 Apr 2020 16:00:00 +0000</pubDate><guid>https://xiaobox.github.io/p/2020-04-11-zookeeper-jian-yao-zong-jie/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2020-04-11-zookeeper-jian-yao-zong-jie/cover.jpg" alt="Featured image of post ZooKeeper简要总结" /&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2020-04-11-zookeeper-jian-yao-zong-jie/001-ef783dc8.png"&gt;&lt;/p&gt;
&lt;h2 id="简介"&gt;&lt;a href="#%e7%ae%80%e4%bb%8b" class="header-anchor"&gt;&lt;/a&gt;简介
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" data-title-escaped="image.png" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" title="image.png"&gt;&lt;/p&gt;
&lt;p&gt;ZooKeeper是用于&lt;strong&gt;维护配置信息，命名，提供分布式同步以及提供组服务的集中式服务&lt;/strong&gt;。所有这些类型的服务都以某种形式被分布式应用程序使用。每次实施它们时，都会进行很多工作来修复不可避免的错误和竞争条件。由于难以实现这类服务，因此应用程序最初通常会跳过它们，这会使它们在发生更改时变得脆弱并且难以管理。即使部署正确，这些服务的不同实现也会导致管理复杂。&lt;/p&gt;
&lt;h2 id="命令集"&gt;&lt;a href="#%e5%91%bd%e4%bb%a4%e9%9b%86" class="header-anchor"&gt;&lt;/a&gt;命令集
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;启动 sh zkServer.sh start&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;停止 sh zkServer.sh stop&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;启动客户端 sh zkCli.sh&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;创建 create /zk-book 123&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;列表 ls /&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;读取 get /zk-book&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;更新 set /zk-book 456&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;删除 delete /zk-book&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="客户端"&gt;&lt;a href="#%e5%ae%a2%e6%88%b7%e7%ab%af" class="header-anchor"&gt;&lt;/a&gt;客户端
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;原生api&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;zkClient&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Curator&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="节点特性"&gt;&lt;a href="#%e8%8a%82%e7%82%b9%e7%89%b9%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;节点特性
&lt;/h2&gt;&lt;h3 id="持久节点persistent"&gt;&lt;a href="#%e6%8c%81%e4%b9%85%e8%8a%82%e7%82%b9persistent" class="header-anchor"&gt;&lt;/a&gt;持久节点（PERSISTENT）
&lt;/h3&gt;&lt;p&gt;所谓持久节点，是指在节点创建后，就一直存在，直到有删除操作来主动清除这个节点——不会因为创建该节点的客户端会话失效而消失。&lt;/p&gt;
&lt;h3 id="持久顺序节点persistent_sequential"&gt;&lt;a href="#%e6%8c%81%e4%b9%85%e9%a1%ba%e5%ba%8f%e8%8a%82%e7%82%b9persistent_sequential" class="header-anchor"&gt;&lt;/a&gt;持久顺序节点（PERSISTENT_SEQUENTIAL）
&lt;/h3&gt;&lt;p&gt;这类节点的基本特性和上面的节点类型是一致的。额外的特性是，在ZK中，每个父节点会为他的第一级子节点维护一份时序，会记录每个子节点创建的先后顺序。基于这个特性，在创建子节点的时候，可以设置这个属性，那么在创建节点过程中，ZK会自动为给定节点名加上一个数字后缀，作为新的节点名。这个数字后缀的范围是整型的最大值。&lt;/p&gt;
&lt;h3 id="临时节点ephemeral"&gt;&lt;a href="#%e4%b8%b4%e6%97%b6%e8%8a%82%e7%82%b9ephemeral" class="header-anchor"&gt;&lt;/a&gt;临时节点（EPHEMERAL）
&lt;/h3&gt;&lt;p&gt;和持久节点不同的是，临时节点的生命周期和客户端会话绑定。也就是说，如果客户端会话失效，那么这个节点就会自动被清除掉。注意，这里提到的是会话失效，而非连接断开。另外，在临时节点下面不能创建子节点。&lt;/p&gt;
&lt;h3 id="临时顺序节点ephemeral_sequential"&gt;&lt;a href="#%e4%b8%b4%e6%97%b6%e9%a1%ba%e5%ba%8f%e8%8a%82%e7%82%b9ephemeral_sequential" class="header-anchor"&gt;&lt;/a&gt;临时顺序节点（EPHEMERAL_SEQUENTIAL）
&lt;/h3&gt;&lt;p&gt;可以用来实现分布式锁&lt;/p&gt;
&lt;h2 id="session"&gt;&lt;a href="#session" class="header-anchor"&gt;&lt;/a&gt;Session
&lt;/h2&gt;&lt;p&gt;Client与Zookeeper之间的通信，需要创建一个Session，这个Session会有一个超时时间。因为Zookeeper集群会把Client的Session信息持久化，所以在Session没超时之前，client与Zookeeper server的连接可以在各个Zookeeper server之间透明地移动。在实际的应用中，如果client与server之间的通信足够频繁，Session的维护就不需要其他额外的消息了。否则，Zookeeper client会每t/3 ms发一次心跳给server，如果Client 2t/3 ms没收到来自Server的心跳回应，就会切换到一个新的Zookeeper Server上。这里t就是用户配置的Session的超时时间。&lt;/p&gt;
&lt;h2 id="watcher"&gt;&lt;a href="#watcher" class="header-anchor"&gt;&lt;/a&gt;Watcher
&lt;/h2&gt;&lt;p&gt;客户端无法从该事件中获取到对应数据节点的原始数据内容以及变更后的数据内容，而是需要客户端再次主动去重新获取数据-这也是zk watcher机制的一个非常重要的特性。&lt;/p&gt;
&lt;h2 id="fifo"&gt;&lt;a href="#fifo" class="header-anchor"&gt;&lt;/a&gt;FIFO
&lt;/h2&gt;&lt;p&gt;对于每一个Zookeeper客户端而言，所有的操作都是遵循FIFO顺序的，这一特性是由下面两个基本特性来保证的：一是Zookeeper client与server之间的网络通信都是基于TCP，Tcp保证了client/server之间传输包的顺序，二是Zookeeper server执行客户端请求也是严格按照FIFO顺序的。&lt;/p&gt;
&lt;h2 id="存储"&gt;&lt;a href="#%e5%ad%98%e5%82%a8" class="header-anchor"&gt;&lt;/a&gt;存储
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;日志文件&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;快照文件&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;内存数据库&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;zkDatabase,是zk的内存数据库，负责zk的所有会话、DataTree存储和事务日志。zkDatabase会定时向磁盘dump快照数据，同时在zk服务器启动的时候，会通过磁盘上的事务日志和快照数据文件恢复成一个完整的内存数据库。&lt;/p&gt;
&lt;p&gt;在每个ZNode上可存储少量数据(默认是1M，可以通过配置修改，通常不建议ZNode上存储大量数据)&lt;/p&gt;
&lt;p&gt;Leader处理所有请求，而Follow和Observer可以处理非事务请求，事务请求需要转发给Leader处理，对于每个事务请求，Leader会为其分配一个全局唯一且递增的ZXID。ZXID ，通常是一个64位的数字。每一个 ZXID 对应一次更新操作，从这些 ZXID 中可以间接地识别出 ZooKeeper 处理这些事务操作请求的全局顺序。&lt;/p&gt;
&lt;h3 id="数据同步"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e5%90%8c%e6%ad%a5" class="header-anchor"&gt;&lt;/a&gt;数据同步:
&lt;/h3&gt;&lt;p&gt;在服务器启动阶段，会进行磁盘数据在恢复，完成数据恢复后就会进行Leader选举，一旦选举产生Leader服务器后，就立即开始进行集群间的数据同步。&lt;/p&gt;
&lt;h3 id="数据同步过程"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e5%90%8c%e6%ad%a5%e8%bf%87%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;数据同步过程：
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" data-title-escaped="image.png" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" title="image.png"&gt;&lt;/p&gt;
&lt;h2 id="应用"&gt;&lt;a href="#%e5%ba%94%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;应用
&lt;/h2&gt;&lt;h3 id="数据发布订阅"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e5%8f%91%e5%b8%83%e8%ae%a2%e9%98%85" class="header-anchor"&gt;&lt;/a&gt;数据发布/订阅
&lt;/h3&gt;&lt;p&gt;即配置中心，zk采用推拉结合的方式实现。&lt;/p&gt;
&lt;p&gt;数据发布与订阅，即所谓的配置中心，顾名思义就是发布者将数据发布到 ZooKeeper 节点上，供订阅者进行数据订阅，进而达到动态获取数据的目的，实现配置信息的集中式管理和动态更新。在我们平常的应用系统开发中，经常会碰到这样的需求：系统中需要使用一些通用的配置信息，例如机器列表信息、数据库配置信息等。这些全局配置信息通常具备以下3个特性。数据量通常比较小。数据内容在运行时动态变化。集群中各机器共享，配置一致。&lt;/p&gt;
&lt;h3 id="命名服务"&gt;&lt;a href="#%e5%91%bd%e5%90%8d%e6%9c%8d%e5%8a%a1" class="header-anchor"&gt;&lt;/a&gt;命名服务
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;类似JNDI&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;分布式全局唯一ID（利用ZK的顺序节点&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;命名服务也是分布式系统中比较常见的一类场景。在分布式系统中，通过使用命名服务，客户端应用能够根据指定名字来获取资源或服务的地址，提供者等信息。被命名的实体通常可以是集群中的机器，提供的服务，远程对象等等——这些我们都可以统称他们为名字（Name）。其中较为常见的就是一些分布式服务框架（如RPC、RMI）中的服务地址列表。通过在ZooKeepr里创建顺序节点，能够很容易创建一个全局唯一的路径，这个路径就可以作为一个名字。ZooKeeper 的命名服务即生成全局唯一的ID。&lt;/p&gt;
&lt;h3 id="分布式协调通知"&gt;&lt;a href="#%e5%88%86%e5%b8%83%e5%bc%8f%e5%8d%8f%e8%b0%83%e9%80%9a%e7%9f%a5" class="header-anchor"&gt;&lt;/a&gt;分布式协调/通知
&lt;/h3&gt;&lt;p&gt;ZooKeeper 中特有 Watcher 注册与异步通知机制，能够很好的实现分布式环境下不同机器，甚至不同系统之间的通知与协调，从而实现对数据变更的实时处理。使用方法通常是不同的客户端都对ZK上同一个 ZNode 进行注册，监听 ZNode 的变化（包括ZNode本身内容及子节点的），如果 ZNode 发生了变化，那么所有订阅的客户端都能够接收到相应的Watcher通知，并做出相应的处理。ZK的分布式协调/通知，是一种通用的分布式系统机器间的通信方式。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;mysql 数据复制总线&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通用的分布式系统间通信方式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;心跳检测-利用临时节点，减少系统耦合。&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; 机器间的心跳检测机制是指在分布式环境中，不同机器（或进程）之间需要检测到彼此是否在正常运行，例如A机器需要知道B机器是否正常运行。在传统的开发中，我们通常是通过主机直接是否可以相互PING通来判断，更复杂一点的话，则会通过在机器之间建立长连接，通过TCP连接固有的心跳检测机制来实现上层机器的心跳检测，这些都是非常常见的心跳检测方法。下面来看看如何使用ZK来实现分布式机器（进程）间的心跳检测。基于ZK的临时节点的特性，可以让不同的进程都在ZK的一个指定节点下创建临时子节点，不同的进程直接可以根据这个临时子节点来判断对应的进程是否存活。通过这种方式，检测和被检测系统直接并不需要直接相关联，而是通过ZK上的某个节点进行关联，大大减少了系统耦合。
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;工作进度汇报-利用临时节点&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; 在一个常见的任务分发系统中，通常任务被分发到不同的机器上执行后，需要实时地将自己的任务执行进度汇报给分发系统。这个时候就可以通过ZK来实现。在ZK上选择一个节点，每个任务客户端都在这个节点下面创建临时子节点，这样便可以实现两个功能：通过判断临时节点是否存在来确定任务机器是否存活。各个任务机器会实时地将自己的任务执行进度写到这个临时节点上去，以便中心系统能够实时地获取到任务的执行进度。
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;系统调度&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;使用zk实现分布式系统机器间的通信，不仅能省去大量底层网络通信和协议设计上的重复工作，更为重要的一点是大大降低了系统之间的耦合，能够非常方便地实现异构系统之间的灵活通信。&lt;/p&gt;
&lt;h3 id="master选举"&gt;&lt;a href="#master%e9%80%89%e4%b8%be" class="header-anchor"&gt;&lt;/a&gt;Master选举
&lt;/h3&gt;&lt;p&gt;Master 选举可以说是 ZooKeeper 最典型的应用场景了。比如 HDFS 中 Active NameNode 的选举、YARN 中 Active ResourceManager 的选举和 HBase 中 Active HMaster 的选举等。针对 Master 选举的需求，通常情况下，我们可以选择常见的关系型数据库中的主键特性来实现：希望成为 Master 的机器都向数据库中插入一条相同主键ID的记录，数据库会帮我们进行主键冲突检查，也就是说，只有一台机器能插入成功——那么，我们就认为向数据库中成功插入数据的客户端机器成为Master。依靠关系型数据库的主键特性确实能够很好地保证在集群中选举出唯一的一个Master。但是，如果当前选举出的 Master 挂了，那么该如何处理？谁来告诉我 Master 挂了呢？显然，关系型数据库无法通知我们这个事件。但是，ZooKeeper 可以做到！利用 ZooKeepr 的强一致性，能够很好地保证在分布式高并发情况下节点的创建一定能够保证全局唯一性，即 ZooKeeper 将会保证客户端无法创建一个已经存在的 ZNode。也就是说，如果同时有多个客户端请求创建同一个临时节点，那么最终一定只有一个客户端请求能够创建成功。利用这个特性，就能很容易地在分布式环境中进行 Master 选举了。成功创建该节点的客户端所在的机器就成为了 Master。同时，其他没有成功创建该节点的客户端，都会在该节点上注册一个子节点变更的 Watcher，用于监控当前 Master 机器是否存活，一旦发现当前的Master挂了，那么其他客户端将会重新进行 Master 选举。这样就实现了 Master 的动态选举。&lt;/p&gt;
&lt;h3 id="分布式锁"&gt;&lt;a href="#%e5%88%86%e5%b8%83%e5%bc%8f%e9%94%81" class="header-anchor"&gt;&lt;/a&gt;分布式锁
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;共享锁&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;排他锁（Exclusive Locks，简称X锁&lt;/strong&gt;），又称为写锁或独占锁。如果事务T1对数据对象O1加上了排他锁，那么在整个加锁期间，只允许事务T1对O1进行读取和更新操作，其他任何事务都不能在对这个数据对象进行任何类型的操作（不能再对该对象加锁），直到T1释放了排他锁。可以看出，排他锁的核心是如何保证当前只有一个事务获得锁，并且锁被释放后，所有正在等待获取锁的事务都能够被通知到。如何利用 ZooKeeper 实现排他锁？定义锁 ZooKeeper 上的一个 ZNode 可以表示一个锁。例如 /exclusive_lock/lock节点就可以被定义为一个锁。获得锁 如上所说，把ZooKeeper上的一个ZNode看作是一个锁，获得锁就通过创建 ZNode 的方式来实现。所有客户端都去 /exclusive_lock节点下创建临时子节点 /exclusive_lock/lock。ZooKeeper 会保证在所有客户端中，最终只有一个客户端能够创建成功，那么就可以认为该客户端获得了锁。同时，所有没有获取到锁的客户端就需要到/exclusive_lock节点上注册一个子节点变更的Watcher监听，以便实时监听到lock节点的变更情况。释放锁 因为 /exclusive_lock/lock 是一个临时节点，因此在以下两种情况下，都有可能释放锁。当前获得锁的客户端机器发生宕机或重启，那么该临时节点就会被删除，释放锁。正常执行完业务逻辑后，客户端就会主动将自己创建的临时节点删除，释放锁。无论在什么情况下移除了lock节点，ZooKeeper 都会通知所有在 /exclusive_lock 节点上注册了节点变更 Watcher 监听的客户端。这些客户端在接收到通知后，再次重新发起分布式锁获取，即重复『获取锁』过程。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="分布式队列"&gt;&lt;a href="#%e5%88%86%e5%b8%83%e5%bc%8f%e9%98%9f%e5%88%97" class="header-anchor"&gt;&lt;/a&gt;分布式队列
&lt;/h3&gt;&lt;h3 id="集群管理"&gt;&lt;a href="#%e9%9b%86%e7%be%a4%e7%ae%a1%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;集群管理
&lt;/h3&gt;&lt;h3 id="负载均衡"&gt;&lt;a href="#%e8%b4%9f%e8%bd%bd%e5%9d%87%e8%a1%a1" class="header-anchor"&gt;&lt;/a&gt;负载均衡
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2020-04-11-zookeeper-jian-yao-zong-jie/004-683106fa.jpg"&gt;&lt;/p&gt;
&lt;p&gt;关注公众号 获取更多精彩内容&lt;/p&gt;</description></item><item><title>持续演进的Cloud Native (读书笔记04)</title><link>https://xiaobox.github.io/p/2020-03-09-chi-xu-yan-jin-de-cloud-native-du-shu-bi-ji-04/</link><pubDate>Mon, 09 Mar 2020 16:00:00 +0000</pubDate><guid>https://xiaobox.github.io/p/2020-03-09-chi-xu-yan-jin-de-cloud-native-du-shu-bi-ji-04/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2020-03-09-chi-xu-yan-jin-de-cloud-native-du-shu-bi-ji-04/cover.jpg" alt="Featured image of post 持续演进的Cloud Native (读书笔记04)" /&gt;&lt;p&gt;&lt;strong&gt;可扩展性设计 性能设计 一致性设计&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="可扩展性设计"&gt;&lt;a href="#%e5%8f%af%e6%89%a9%e5%b1%95%e6%80%a7%e8%ae%be%e8%ae%a1" class="header-anchor"&gt;&lt;/a&gt;可扩展性设计
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;横向扩展&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;横向扩展（scale out）也叫水平扩展，指用更多的节点支撑更大量的请求。例如如果1台机器支撑10 000TPS，那么两台机器是否能支撑20 000TPS？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;纵向扩展（scale up）也叫垂直扩展，扩展一个点的能力支撑更大的请求，它通常通过提升硬件实现，例如把磁盘升级为SSD。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;如何扩展数据库&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;主从复制集群&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;分库、垂直分表&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;分片（sharding）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;区间法（Range-Based）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;轮流法（Round-Robin）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;一致性哈希法（Consistent Hash）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;如何扩展数据中心&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;两地三中心&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;同城多活&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;异地多活&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="性能设计"&gt;&lt;a href="#%e6%80%a7%e8%83%bd%e8%ae%be%e8%ae%a1" class="header-anchor"&gt;&lt;/a&gt;性能设计
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;比较常见的性能问题如下&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;内存泄漏——导致内存耗尽。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;过载——突发流量，大量超时重试。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;网络瓶颈——需要加载的内容太多&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;阻塞——无尽的等待。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;锁——通过限制。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;IO繁忙——大量的读写、分布式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CPU繁忙——计算型常见问题。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;长请求拥塞——连接耗尽。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;性能指标&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;响应时间（Latency），就是发送请求和返回结果的耗时。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;吞吐量（Throughput），就是单位时间内的响应次数。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;树立目标&lt;/p&gt;
&lt;p&gt;寻找平衡点&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;我们可以通过一组压力测试数据找到拐点。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;定位瓶颈点&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;压力测试&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;日志分析&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;监控工具&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;服务通信优化&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;同步转异步&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;阻塞转非阻塞&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;序列化优化&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;通过消息中间件提升写性能&lt;/p&gt;
&lt;p&gt;通过缓存提升读性能&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;缓存的常用模式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Read Through模式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Write Through模式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Write Behind Caching模式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cache-Aside模式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cache-As-SoR模式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;为缓存数据设置合理的过期时间&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;为缓存设置回收策略&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;先预热数据&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;数据库优化&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;通过执行计划分析瓶颈点&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;为搜索字段创建索引&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过慢查询日志分析瓶颈点&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过提升硬件能力优化数据库&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;目前各大互联网公司的数据库均使用SSD硬盘或者PCIE-FLASH，据说2012年的时候微博使用PCIE-FLASH支撑了Feed系统在春晚时的3.5万QPS。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;简化设计&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;转移复杂度&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;从业务角度优化&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="一致性设计"&gt;&lt;a href="#%e4%b8%80%e8%87%b4%e6%80%a7%e8%ae%be%e8%ae%a1" class="header-anchor"&gt;&lt;/a&gt;一致性设计
&lt;/h3&gt;&lt;p&gt;事务&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;原子性（Atomicity）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;一致性（Consistency）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;隔离性（Isolation）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;未提交读（Read uncommitted）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;提交读（Read committed）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可重复读（Repeatable reads）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可序列化（Serializable）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;隔离级别&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;持久性（Durability）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CAP定理&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;一致性（Consistence）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可用性（Availability）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;分区容错性（Partition tolerance）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;分布式系统的一致性分类&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;以数据为中心的一致性模型&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;1.严格一致性（Strict Consistency&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2.顺序一致性（Sequential Consistency）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;3.因果一致性（Causal Consistency）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;4.FIFO一致性（FIFO Consistency）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;以用户为中心的一致性模型&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;1.单调读一致性（Monotonic-read Consistency）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2.单调写一致性（Monotonic-write Consistency）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;3.写后读一致性（Read-your-writes Consistency）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;4.读后写一致性（Writes-follow-reads Consistency）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;业界常用的一致性模型&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;弱一致性&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;最终一致性（Eventual Consistency）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;强一致性（Strong Consistency）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如何实现强一致性&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;两阶段提交&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;三阶段提交（3PC）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如何实现最终一致性&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;重试机制&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;本地记录日志&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可靠事件模式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Saga事务模型&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;TCC事务模型&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;分布式锁&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;基于数据库实现悲观锁和乐观锁&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;基于ZooKeeper的分布式锁&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;基于Redis实现分布式锁&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如何保证幂等性&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;幂等令牌（Idempotency Key）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在数据库中实现幂等性&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2020-03-09-chi-xu-yan-jin-de-cloud-native-du-shu-bi-ji-04/001-bf98d7fd.jpg"&gt;&lt;/p&gt;
&lt;p&gt;关注公众号 获取更多精彩内容&lt;/p&gt;</description></item></channel></rss>