private plot

应无所住 | 而生其心

🏋️‍♂️ 徒手极简训练 7 天计划(5 分钟版)

🗓 训练频率

  • 每天 5~8 分钟
  • 随时随地可做,不受环境限制

🕒 时间建议

场景 推荐时间
☀️ 早晨 起床后 5 分钟(喝水后再做)
🌙 晚上 晚饭后站立做一轮(轻松无负担)
📱 白天碎片时间 工作间隙站起来活动,1~2 分钟即可

📅 每日训练动作

🗓 Day 1 / Day 4

  1. 站姿开合跳 🦘 - 30 秒
  2. 高抬腿 🚶‍♂️ - 30 秒
  3. 跪姿俯卧撑 💪 - 8~10 次
  4. 站立体前屈伸展 🧘 - 保持 15 秒

🗓 Day 2 / Day 5

  1. 深蹲 🦵 - 10 次
  2. 肩部绕环 🔄 - 前后各 10 次
  3. 站姿体侧伸展 ↔️ - 左右各 10 秒
  4. 平板支撑 💪 - 保持 10~15 秒

🗓 Day 3 / Day 6

  1. 原地快走 🚶‍♀️ - 1 分钟
  2. 箭步后撤 🦵 - 每条腿 6~8 次
  3. 俯身肩部伸展 🧘 - 左右各保持 10 秒

🗓 Day 7(恢复+放松日)

  • 颈部放松(点头/摇头各 5 次)
  • 腰背放松(站姿猫牛式,左右转动腰部各 5 次)
  • 原地慢走 2 分钟

📌 注意事项

  1. 重点在坚持,哪怕只做 1~2 个动作
  2. 饭后建议间隔 30~60 分钟
  3. 感觉疲劳时减少重复次数

便当搭配组合表

一、食材分类

1. 蛋白质类(中午带饭)

  • 鸡蛋
  • 豆腐
  • 虾仁
  • 腐竹
  • 牛肉

备注:虎头虾和三文鱼为周末偶尔食用,不纳入日常带饭食谱。

2. 蔬菜类

  • 西兰花
  • 花菜(菜花)
  • 芹菜
  • 胡萝卜
  • 紫甘蓝
  • 红甜椒

3. 主食类

  • 米饭(中午主食)

备注:紫薯、红薯、玉米等粗粮为早餐使用,不纳入中午主食搭配。

4. 调味及油脂类

  • 菜籽油
  • 橄榄油(适合低温炒菜或拌熟食)
  • 姜丝
  • 花椒
  • 低盐调味

二、搭配组合与做法

组合1:豆腐+西兰花+红甜椒+米饭

  • 做法
    • 豆腐切块焯水,用姜丝和花椒爆香炒制。
    • 西兰花焯水,红甜椒切丝同炒。
    • 出锅后可淋少量橄榄油增香。
    • 配白米饭装盒。

组合2:虾仁+芹菜+胡萝卜+米饭

  • 做法
    • 虾仁用盐和料酒腌制10分钟。
    • 芹菜、胡萝卜切片热炒,加入虾仁炒至变色。
    • 用少量橄榄油炒制更清爽。
    • 配白米饭装盒。

组合3:腐竹+花菜+紫甘蓝+米饭

  • 做法
    • 腐竹泡发后炒制,加入姜丝花椒提香。
    • 花菜、紫甘蓝焯水后翻炒。
    • 装盒后可适量淋橄榄油拌匀。
    • 搭配米饭,清淡健康。

组合4:鸡蛋+西兰花+胡萝卜+米饭

  • 做法
    • 鸡蛋煎成蛋饼切块。
    • 西兰花焯水,胡萝卜丝快炒。
    • 最后统一加橄榄油拌匀或分层装盒。
    • 与米饭搭配。

组合5:牛肉+芹菜+红甜椒+米饭

  • 做法
    • 牛肉切片,用生抽、料酒、姜丝腌制10分钟。
    • 芹菜、红甜椒切丝热炒,加入牛肉快炒至熟。
    • 全程使用菜籽油或橄榄油皆可。
    • 配米饭装盒,香气浓郁,蛋白质充足。

三、备注

  • 中午主食为米饭,控制分量,维持饱腹但不负担。
  • 粗粮如紫薯、红薯、玉米安排在早餐食用。
  • 所有蔬菜建议焯水后快炒,保留营养与口感。
  • 橄榄油适合用于熟食后拌匀或中低温快炒,搭配清淡便当尤佳。
  • 蛋白质可提前准备提升效率,调味以清淡为主。
  • 周末偶尔食用虎头虾、三文鱼;番茄晚上食用,不入便当。

