脚手架架构设计_小白版 📅 2026/7/13 4:34:59 ️ 脚手架架构设计——小白完全版原文脚手架架构设计.md来源Day21 课程笔记本版目标零基础看懂架构演进、Base 模块、Redis、Minio 等概念 一句话先搞懂什么是脚手架脚手架 项目的地基 水电管道盖房子不能从挖坑开始就糊水泥——得先搭脚手架把框架立起来穿水电管把公共基础设施铺好然后再砌墙装修。盖房子 搭脚手架 → 铺水电 → 砌墙 → 装修 做项目 写Base模块 → 装数据库/缓存 → 写业务功能原文里说的脚手架指的就是项目中Base 模块——所有业务功能都依赖于它的基础设施层。一、软件架构的三种盖房方式附图片详解原文档有 3 张架构演进图咱们一张一张讲。 图一单体架构——“一个房间啥都干”![单体架构]图长什么样详细描述┌─────────────────────────────────────────────────┐ │ 单体架构 │ │ │ │ 数据库服务器 │ │ ┌──────────────┐ │ │ │ 数据库服务器 │ ← 只有1个数据库 │ │ └──────┬───────┘ │ │ │ ↕ 双向交互 │ │ ┌──────▼───────┐ │ │ │ 后端的服务器 │ │ │ │ ┌─────────┐ │ ← 1个安装包 │ │ │ │学生管理系统│ │ 所有功能塞一起 │ │ │ │ 登录注册 │ │ │ │ │ │ 成绩管理 │ │ │ │ │ │ ORM层 │ │ │ │ │ │ service层 │ │ │ │ │ │ Controller │ │ │ │ │ └─────────┘ │ │ │ └──────┬───────┘ │ │ │ ↕ │ │ ┌──────▼───────┐ │ │ │ 网关 (nginx) │ │ │ └──────┬───────┘ │ │ ↕ ↕ │ │ ┌──┐ ┌──┐ │ │ │小程序│ │ APP │ │ │ └──┘ └──┘ │ └─────────────────────────────────────────────────┘生活类比一个家庭小作坊 老王开个面馆 - 他就是老板 厨师 收银 服务员 - 所有事情一个人干 - 店里就4张桌子 ✅ 优点简单一个人就能搞定 ❌ 缺点来8个客人就忙不过来了 如果老王生病了服务器挂了面馆直接关门对应到软件一个学生管理系统就一个安装包 - 登录注册功能 ✓ - 成绩管理功能 ✓ - ORM层 ✓ - service层 ✓ - controller层 ✓ 全在一个程序里 ✅ 优点开发简单、部署简单、调试方便 ❌ 缺点任何一个功能出 bug整个系统重启 用户一多就卡死老王面馆坐不下适用场景功能简单的项目用户量不大几十到几百人 图二分布式架构——“开连锁店”图长什么样┌─────────────────────────────────────────────────┐ │ 分布式架构 │ │ │ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │ │DB1 │→ │DB2 │→ │DB3 │→ │DB4 │ ← 4个数据库 │ │ └─┬──┘ └─┬──┘ └─┬──┘ └─┬──┘ (分库/复制) │ │ │ │ │ │ │ │ ▼ ▼ ▼ ▼ │ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │ │节点│ │节点│ │节点│ │节点│ ← 4台服务器 │ │ │ 1 │→ │ 2 │→ │ 3 │→ │ 4 │ ← 请求轮流发 │ │ │学生│ │学生│ │学生│ │学生│ (负载均衡) │ │ │管理│ │管理│ │管理│ │管理│ │ │ └────┘ └────┘ └────┘ └────┘ │ │ ↕ ↕ ↕ ↕ │ │ ┌──────────────┐ │ │ │ 网关 │ │ │ └──────┬───────┘ │ │ ↕ ↕ │ │ ┌──┐ ┌──┐ │ │ │小程序│ │ APP│ │ │ └──┘ └──┘ │ └─────────────────────────────────────────────────┘生活类比面馆开连锁店 老王生意好了开了4家分店 - 每家店卖的东西完全一样学生管理系统 - 来了客人前台网关说3号店有空位去那边 - 每家店有自己的厨房数据库 - 4家店的菜单是同步的数据库复制 ✅ 优点 - 一家店排长队客人可以去其他店负载均衡 - 一家店煤气坏了其他3家照常营业高可用 - 生意更好了再开第5家水平扩展 ❌ 缺点 - 管理成本高了要协调4家店 - 各店的库存可能不同步数据一致性问题 - 每家店仍然什么菜都做没有专业化分工对应到软件4台服务器部署了4个一模一样的学生管理系统 - 每台都有完整的登录、成绩管理、ORM... - 网关把用户请求均匀分配 - 一台挂了其他三台继续服务 ✅ 优点扛得住高并发、不会单点故障 ❌ 缺点部署复杂了、数据同步要处理 图三微服务架构——“美食广场”图长什么样┌─────────────────────────────────────────────────┐ │ 微服务架构把每个功能模块拆分成单独的应用 │ │ 和服务可以独立部署和运行 │ │ │ │ 服务器集群 │ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │ 登录/ │ │ 售后 │ │ 支付 │ │ 下单/ │ │ │ │ 注册 │ │ 服务 │ │ │ │秒杀 #1 │ │ │ └────────┘ └────────┘ └────────┘ └────────┘ │ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │ 商品 │ │ 登录/ │ │ 下单/ │ │ 下单/ │ │ │ │ 浏览检索 │ │ 注册#2 │ │秒杀 #2│ │秒杀 #3 │ │ │ └────────┘ └────────┘ └────────┘ └────────┘ │ │ │ │ 右侧说明可以更方便地对某个功能模块做水平扩展 │ │ 例如下单业务量增加时单独扩展5台下单服务 │ │ │ │ ┌──────────────┐ │ │ │ 网关 │ │ │ └──────┬───────┘ │ │ ↕ │ │ 张三→注册 ────┐ │ │ │ 李四→查商品 ──┤ │ │ │ 王五→下单 ────┘ │ │ │ │ │ └─────────────────────────────────────────────────┘生活类比美食广场不再是老王4家面馆而是龙湖天街美食广场 饺子铺登录注册服务 拉面铺售后服务 披萨铺支付服务 汉堡铺1号下单服务第1台 汉堡铺2号下单服务第2台 汉堡铺3号下单服务第3台 ← 汉堡卖得好多开几家 奶茶铺商品浏览检索 顾客用户来到美食广场网关说 - 张三我要注册 → 去饺子铺 - 李四查查有什么吃的 → 去奶茶铺 - 王五下单一份汉堡 → 去汉堡铺1号 ✅ 优点 - 每个铺子独立经营独立部署 - 汉堡卖得好多开3家汉堡铺水平扩展 - 奶茶铺关了汉堡铺照常营业故障隔离 ❌ 缺点 - 管理麻烦每个服务要单独部署监控 - 跨服务调用复杂点一个汉堡要跟多个铺子协作图片中的关键视觉细节图中的元素解释下单/秒杀出现了3次高并发模块独立扩展——卖得好就多开登录/注册出现了2次登录需求也大同样可以扩展各模块互不连接各自独立部署、独立运行每个模块只有一个功能微服务核心单一职责适用场景大型复杂系统几十个功能模块高并发场景某个功能需要大量服务器大型团队各团队维护不同的微服务三张图的对比——一张表看懂对比维度 单体架构 分布式架构 微服务架构生活类比一个家庭面馆4家老王面馆连锁美食广场服务器数量1台多台一模一样多台各干各的数据库数量1个多个多个各管各的功能拆分不拆分不拆分每台都完整拆分为小服务扩展方式换更大服务器垂直扩展加同样服务器水平扩展只加需要的服务精准扩展如果一个功能出bug整个系统瘫痪那一台服务挂了只有那个微服务挂了适合小项目、初创中型项目、增长期大型项目、大团队部署复杂度⭐ 简单⭐⭐⭐ 中等⭐⭐⭐⭐⭐ 复杂二、Base模块需要装的公共设施把软件架构理解成盖楼之后Base模块脚手架就是这栋楼的水电气管网——所有楼层业务功能都要用到的公共设施。像盖一栋办公楼 电梯网关——所有人要用 水管数据库——所有房间要用水 电箱缓存——所有灯要用电 空调管道消息队列——通风系统具体要装什么️ MySQL —— 主数据仓库状态已安装 ✅作用存所有永久数据——用户信息、题目、成绩、订单…类比大楼的实体档案室每份文件手写保存安全但慢 Milvus —— 向量搜索引擎状态已安装 ✅作用存语义索引——找相似题目、相似对话…类比大楼的智能索引柜“帮我找到去年跟’函数’有关的文件” → 秒出☁️ Minio —— 私有云文件柜状态需要安装 ❌在 Docker 里装作用存储文件——图片、文档、试卷 PDF、学生头像…类比大楼的自有文件仓库跟阿里云OSS类似但部署在自己服务器上阿里云OSS 租外面的仓库Minio 自己地下室建仓库特点支持分布式——多台服务器组成一个文件存储集群⚡ Redis —— 极速缓存状态需要安装 ❌在 Docker 里装作用存频繁访问的临时数据类比大楼前台的快取小本本——常用电话记在便利贴上贴桌上不用每次都翻通讯录怎么安装原文提供了两种方式方式一每个组件单独安装一个一个装 docker run mysql ... docker run redis ... docker run minio ... 方式二写 docker-compose.yaml 一次安装一步到位 docker-compose up -d → MySQL、Redis、Minio 一起启动推荐方式二就像买家具——不是一个一个搬而是用一辆卡车一次运完。三、Milvus 的元数据是什么原文提到Milvus 中的元数据存储在 etcd 中“切片的元数据chunkid, 文档, 章节, 多少Token, 开始位置, 结束位置…”小白理解书籍原始数据 → 存在哪里 → 怎么索引 ┌───────────────────┐ ┌────────────┐ ┌────────────┐ │ 一本书的内容向量 │ │ Milvus │ │ etcd │ │ 每个段落是一个向量 │ → │ (存书本身)│ │ (存书的目录)│ └───────────────────┘ └────────────┘ └────────────┘ etcd 存的是元数据metadata——关于数据的数据 | 元数据项 | 生活类比 | 示例值 | |---------|---------|-------| | chunk_id | 图书编号 | chunk_001 | | 文档ID | 哪本书 | doc_数学课本 | | 章节 | 第几章 | 第3章 函数 | | Token数 | 这段多少字 | 256个token | | 开始位置 | 从第几页开始 | 第102页 | | 结束位置 | 到第几页结束 | 第105页 |为什么需要 etcd因为 Milvus 需要知道有哪些表有哪些字段索引怎么建的这些关于数据的数据不能存在 Milvus 自己里面需要一个专门的目录服务中心etcd。就像大型图书馆不能只在书架上贴标签还得有一个电脑目录系统——告诉你 X 楼 Y 架 Z 层放的是什么书。四、Redis 详解 它在大楼中的位置附图片四详解Redis 是这篇文档的重点让我们彻底搞懂。4.1 Redis 是什么Redis Remote DIctionary Service远程字典服务 一句话一个住在内存里的超级字典 特点 ⚡ 基于内存操作 → 比从硬盘读快 1000 倍 键值对存储 → 像查字典一样给个key秒出value 天生支持分布式 → 多台Redis自动协作 支持持久化 → 断电后数据不会全丢 ⏰ 支持过期时间 → 可以自动删除旧数据生活类比你手机通讯录 → 存手机里硬盘慢 你大脑记住常打的5个号码 → 存脑子里内存快 Redis 你大脑的速记区4.2 Redis 存什么数据原文重点 高频访问的业务数据 商品信息、购物车、收藏、订单... → 每次用户查商品都去MySQL太慢 → 存到Redis秒查 用户登录Token 你登录后服务器给你一张临时通行证(Token) 之后每次请求带Token验证身份 这个不能每次都查数据库放Redis AI对话的短期记忆 你跟AI聊天的刚刚说了什么 → 存在Redis里聊完就过期删掉4.3 四张图中的 Redis 位置图图片四详解原文档第4张图是在微服务架构基础上加了数据层和缓存层┌────────────┐ ┌────────────┐ │ MySQL 数据库│ │ MySQL 数据库│ ← 最底层的数据存储 │ #1 │ │ #2 │ └─────┬──────┘ └─────┬──────┘ │ │ ▼ ▼ ┌─────────────────────────────────────┐ │ Redis 集群 │ ← 缓存层 │ │ │ Redis1 → Redis2 → Redis3 → ~~Redis4~~→ 5 │ ↑ 被划掉了 │ Redis4被划掉 这个节点挂了 │ │ 但系统仍然正常运转 │ └─────────────────┬───────────────────┘ │ ┌────────────────▼───────────────────┐ │ 微服务架构 │ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │ │登录 │ │售后 │ │支付 │ │下单 │ │ │ │注册 │ │服务 │ │ │ │秒杀 │ │ │ └────┘ └────┘ └────┘ └────┘ │ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │ │商品 │ │登录 │ │下单 │ │下单 │ │ │ │浏览 │ │注册 │ │秒杀 │ │秒杀 │ │ │ └────┘ └────┘ └────┘ └────┘ │ └────────────────┬───────────────────┘ │ ┌────▼────┐ │ 网关 │ └────┬────┘ │ ┌───────┬───┴───┬───────┐ │ │ │ │ 张三注册 李四查商品 王五下单 ...图片的关键细节解读图中的细节它在说什么Redis4 被斜线划掉Redis天然支持故障自动切换——一个节点挂了其他节点照样工作Redis在MySQL之上缓存层的逻辑位置先查Redis没有才查MySQLRedis与微服务同层每个微服务都可以直接调用Redis不需要经过网关箭头指向关系服务→Redis→MySQL越往下越慢越往上越快数据读取流程从图可以推导用户查商品王五下单 │ ▼ ① 先查 Redis这个商品最近有人查过吗 ├── 有缓存命中→ 秒级返回 ✅ └── 没有缓存未命中 │ ▼ ② 查 MySQL从硬盘读取数据 │ ▼ ③ 把查到的结果写入 Redis下次就快了 │ ▼ ④ 返回给用户4.4 Redis 实际操作# 存数据redis_client.put(s001,{name:昌老师,age:25},过期时间)# 把学号s001的学生信息存到Redis设置过期时间redis_client.put(昌老师,25)# 直接存一个键值对# 取数据redis_client.get(s001)# 根据学号取学生信息五、设计模式单例模式原文提到Redis Client 是单例模式什么是单例模式一个类只能创建一个实例不能创建多个。生活类比✅ 适合单例的 公司打印机 —— 全公司只需要一台大家排队用 学校广播站 —— 只有一个话筒不能同时有两个人说话 Redis客户端 —— 一个程序只需要一个连接管理 ❌ 不适合单例的 学生对象 —— 每个学生不同需要多个实例 商品对象 —— 每个商品不同代码类比# ❌ 不使用单例每次 new 一个新连接db1Database()# 建立一次连接db2Database()# 再建立一次——浪费资源db3Database()# 又建立一次——服务器哭了# ✅ 使用单例全世界只有一个实例dbDatabase.get_instance()# 第一次创建连接same_dbDatabase.get_instance()# 第二次返回同一个same_db_againDatabase.get_instance()# 还是一样的# 它们仨指向同一个对象项目中哪些用单例对象是否单例原因数据库连接MySQL✅ 是一个连接池管理所有请求Redis客户端✅ 是一个客户端管理所有缓存操作Milvus客户端✅ 是一个客户端管理所有向量操作学生对象Student❌ 不是每个学生不同题目对象Question❌ 不是每道题不同六、连接池的概念为什么要连接池没有连接池 每次要连数据库 建立连接握手、认证...→ 使用 → 断开连接 下次还有数据要查再建立一次 → 再用 → 再断 就像每次进家门都要重新砌一堵墙、再开个门 非常浪费资源 有连接池 程序启动时一次性建立20个数据库连接 放在一个池子里 每次要用直接从池子里拿一个 用完放回去 就像地铁站的闸机——提前装好了20个闸口 乘客来了直接刷卡进站不用现场装闸机连接池图示启动时 ┌─────────────────────────────────┐ │ 连接池 │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │ │ │C1│ │C2│ │C3│ │C4│ │C5│ ... │ ← 提前建立 20 个连接 │ └──┘ └──┘ └──┘ └──┘ └──┘ │ │ 等待使用... │ └─────────────────────────────────┘ 请求来了 ┌─────────────────────────────────┐ │ 用户A → 从池子拿 C1 → 查数据 │ │ 用户B → 从池子拿 C2 → 查数据 │ │ 用户C → 从池子拿 C3 → 查数据 │ └─────────────────────────────────┘ 用完了 ┌─────────────────────────────────┐ │ 用户A用完 C1 → 放回池子 │ │ 用户B用完 C2 → 放回池子 │ └─────────────────────────────────┘不只是数据库连接池连接池的思想不只用于数据库连接池类型类比作用数据库连接池提前建好一批水管避免频繁开关连接线程池提前招好一批工人避免频繁招聘/辞退HTTP连接池提前建好一批电话线避免频繁拨号/挂断七、Settings 类封装——告别硬编码什么是硬编码# ❌ 硬编码写死在代码里defconnect_mysql():host192.168.1.100# 直接写在代码里port3306usernamerootpassword123456# 问题换数据库了要改代码重新部署怎么改进用 .env 文件# ✅ 把配置写到 .env 文件里 MYSQL_HOST192.168.1.100 MYSQL_PORT3306 MYSQL_USERroot MYSQL_PASSWORD123456 DEEPSEEK_API_KEYsk-xxxxx DEEPSEEK_BASE_URLhttps://api.deepseek.com REDIS_HOSTlocalhost REDIS_PORT6379在代码中读取importos hostos.getenv(MYSQL_HOST)# 从.env读不改代码portos.getenv(MYSQL_PORT)但还不够好——问题来了.env 文件可能有几十个key怎么管理.env 文件里 MYSQL_HOST... MYSQL_PORT... MYSQL_USER... MYSQL_PASSWORD... DEEPSEEK_API_KEY... DEEPSEEK_BASE_URL... REDIS_HOST... REDIS_PORT... REDIS_PASSWORD... MINIO_ENDPOINT... MINIO_ACCESS_KEY... MINIO_SECRET_KEY... ... 几十行混在一起所以需要在 .env 的上面再加一层封装# ✅ 最终方案Settings类 class MysqlSettings: # MySQL的配置归我管 host ... port ... user ... password ... class RedisSettings: # Redis的配置归我管 host ... port ... password ... class LLMSettings: # 大模型的配置归我管 api_key ... base_url ... model ...生活类比❌ 不用Settings类 你搬家时把所有东西混在一起装箱 → 到新家要找充电器翻遍所有箱子 ✅ 用Settings类 按类别装箱——厨房用具一箱、电子产品一箱、衣服一箱 → 到新家要充电器直接找电子产品那箱八、Minio 对象存储——你自己的阿里云OSS什么是对象存储简单说就是存文件的地方。你平时存文件 电脑硬盘 → C盘 D盘 手机相册 → 手机存储 程序存文件 以前存到服务器的硬盘上比如 D:\uploads\ 问题服务器硬盘满了怎么办换服务器了文件怎么办 Minio独立的文件存储服务 → 像阿里云OSS一样但部署在自己服务器上 → 支持分布式多台Minio组成集群 → 不用担心硬盘满、不用怕文件丢什么时候用 Minio场景存哪里用户头像图片Minio试卷PDF文件Minio题目中的图表Minio学生作业附件Minio聊天中的图片Minio九、总结——脚手架Base模块完整结构图┌─────────────────────────────────────────────────┐ │ ️ Base模块脚手架 │ │ │ │ ┌──────────────────────────────┐ │ │ │ Settings 类封装 │ │ │ │ MysqlSettings RedisSettings │ │ │ │ LLMSettings MinioSettings │ │ │ └──────────┬───────────────────┘ │ │ │ │ │ ┌──────────▼───────────────────┐ │ │ │ 连接池管理 │ │ │ │ 数据库连接池 线程池 │ │ │ └──────────┬───────────────────┘ │ │ │ │ │ ┌───────┬──────┼──────┬────────┐ │ │ │ │ │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ │ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────────┐ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └────┘ └────┘ └────┘ └────┘ └────────┘ │ │ MySQL Milvus Redis Minio 大模型客户端 │ │ (etcd) (单例模式) │ │ │ │ 每个客户端都采用 │ │ ✅ 单例模式一个程序只有一个实例 │ │ ✅ 连接池提前建好一批连接随用随取 │ │ ✅ 配置从Settings类读取不硬编码 │ └─────────────────────────────────────────────────┘ ┌─────────────────────┐ │ 业务模块楼上的房间 │ │ 登录注册 / 出题 / 判题 │ │ 全都依赖Base脚手架 │ └─────────────────────┘十、面试考点速查原文最后列的要求就是面试考点考点1单例模式 vs 工厂模式模式一句话生活类比项目中使用单例模式一个类只能有一个实例公司打印机大家共用Redis客户端、数据库连接、日志记录器工厂模式根据条件创建不同类型对象饺子机——投白菜馅出白菜饺子投韭菜馅出韭菜饺子创建不同AI模型的工厂——要Qwen给Qwen要DeepSeek给DeepSeek考点2连接池的概念不只数据库连接池还有线程池预先创建一批线程避免频繁创建/销毁线程的开销HTTP连接池预先建立一批HTTP连接Redis连接池预先建立一批Redis连接一句话讲明白连接池就是提前把资源准备好要用的时候直接拿不用现场创建加分话术“在项目脚手架中采用了单例模式管理 Redis 和数据库客户端确保资源的唯一性通过连接池机制预先建立连接大幅降低重复创建的开销同时使用 Settings 类封装所有配置避免硬编码换环境只需改 .env 文件。”原文是课程笔记给学过的人复习用。这份小白版是给零基础的人——每个概念都配生活类比、每张图都配详细解说。