本文将持续更新,根据食材变化、搭配优化及饮食经验进行维护记录。

在成长的路上,减少冗余、聚焦主线 是一项长期必修课。
这些是从chatgpt记忆里导出的内容,用于备份


🧠 为什么要清理记忆?

随着多个项目同时进行、生活节奏交错推进,我的系统记忆中积累了大量信息,逐渐变得冗余、重复,甚至出现冲突。为此,我主动开启了一次系统性的精简行动,目的是:

  • 清除重复、过时、已冻结的内容
  • 合并知识节点,提升整体认知结构清晰度
  • 腾出空间,容纳更新、更重要的信息
  • 其实最主要的原因是非订阅版的chatgpt记忆空间有限,我觉得这是chatgpt的bug,作为这么厉害的大预言模型,完全可以精简归纳记忆体内容,从而减少空间占用

🧩 精简后的核心内容

✅ 主线方向

  • AI 服务平台(askairo.com):构建一个服务跨境电商场景的本地智能系统,整合模型调用、LangChain、提示词优化等能力。
  • 已部署本地 Gemma 3 1B 模型,采用 Spring Boot + MySQL 构建完整客户端。

✅ 支撑基础

  • CS / AI 学习计划:长期推进,融合 AI 应用与理论知识补全。
  • lang-ast-analyze 项目:语法树分析 + 编译原理 + 自然语言学习。
  • 算法书项目:企业实战算法清单,整理为 Markdown Roadmap。

✅ 副线成长项目

  • 博客优化(blueshadex.com):持续打磨样式、SEO、阅读体验。
  • 家庭私有云:以 Tailscale + Syncthing + Jellyfin 为核心,搭建远程访问系统。

🧘 风格与节奏

  • 偏好传统项目结构,Clean Code 原则深入实践。
  • 默认 JDK 8,结构清晰、易于测试。
  • 每周设有“复盘模板”,类似禅修式陪练机制。

🍱 生活同步:90 天逆转计划

  • 午餐便当:西兰花、芹菜、花菜、腐竹、紫甘蓝、红甜椒、豆腐、虾仁,主食以米饭为主,低盐低油。
  • 早餐轮换:鸡蛋、牛奶、紫薯/玉米,水果收尾。
  • 晚上节制,偶尔补充坚果、深色蔬菜,周末加虎头虾、三文鱼。

🌿 审美与身份

  • 哀愁而含蓄的东方式美学,是我心灵的归属(《红楼梦》《边城》)。
  • Kairo 是我偏爱的名字,定生二字,是我对生命状态的期许。

🔚 小结

这次记忆精简行动,不只是一次数据管理,更是对自己认知结构的重塑。愿以更轻盈、更清晰的内在架构,走向下一阶段。

“删繁就简三秋树,领悟方向一叶舟。”

引言

在业务系统的高并发读写压力下,合理架构数据库系统成为系统稳定性与可扩展性的关键。本文从 OLTP、OLAP、HTAP 三类架构模型出发,逐步探讨主流解决方案的适用场景,最终回归到底层数据结构和事务引擎的设计哲学。


一、OLTP、OLAP、HTAP 的关系与区别

OLTP(Online Transaction Processing)

  • 面向高并发、实时写入与读取。
  • 典型场景:订单系统、支付系统。
  • 特点:小事务、快速响应、数据一致性强。

OLAP(Online Analytical Processing)

  • 面向数据分析与多维查询,重读操作。
  • 典型场景:报表分析、BI 系统。
  • 特点:复杂查询、大数据量聚合、写入延迟可接受。

HTAP(Hybrid Transactional and Analytical Processing)

  • 目标:在同一系统中同时支持 OLTP 与 OLAP。
  • 代表系统:TiDB、SingleStore、Doris。
  • 难点:一套引擎既要保证事务一致性,又要提供分析性能,成本高、复杂度高。

总结:

架构 主要目的 数据延迟容忍 一致性要求 查询复杂度 应用类型
OLTP 快速写入与查询 简单 订单、库存系统
OLAP 多维分析 可容忍 弱/最终一致性 报表、BI分析
HTAP 统一处理混合负载 低至中等 中等至高 通用大数据平台

二、读写分离方案与数据分析架构

读写分离(MySQL 主从 + ShardingSphere-JDBC)

  • 主节点专职写,从节点负责读,通过代理层实现透明路由。
  • 适用场景:业务系统中读请求远大于写请求,提高系统吞吐量。
  • 特点:
    • 快速部署,技术成熟。
    • 只能提升读性能,写性能无法提升。
    • 一致性依赖 binlog 异步复制,存在数据延迟。

OLTP + ETL + OLAP 架构

  • ETL:周期性从 OLTP 拉取数据,清洗加工后写入数据仓库。
  • OLAP:在数据仓库中进行高复杂度查询与分析。
  • 优点:读写解耦,业务与分析隔离,灵活可扩展。
  • 缺点:数据同步延迟(分钟级、小时级),一致性难保证。

三、读写冲突的本质

读写冲突的根源是结构的共享与修改竞争

  • 读操作依赖于当前数据结构(如索引树),要求一致性。
  • 写操作修改数据结构(新增记录、变更索引节点)。
  • 写涉及加锁、日志、索引更新;读为了事务隔离也需要锁或快照。
  • 二者对相同数据结构的访问模式不同,引发冲突。

四、InnoDB 如何减少读写冲突:MVCC 机制

InnoDB 实现了多版本并发控制(MVCC)来减少锁冲突,关键字段:

  • trx_id:表示该版本由哪个事务创建。
  • roll_pointer:指向上一个旧版本的数据。
  • undo log:通过回滚指针形成历史版本链表。
  • 快照读(Snapshot Read):读取满足版本可见性的数据版本。
  • 当前读(Current Read):必须加锁,例如 SELECT ... FOR UPDATE

可重复读(RR)通过 MVCC 实现无需加锁的快照读取,兼顾一致性与并发性。


五、索引的结构设计:为什么选择 B+ 树

InnoDB 的索引(聚簇与辅助索引)采用 B+ 树实现,原因如下:

相比 B 树:

  • 所有数据仅存在叶子节点,内节点只存储 key,占空间更小,分支因子更高,更适合磁盘存储。
  • 叶子节点之间通过链表连接,天然支持范围查询。

相比红黑树:

  • B+ 树为多路平衡树,树高更低,磁盘访问更少
  • 红黑树为二叉树,在大数据量下树高过深,不适合磁盘场景

六、三种结构直观对比

特性 B 树 B+ 树 红黑树
数据存储位置 所有节点都可存 只在叶子节点存储数据 所有节点存储数据
查询效率 高效(叶子节点链表)
范围查询 最优 最差
适用场景 磁盘索引 数据库、文件系统索引 内存数据结构(TreeMap 等)

推荐阅读:


结语

读写冲突、索引设计、事务并发控制,这些数据库内部机制是我们构建健壮系统的基石。掌握这些原理不仅能设计出更高效的系统架构,也有助于我们在性能瓶颈中找到最优解法。

主结构

本文记录一次对 Spring Boot 项目中 Logback 配置的优化过程,围绕如下目标展开:

  • 控制台 + 文件双输出
  • INFO / WARN / ERROR 日志分级输出
  • 用户行为日志单独归档
  • 区分开发与生产环境的日志级别(dev 为 DEBUG,prod 为 WARN)
  • 日志格式统一、结构清晰,方便后期问题排查与行为分析

日志配置结构与关键实现

基础配置

1
2
<property name="log.path" value="/home/kairo/logs"/>
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>

控制台输出

1
2
3
4
5
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>

分级输出文件:INFO/WARN 与 ERROR 拆分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<appender name="file_info" class="...RollingFileAppender">
<filter class="...LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>NEUTRAL</onMismatch>
</filter>
<filter class="...LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<appender name="file_error" class="...RollingFileAppender">
<filter class="...LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

用户行为日志单独输出

1
2
3
4
5
6
7
8
<appender name="sys-user" class="...RollingFileAppender">
<file>${log.path}/sys-user.log</file>
...
</appender>

<logger name="sys-user" level="INFO">
<appender-ref ref="sys-user"/>
</logger>

环境隔离配置(开发用 DEBUG,生产用 WARN)

1
2
3
4
5
6
<springProfile name="dev">
<logger name="com.kairo" level="DEBUG"/>
</springProfile>
<springProfile name="!dev">
<logger name="com.kairo" level="WARN"/>
</springProfile>

关键问题深度剖析

✅ 1. springProfile 不生效的排查逻辑

现象:在 dev 环境下指定 logger.level=DEBUG 无效。

原因与排查:

  • 检查 application.yml 中是否重复配置 logging.level,会覆盖 logback 的 logger 设置
  • springProfile 标签仅作用于 <logger>不作用于 <root>
  • <springProfile> 标签不能嵌套在 <root> 外部,只能出现在 <logger> 外部,只能控制类或包级别日志,不控制 appender 或 root。

建议:使用 <springProfile> 时必须绑定 <logger>,用于区分环境中 logger 的级别控制。


✅ 2. root 与 logger 的职责区分:输出 vs 定位

  • <root> 是日志系统的兜底配置,当 logger 找不到匹配项时,将使用 root 的日志级别及输出配置。
  • <logger> 是针对特定类或包名(如 com.kairo)做更细粒度的日志级别控制。
  • 简单说:logger 控制日志“来源”,root 控制日志“去向”(默认路径和等级)

✅ 3. logger 优先级高于 root,合理组合精细化配置

  • 如果某个类或包使用了 <logger> 配置,则 root 的配置将不再生效
  • 仅当未指定 <logger> 时,root 才会起作用。
  • 合理做法是:关键业务模块用 logger 精细配置,其他模块用 root 兜底。

✅ 4. logger / root / appender + filter 三者关系

元素 控制内容 粒度 备注
logger 控制日志来源(类/包) 可环境隔离配置
root 控制日志兜底来源 不能用 springProfile 隔离
appender + filter 控制日志输出去向(文件/控制台)和级别 输出端 是最终的过滤逻辑

核心结论:最终能不能输出,还要通过 appender 的 LevelFilter 筛一遍,即使 logger 放行了,如果 filter 不放行也无法写出。


✅ 5. 环境隔离要基于 logger 做

  • 不能用 springProfile 控制 root 的输出级别
  • 需要将 logger 包名配置明确,并分别在 dev / prod 环境下赋予不同级别。
  • 建议约定所有业务日志均以统一包名开头,例如 com.kairo,方便统一配置。

附录(可选)

logback.xml配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 日志存放路径 -->
<property name="log.path" value="/home/kairo/logs"/>
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>

<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>

<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:继续交由后续 filter 判断是否接收 -->
<onMismatch>NEUTRAL</onMismatch>
</filter>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>WARN</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<!-- 用户访问日志输出 -->
<appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-user.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天回滚 daily -->
<fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>


<!-- ============================== 输出渠道日志级别控制 ============================== -->

<!-- 根日志输出级别(“兜底”的默认级别控制器,仅对没有单独指定 logger 的类或包生效,配合appender里的filter使用) -->
<root level="INFO">
<appender-ref ref="console"/>
<appender-ref ref="file_info"/>
<appender-ref ref="file_error"/>
</root>
<!--系统用户操作日志(单独控制,记录登录等)-->
<logger name="sys-user" level="info">
<appender-ref ref="sys-user"/>
</logger>


<!-- ============================== 资源日志级别控制(<logger> 的级别优先于 <root>,控制的是包或类级别的日志输出) ============================== -->

<!-- 区分环境的包控制 -->
<!-- 开发环境,日志级别控制 -->
<springProfile name="dev">
<logger name="com.kairo" level="DEBUG"/>
</springProfile>
<!-- 其他环境,日志级别为 warn -->
<springProfile name="!dev">
<logger name="com.kairo" level="WARN"/>
</springProfile>

<!-- 不区分环境的包控制 -->
<!-- framework日志控制 -->
<logger name="org.springframework" level="WARN"/>
<logger name="springfox.documentation.spring.web" level="WARN"/>
<logger name="org.activiti" level="WARN"/>
<logger name="org.quartz" level="WARN"/>
<!-- 特定业务日志精细控制 -->
<logger name="com.kairo.oms" level="INFO"/>
<logger name="com.kairo.stat" level="INFO"/>

</configuration>

日志输出样例

1
2
12:01:23.456 [main] INFO  c.z.s.controller.LoginController - [login,42] - 用户登录成功,userId=123
12:01:25.789 [main] ERROR c.z.s.service.OrderService - [submitOrder,88] - 下单失败:库存不足

推荐日志目录结构

1
2
3
4
/home/kairo/logs/
├── sys-info.2025-05-17.log
├── sys-error.2025-05-17.log
├── sys-user.2025-05-17.log

总结

本次 Logback 优化实现了以下能力:

  • 分级、分模块、分环境的日志输出
  • 控制台与文件并行输出
  • 可扩展性强,支持后续 JSON 格式或 ELK 接入
  • 易于维护与排错,结构清晰

特别注意多个配置项之间的交互逻辑,掌握“logger 控源,filter 控流,root 兜底”的思维模型,有助于写出稳定、灵活的日志配置方案。

背景

在项目接口设计过程中,团队成员对于接口 URL 命名风格存在分歧:是否应采用 camelCase(驼峰命名)?对此展开了讨论。


结论

接口 URL 不应使用驼峰命名(camelCase),推荐统一采用 小写 + 中划线(kebab-case) 风格,或根据项目团队的规范选择使用下划线(snake_case),但应保持一致性。


理由分析

1. URL 是大小写敏感的

  • /userInfo/userinfo 被视为不同资源,易引发错误。
  • 驼峰风格加剧了大小写混淆的风险。

2. REST 社区与业界共识

  • 主流 RESTful API 设计(GitHub、Stripe、Twitter 等)均采用 kebab-case。
  • 阿里巴巴《Java 开发手册》、Google API 设计文档均推荐使用中划线分词。

3. 可读性更优

  • user-infouserInfo 更直观显示单词边界。
  • 相比下划线 _,中划线 - 在浏览器中的可视效果更明显、更美观。

4. SEO 更友好

  • 搜索引擎(如 Google)明确推荐使用中划线分隔词,避免使用下划线。
  • kebab-case 能被识别为多个关键词,有利于网页检索。

5. 为什么不推荐使用下划线(snake_case)

虽然下划线在数据库字段命名中很常见,但在 URL 中使用存在如下问题:

  • 不利于 SEO
    Google 明确表示:中划线被视为“词边界”,下划线不会;即 /user-info 会被当作两个词,而 /user_info 会被当作一个词。

  • 可读性差
    下划线在链接中经常被渲染为“不可见”或与底线混淆(尤其在下划线带超链接时),不如中划线易于识别。

  • 不符合社区主流
    主流框架和 API 设计规范文档均推荐使用 kebab-case,而非 snake_case。

6. 阿里巴巴 Java 开发手册的推荐

根据阿里巴巴的 Java 开发手册(《中册》)规定:

  • URL 地址命名风格推荐使用下划线分隔单词,并且全部小写。
  • 示例:/query_user_info/register_device_token

阿里规范与社区主流差异

  • 阿里规范:推荐使用下划线(snake_case)。
  • RESTful API 规范:社区主流(例如 GitHub、Stripe)推荐使用中划线(kebab-case)。

这两者的差异反映了不同技术社区和团队的偏好,而在具体项目中,选择遵循哪种规范应考虑团队需求及一致性。

7. 统一风格提升可维护性

为了避免不同风格的混杂,建议根据项目需求选择一种命名风格,并在整个项目中保持一致。

场景 命名风格
URL 路径 kebab-case / snake_case(根据项目规范选择)
JSON 字段名 camelCase
数据库字段 snake_case
常量/枚举 UPPER_CASE

不推荐的命名风格比较

风格 是否推荐 原因简述
camelCase ❌ 不推荐 易混淆、大小写敏感
snake_case ✅ 推荐(阿里规范) 适用于数据库,但对 URL 不太友好
kebab-case ✅ 推荐(REST 社区主流) SEO 友好、可读性好、符合行业趋势

推荐阅读与参考资料


总结

URL 是接口设计中面向外部的重要部分,命名风格应符合通用标准。为了减少歧义、提升可维护性、增强可读性,推荐统一使用 kebab-case 风格定义接口 URL,或者根据团队的具体要求选择下划线(snake_case)风格,但需保持一致性,避免混合使用。

引言

Jeff Dean 是 Google 历史上最具影响力的工程师之一。他不仅是多个关键基础设施的第一作者或领导者,也长期主导 Google 的技术发展方向。从早年的分布式系统,到后来的机器学习框架与深度模型架构,他的工作体系贯穿了计算范式的两次重大转变。

本文将围绕 Jeff Dean 所参与的几篇关键论文,梳理其背后的技术体系和影响轨迹。


一、大数据时代:分布式计算基础设施的建立

1. The Google File System (2003)

  • 作者:Sanjay Ghemawat, Howard Gobioff, Jeff Dean
  • 贡献:首次系统性构建适用于廉价硬件的大规模分布式文件系统,为 Google 内部所有高吞吐服务提供了存储支撑。
  • 技术亮点:Chunk-based 存储、主控节点简化调度、自动副本管理容错。

2. MapReduce: Simplified Data Processing on Large Clusters (2004)

  • 作者:Jeff Dean, Sanjay Ghemawat
  • 贡献:提出了通用的分布式计算模型,将大规模数据处理抽象为 Map/Reduce 两个阶段。
  • 影响:成为 Hadoop 等系统的灵感来源,极大降低了分布式编程门槛。

3. Bigtable: A Distributed Storage System for Structured Data (2006)

  • 作者:Fay Chang, Jeffrey Dean 等
  • 贡献:构建高可扩展性的结构化存储系统,支撑搜索、地图、广告等核心服务。
  • 技术亮点:SSTable、Chubby、列式存储、自动分区与负载均衡。

Jeff Dean 亲自参与并主导了 Google 构建分布式计算三大支柱(GFS、MapReduce、Bigtable),确立了技术基础框架,影响了后来的云计算生态。


二、AI 时代:深度学习平台与模型架构的兴起

4. TensorFlow: Large-Scale Machine Learning on Heterogeneous Systems (2015)

  • 作者:Martín Abadi, Jeff Dean(主导 Google Brain)
  • 贡献:统一计算图、自动求导、多设备分布式训练,开启深度学习工业化。
  • 亮点:灵活图结构、支持 CPU/GPU/TPU、生态繁荣。

5. Attention is All You Need (2017)

  • 作者:Ashish Vaswani, Noam Shazeer, Jakob Uszkoreit 等(Google Brain/Research)
  • 背景:Transformer 模型的提出催生了 BERT、GPT、T5 等大语言模型。
  • Jeff Dean 的角色:当时领导 Google Brain,指导性推动 Transformer 等架构探索,形成从框架到模型的协同研发文化。

三、Jeff Dean 的工作体系特征

1. 系统思维主导的工程设计

  • 将“抽象”与“工程实现”深度结合,先后建立了 Google 的存储系统、计算框架、机器学习平台。
  • 每个系统都强调:扩展性、容错性、易用性

2. 注重论文产出与开源结合

  • 其工作不只是内部系统设计,还特别注重通过论文、白皮书、开源推动学术与工业的互动。
  • TensorFlow 即是科研与工程结合的代表产物。

3. 技术演进中的桥梁角色

  • 从 C++ 系统级工程,到 Go/TPU/AI 平台,Jeff Dean 始终是 Google 技术变迁中承上启下的枢纽人物。
  • 他倡导工程师参与研究、研究者深入工程,打造跨界团队。

四、小结:一个技术体系的缩影

从 GFS 到 TensorFlow,从 MapReduce 到 Transformer,Jeff Dean 的工作体系不仅见证,也构建了 Google 技术体系的脊梁。这些工作推动了两个时代的技术浪潮:

  • 分布式计算 → 云平台生态
  • 神经网络训练 → 通用 AI 架构

Jeff Dean 本人始终强调“将抽象转化为生产力”,这也是 Google 技术创新的一以贯之之道。


附录:涉及论文与链接一览

序号 论文标题 链接 发表年份
1 The Google File System 链接 2003
2 MapReduce: Simplified Data Processing on Large Clusters 链接 2004
3 Bigtable: A Distributed Storage System for Structured Data 链接 2006
4 TensorFlow: Large-Scale Machine Learning on Heterogeneous Systems 链接 2015
5 Attention is All You Need 链接 2017

在日常 Java 后台开发中,良好的命名规范能显著提升代码的可读性、可维护性与协作效率。本文基于实践经验,总结出一套命名规范模板,适用于典型的 Web 后端开发场景。

🌟 命名原则

  • 语义清晰:命名要能准确表达其所代表的实体或行为。
  • 统一风格:统一使用驼峰命名(CamelCase),类名首字母大写,变量/方法名首字母小写。
  • 简洁优雅:避免冗长,拒绝无意义缩写。
  • 领域驱动:以业务语言命名,贴合领域模型。

📦 包名规范

1
com.company.project.module

示例:

1
com.acme.warehouse.outbound // 出库模块

🔠 类名规范

类型 命名后缀 示例
实体类 Entity OrderEntity, UserEntity
DTO类 DTO UserDTO, CreateOrderDTO
VO类 VO UserVO, TabVO
参数类 Param, Request LoginRequest, QueryOrderParam
返参类 Response, DO QueryResultResponse, OrderDO
接口类 以功能命名 OrderService
实现类 Impl OrderServiceImpl
Mapper接口 Mapper UserMapper
枚举类 Enum OrderStatusEnum

🧩 方法命名规范

增删改查

功能 方法名前缀 示例
新增 create / add createOrder()
查询 get / list / query getOrderById() / listUsers()
更新 update / refresh / modify updateUserProfile()
删除 delete / remove deleteOrderById()

业务行为

  • 尽量使用动宾结构,如 shipOrder()cancelOrder()
  • 特殊行为用动词短语,如 rollbackInventory()refreshStatusAfterShipping()

🔧 变量命名规范

类型 命名风格 示例
基本类型 简短语义 count, totalAmount
对象实例 实体名小写 order, userDTO
集合 复数形式 orders, userList
布尔值 is, has, can 前缀 isValid, hasPermission

📄 控制器规范

  • 控制器类名:xxxController
  • 路由方法名建议语义化,如:
1
2
@PostMapping("/create")
public AjaxResult createOutboundOrder(@RequestBody OutboundOrderDTO dto)

🧱 DAO 层命名与参数返回规范(重点)

DAO 层是数据持久化访问层,命名与参数结构需统一规范,避免 VO/DTO 混用、职责模糊等问题。

🔹 入参规范

场景 入参类型 示例
基础查询 MyBatis-Plus 自动封装 selectById(id)
复杂查询 QueryParam / QueryRequest QueryOrderParam

不再使用 PO 作为术语或命名后缀,基础持久化逻辑由 MyBatis-Plus 提供,Entity 即可满足结构映射需求。

🔹 返回值规范

场景 返回类型 示例 说明
基础查询 Entity UserEntity, OrderEntity 由 MyBatis-Plus 提供,直接返回数据库字段映射结构
复杂查询 DO(Data Object) OrderDetailDO, WarehouseDO 用于多表联查、聚合字段等,结构不直接绑定数据库表
复杂查询 QueryResponse OrderQueryResponse, UserQueryResponse 表达请求响应对称性,结构更贴近业务语义

✅ DO 全称解释

  • DOData Object
  • 意指:数据库查询返回的只读结构体,通常用于多表结果、聚合字段等
  • 与 Entity 的职责分离,不与数据库直接绑定

❌ 不推荐

  • ❌ 使用 VO 作为 DAO 返回结构:职责在于视图展示,不应参与数据访问层逻辑
  • ❌ 使用 DTO 作为 DAO 返回结构:DTO 是服务间传输结构,非查询结果结构

🔁 Service 层转换职责(重点)

  • DTO:用作接口入参、插入/更新结构化输入
  • VO:作为返回结构
  • DTO -> DAO层的QueryParam和QueryResponse的转换
  • DAO层的DO或QueryResponse -> VO的转换
  • ❗ Service 层仅负责业务逻辑组织,不应承载转换职责过多,建议结构拆分清晰。可使用 MapStruct / BeanUtil 等工具进行结构转换

💬 总结建议

  • 明确每层职责,结构命名与使用语义清晰区分
  • 接口层结构:入参DTO、返参VO
  • Service层结构:入参DTO,返参VO
  • DAO层基础持久化结构:Entity(建议不加Entity后缀,与表名一致),基于MyBatis-Plus
  • DAO层查询结构:入参QueryParam/QueryRequest,返参DO/QueryResponse

命名即抽象,抽象即设计。持续迭代你的命名风格,它反映了你的认知深度和系统设计水平。

欢迎在评论区补充你常用的命名模式或反面案例!

引言

随着容器化技术的普及,Docker 成为现代开发中非常流行的工具。它提供了轻量级的虚拟化解决方案,帮助开发者提高应用的可移植性和扩展性。但是,Docker 并不是适合所有场景。在选择是否将应用容器化时,需要仔细考虑应用的特性、部署需求以及管理复杂度。本文将深入探讨 Docker 的使用场景,分析哪些应用适合使用 Docker,哪些应用可能会带来不必要的复杂性。

1. Docker 的基础概念与应用场景

首先,我们简要回顾 Docker 的基础概念:

  • Docker 镜像:一种轻量级、可执行的软件包,包含了运行某个应用所需的所有代码、运行时、库和依赖。
  • Docker 容器:镜像的运行实例,它是隔离的、快速的,并且可以在不同环境中运行。
  • 数据持久化:通过 -v 参数将宿主机的目录挂载到容器中,从而实现数据的持久化存储。

在容器化应用时,我们通常需要考虑以下几个方面:

  • 可移植性:Docker 提供了一致的运行环境,可以确保应用在任何支持 Docker 的平台上都能以相同方式运行。
  • 资源隔离与弹性扩展:容器能够在同一台物理服务器上运行多个应用,并能灵活地调整资源配额。
  • 开发与部署流程:容器化应用可以方便地与 CI/CD 流程结合,自动化部署和测试。

2. 使用 Docker 时的考虑因素

虽然 Docker 在很多场景下都能带来便利,但它并不是所有应用的最佳选择。以下是需要重点考虑的几个因素:

2.1 是否需要持久化数据?

Docker 中的容器默认是临时的,容器停止或删除后,容器内的数据也会丢失。因此,对于需要持久化数据的应用(如数据库应用),我们需要使用 卷(Volume)绑定挂载(Bind Mount) 来持久化数据。

  • 最佳实践
    • 对于需要持久化数据的应用,如数据库、缓存服务等,可以通过 -v 参数将宿主机的目录挂载到容器内,确保数据在容器生命周期之外持久保存。
    • 如果数据量较大,建议使用外部存储解决方案来避免存储在容器内。

2.2 是否需要频繁更新或重建镜像?

对于一些依赖频繁更新的外部资源(如机器学习模型、第三方库等)的应用,每次修改或重建镜像时都可能丧失这些资源,这样就会增加不必要的管理复杂性。

  • 最佳实践
    • 对于需要频繁更新的文件或数据,建议将它们存储在宿主机上,并通过 -v 参数挂载到容器中,这样可以避免每次重新构建镜像时重复下载和复制这些文件。

2.3 管理与运维复杂性

Docker 通过将应用及其依赖封装到容器中,提供了高度的隔离性和一致性。然而,这种隔离性也可能增加管理和运维的复杂性。例如,容器的日志管理、网络配置、数据卷管理等都需要额外的配置和监控。

  • 最佳实践
    • 使用 Docker ComposeKubernetes 来管理和编排多个容器,特别是在涉及多容器服务(如数据库、后端服务和前端服务)时。
    • 通过 PrometheusGrafana 等工具来监控 Docker 容器,确保容器的健康状态和资源使用情况。

3. Docker 使用的常见场景

3.1 应用服务的隔离与弹性扩展

Docker 非常适合用于需要服务隔离并且具有弹性扩展要求的应用。例如,微服务架构中的每个微服务都可以通过独立的容器运行,并在需要时动态扩容。

  • 最佳实践
    • 使用 Docker Compose 来管理多容器应用,确保容器之间的网络、存储和其他配置可以统一管理。
    • 对于需要弹性扩展的服务,使用 Kubernetes 来编排容器,自动化扩展和负载均衡。

3.2 CI/CD 流程中的自动化部署

在持续集成/持续交付(CI/CD)流程中,Docker 镜像可以帮助开发团队以一致的环境进行开发、测试和生产部署。通过容器化,开发者能够轻松地复制和迁移应用。

  • 最佳实践
    • 使用 Docker Hub 或私有镜像仓库来存储构建好的 Docker 镜像,并通过 CI/CD 工具(如 GitLab CIJenkins)进行自动化部署。
    • 结合 Docker Compose,在 CI 流程中自动构建和测试容器化应用。

3.3 不需要持久化数据的应用

如果你的应用不需要长期存储数据或只在容器生命周期内存储临时数据,那么 Docker 是一个理想的选择。例如,用于临时计算的应用或一次性运行的任务。

  • 最佳实践
    • 这类应用可以直接运行在 Docker 容器中,并且可以随时销毁,减少运维成本。
    • 使用容器自动化运行短期任务(如批处理任务、定时任务等)。

4. 为什么不一定所有应用都适合 Docker?

虽然 Docker 具有很多优点,但在一些场景下,它可能会增加不必要的复杂性。例如:

  • 简单的桌面应用或开发环境:这些应用不需要 Docker 的隔离性和资源管理,直接安装和运行即可。
  • 数据库服务:虽然 Docker 可以容器化数据库服务,但对于需要高性能和稳定性的生产数据库,直接在宿主机上安装数据库可能更合适。
  • 频繁更新的文件或数据:如果应用中有频繁变化的文件或数据,Docker 容器可能会带来额外的管理负担。

5. 结论:是否使用 Docker?

在选择是否使用 Docker 时,开发者需要根据应用的特点来权衡 Docker 的优劣:

  • 适合使用 Docker 的场景

    • 微服务架构
    • CI/CD 自动化部署
    • 快速部署和移植
    • 临时性、轻量级的应用
  • 不适合使用 Docker 的场景

    • 对性能要求极高的数据库应用
    • 不需要隔离和快速扩展的单体应用
    • 频繁更新和变化的数据存储需求

6. Docker 的最佳实践与总结

总结下来,Docker 是一个非常强大的工具,但并非所有场景都适合使用它。对于需要高可用、高性能、持久化存储以及频繁更新的应用,Docker 可能并不是最佳选择。而对于需要快速部署、隔离服务、跨平台运行、以及支持弹性扩展的应用,Docker 提供了显著的优势。

在实际开发中,选择 Docker 还是其他解决方案,应该根据具体需求进行评估,避免在不合适的场景下使用 Docker 带来额外的复杂性和管理负担。通过结合 最佳实践开发规范,我们可以更好地利用 Docker,提升开发效率和运维质量。

0%