Go

draft need to be improved Slice GOtype slice struct { array unsafe.Pointer len int cap int } // 扩容 func nextslicecap(newLen, oldCap int) int { newcap := oldCap doublecap := newcap + newcap if newLen > doublecap { return newLen } const threshold = 256 if oldCap < threshold { return doublecap } for { // 1.25x newcap += (newcap + 3*threshold) >> 2 if uint(newcap) >= uint(newLen) { break } } // overflowed if newcap <= 0 { return newLen } return newcap } Map GOtype Map struct { used uint64 // The number of filled slots seed uintptr // the hash seed, computed as a unique random number per map. // The directory of tables. // Normally dirPtr points to an array of table pointers // dirPtr *[dirLen]*table dirPtr unsafe.Pointer dirLen int // 1 << globalDepth globalDepth uint8 // The number of bits to use in table directory lookups. globalShift uint8 // The number of bits to shift out, 64 - globalDepth writing uint8 // detect the race. tombstonePossible bool // whether a table in this map contains a tombstone. clearSeq uint64 // version number, used to detect map clears during iteration. } Swiss Table refer: Faster Go maps with Swiss Tables ...

March 2, 2026

Spring

Spring 容器启动流程

March 2, 2026

Operating System

虚拟内存 进程 资源分配的基本单位。每个进程拥有独立的地址空间、文件描述符表、信号处理器等资源,进程之间彼此隔离。 进程的状态包括:创建、就绪、运行、阻塞、终止。 上下文切换 进程上下文切换需要保存和恢复的内容: CPU 寄存器(程序计数器 PC、栈指针 SP、通用寄存器等) 虚拟内存映射(页表基址寄存器,需刷新 TLB) 内核栈 进程控制块(PCB)中的状态信息 由于涉及页表切换和 TLB 刷新,进程切换的开销较大(通常在微秒级)。 进程间通信 进程拥有独立的地址空间,因此需要通过操作系统提供的 IPC 机制来通信: 方式 特点 适用场景 管道(Pipe) 半双工,父子进程间使用 简单的单向数据流 命名管道(FIFO) 半双工,无亲缘关系限制 不相关进程间通信 消息队列 有格式的消息,可按类型读取 结构化数据传递 共享内存 最快的 IPC 方式,需配合同步机制 大量数据交换 信号量(Semaphore) 用于同步,控制对共享资源的访问 互斥与同步 信号(Signal) 异步通知机制 事件通知(如 SIGKILL) Socket 支持不同主机间通信 网络通信 线程 CPU 调度的基本单位。同一进程内的线程共享地址空间、文件描述符和堆内存,但各自拥有独立的栈、程序计数器和寄存器组。 上下文切换 线程上下文切换只需保存和恢复: CPU 寄存器(PC、SP、通用寄存器) 线程栈指针 由于不涉及页表切换和 TLB 刷新(同进程内的线程共享地址空间),线程切换比进程切换快得多。 线程间通信 同一进程内的线程共享地址空间,可以直接读写共享变量,但需要同步机制来避免竞态条件: 互斥锁(Mutex):保证同一时刻只有一个线程访问临界区 读写锁(RWLock):允许多个读者并发,写者独占 条件变量(Condition Variable):让线程等待某个条件成立后再继续执行,配合互斥锁使用 信号量(Semaphore):控制并发访问数量 协程 运行在用户态的轻量级线程。协程的调度完全由用户程序控制,不需要陷入内核,因此切换开销极小。 ...

March 1, 2026

Linux Troubleshooting

L1 日常排错篇 适用场景:服务连不上、启动报错、明显卡顿。 1. 查死活与资源占用 ps -ef | grep <name> 用途:最基础的进程探测。看进程是否存在、看启动参数是否正确、看运行态的 PID。 top / htop 用途:看系统的整体大盘。 极客技巧:在 top 界面按 1 展开所有 CPU 核,按 P 找 CPU 消耗大户,按 M 找内存泄露元凶。htop 是其彩色增强版,支持鼠标和树状图(需安装)。 free -h 用途:看内存还剩多少。 避坑:不要看 free 列,直接看 available(系统真实可分配内存)。 2. 查网络与连通性 ss -lntp 用途:查本地监听端口。比老旧的 netstat 快百倍。排查"服务是否真起来了"、“谁占了 8080 端口”。 -l 仅显示监听状态,-n 不做域名反解(提速),-t 只看 TCP,-p 显示进程名和 PID。 ss -ant 用途:查看所有 TCP 连接的实时状态分布(ESTABLISHED / TIME_WAIT / CLOSE_WAIT 等)。 诊断技巧: TIME_WAIT 堆积过多 → 短连接并发太高,考虑开启 tcp_tw_reuse 或改用长连接。 CLOSE_WAIT 堆积 → 应用代码没有正确关闭连接(典型 Bug),需排查代码。 快速统计各状态数量: BASHss -ant | awk '{print $1}' | sort | uniq -c | sort -rn ss -s 用途:一行命令输出 TCP/UDP 连接数汇总统计,快速掌握全局连接规模。 BASH$ ss -s Total: 1024 TCP: 862 (estab 521, closed 12, orphaned 0, timewait 310) lsof -i :<port> 用途:报 Address already in use 时,一秒揪出占用该端口的凶手 PID。 nc -zv <ip> <port> 用途:纯 TCP 层的端口探活。不发数据,只测三次握手通不通(排查防火墙/安全组拦截的最快手段)。 curl -Iv <url> 用途:HTTP 层探活。-I 只拉取 Header 提速,-v 打印详细的 DNS 解析与握手过程。 curl -w(请求耗时拆分) 用途:精确测量一次 HTTP 请求各阶段的耗时,一行命令定界"慢在哪"。 BASH$ curl -o /dev/null -s -w "dns: %{time_namelookup}s\ntcp: %{time_connect}s\ntls: %{time_appconnect}s\nttfb: %{time_starttransfer}s\ntotal: %{time_total}s\n" https://example.com dns: 0.028s # DNS 解析耗时 tcp: 0.045s # TCP 三次握手完成 tls: 0.097s # TLS 握手完成 ttfb: 0.312s # 首字节到达(服务端处理耗时) total: 0.340s # 整个请求完成 定界思路: dns 高 → DNS 解析慢,用 dig 排查是否解析链路有问题 tcp - dns 高 → 网络延迟大或连接建立慢,用 ping/nc 验证 ttfb - tls 高 → 服务端处理慢(最常见),查服务端日志、CPU、慢 SQL total - ttfb 高 → 响应体传输慢,查带宽是否打满(sar -n DEV) ping -c 4 <ip> 用途:最基础的 ICMP 连通性检测与延迟测量。 注意:很多云服务器默认禁 ping(安全组/iptables 屏蔽 ICMP),ping 不通 ≠ 网络不通,需配合 nc/curl 交叉验证。 dig / nslookup <domain> 用途:DNS 解析排查。服务连不上时,第一步确认域名是否解析到了正确的 IP。 极客技巧:dig +trace <domain> 从根域开始逐级追踪解析链路,排查 DNS 劫持或缓存污染。 ip addr / ip route 用途:查看网卡 IP 地址、子网掩码、路由表。替代已废弃的 ifconfig 和 route。 排查场景:多网卡环境确认流量走了哪张网卡、默认网关是否正确。 tcpdump -i eth0 port 80 -w dump.pcap 用途:终极网络定界工具。当业务层查不出为何丢包或超时,直接到底层网卡抓包,导出后用 Wireshark 分析时序。 3. 查日志与磁盘 tail -f /var/log/xxx.log 用途:实时追踪日志输出,排查启动报错或运行时异常。 进阶:tail -f log | grep --line-buffered 'ERROR' 实时过滤错误行;多日志同时追踪用 tail -f a.log b.log。 journalctl -u <service> -f 用途:查看 systemd 管理的服务日志。比翻日志文件更方便,支持时间过滤。 常用组合: -f:实时追踪 --since "10 min ago":只看最近 10 分钟 -p err:只看错误级别以上 df -h / du -sh <path> 用途:df -h 查看各挂载点磁盘使用率,du -sh * 找出哪个目录最占空间。 避坑:df 显示磁盘满但 du 加起来不够?可能是已删除文件仍被进程持有(lsof +L1 排查)。 iostat 用途:最基础的磁盘读写查看,评估是否在疯狂写日志或落盘慢。 L2 高阶诊断篇 适用场景:系统负载飙升、偶发性延迟、无明显报错但疯狂卡顿。 ...

February 28, 2026

Redis Datastructure

Redis 数据结构 逻辑类型 (Type) 底层数据结构 (Internal Encoding) String int, embstr, raw (SDS) List quicklist Hash listpack, hashtable Set intset, hashtable ZSet listpack, skiplist + hashtable graph TD A[redisObject] --> B{type} B -->|STRING| C[int / embstr / raw] B -->|LIST| D[quicklist] B -->|HASH| E{size?} B -->|SET| F{all int?} B -->|ZSET| G{size?} E -->|小| H[listpack] E -->|大| I[hashtable] F -->|yes & 少| J[intset] F -->|no| K[hashtable] G -->|小| L[listpack] G -->|大| M[skiplist + hashtable]每种类型根据数据量自动切换编码:小数据用紧凑结构省内存,大数据切高效结构保性能。 ...

February 12, 2026

Java New Features

前言 Java 作为一门历史悠久的编程语言,一直在不断演进。本文按照 LTS(长期支持)版本 组织,介绍 Java 8 到 Java 25 的重要新特性,帮助开发者快速了解每个版本可以用哪些功能。 💡 每个特性后标注的版本号表示该特性正式可用的最低版本。 Java 8 LTS (2014) - 里程碑式更新 Java 8 是 Java 历史上最重要的版本,引入了函数式编程的核心概念。 Lambda 表达式 是什么? 一种简洁的匿名函数写法,把"行为"像数据一样传递。 JAVA// ❌ 传统写法 Collections.sort(list, new Comparator<String>() { @Override public int compare(String s1, String s2) { return s1.compareTo(s2); } }); // ✅ Lambda 写法 Collections.sort(list, (s1, s2) -> s1.compareTo(s2)); // ✅ 方法引用 Collections.sort(list, String::compareTo); Lambda 语法: ...

February 4, 2026

Mysql Technical Blog

MySQL 技术要点 一、MySQL 架构 MySQL 采用分层架构设计,主要分为 Server 层 和 存储引擎层。 1.1 Server 层 组件 职责 连接器 管理客户端连接、身份认证、权限校验 分析器 词法分析(识别关键字、表名、列名)、语法分析(构建语法树) 优化器 生成执行计划、选择最优索引、决定 JOIN 顺序 执行器 调用存储引擎 API 执行查询,返回结果集 1.2 存储引擎层 MySQL 支持插件式存储引擎,常用引擎对比: 引擎 事务支持 锁粒度 适用场景 InnoDB ✓ 行锁 OLTP、高并发读写 MyISAM ✗ 表锁 只读或读多写少 Memory ✗ 表锁 临时表、缓存 InnoDB architecture 二、索引机制 2.1 索引数据结构 类型 特点 适用场景 B+ Tree 有序、支持范围查询、树高稳定 主键索引、普通索引 Hash O(1) 查找、不支持范围查询 等值查询(Memory 引擎) Full-Text 倒排索引、支持自然语言搜索 全文检索 2.2 索引分类 按物理存储: ...

January 15, 2026

DDD Strategic and Tactical Design

领域驱动设计(DDD) 领域驱动设计(Domain-Driven Design, DDD)是一种以领域模型为核心的软件开发方法论,旨在应对复杂业务系统的设计与演进。DDD 分为战略设计和战术设计两个层面:战略设计关注系统整体的边界划分与团队协作模式,战术设计则聚焦于领域模型的具体实现模式。 1. 战略设计 战略设计的目标是从整体上划分系统的限界上下文(Bounded Context),并在每个上下文中发展出清晰一致的通用语言(Ubiquitous Language)。 1.1 领域与子域 领域(Domain):系统所关注的问题范围,代表业务活动和规则的集合。 子域(Subdomain):领域的组成部分,将复杂业务划分为更小、更聚焦的单元。 子域通常分为三类: 类型 说明 核心域(Core Domain) 业务的核心竞争力所在,需要重点投入 支撑域(Supporting Subdomain) 支撑核心业务运作,但非核心竞争力 通用域(Generic Subdomain) 通用功能,可采用现成方案 领域分析发生在问题空间(Problem Space),而领域模型的设计与实现属于解决方案空间(Solution Space): 问题空间:识别业务目标和边界,关注"做什么"。 解决方案空间:将需求转化为可实现的设计和模型,关注"怎么做"。 1.2 限界上下文(Bounded Context) 限界上下文是领域模型的语义边界。在该边界内,所有的概念、对象和规则都有明确且一致的含义。 同一个术语在不同上下文中可能代表不同含义,而在同一上下文中则保持语义一致。 例如,“账户"在用户上下文中可能指用户登录凭证,而在财务上下文中则指资金账户。限界上下文的划分有助于避免模型的混淆和污染。 1.3 通用语言(Ubiquitous Language) 通用语言是限界上下文内部领域专家与开发人员共享的统一语言。它通过领域模型来表达业务规则、行为和约束。 每个限界上下文都有自己独立的通用语言 通用语言不能跨上下文混用 代码、文档、沟通都应使用通用语言 1.4 上下文映射(Context Mapping) 当不同的限界上下文需要交互时,必须通过上下文映射来完成语言的"翻译"和语义对齐。上下文映射定义了上下文之间的关系、通信模式以及模型转换方式。 常见的上下文映射模式包括: 模式 说明 合作关系(Partnership) 两个团队共同协调开发,相互依赖 共享内核(Shared Kernel) 共享部分模型代码,需谨慎管理 客户-供应商(Customer-Supplier) 上游供应、下游消费,下游可提需求 遵奉者(Conformist) 下游完全遵从上游模型 防腐层(ACL) 下游建立转换层隔离上游模型 开放主机服务(OHS) 上游提供标准化协议供多方使用 发布语言(Published Language) 使用标准化的数据交换格式 1.5 防腐层(Anti-Corruption Layer) 下游上下文在使用上游上下文的数据或服务时,应建立一个防腐层(ACL)。防腐层负责: ...

January 5, 2026

Mysql Slow Query Filesort Optimization

IM 消息拉取接口的 SQL 优化记录 1. 背景与问题 在开发 IM 系统的“拉取历史消息”功能时,我发现当单张消息表(messages)的数据量达到百万级,且某个热点会话(conversation_id)拥有超过 10 万条消息时,接口响应出现明显卡顿。 环境信息: 数据库:MySQL 8.0+ (InnoDB) 数据量:单表 100 万行,大会话 10 万条信息 场景:用户查看最新的 20 条消息(Top-N 查询) 慢查询 SQL: SQLSELECT * FROM messages WHERE conversation_id = 'chat_hot' ORDER BY seq DESC LIMIT 20; 2. 排查过程 2.1 慢日志抓取 开启 MySQL 慢查询日志(log_output=FILE, long_query_time=0.1),捕获到该语句的执行情况: TEXT# Query_time: 0.148528 Lock_time: 0.000003 Rows_sent: 20 Rows_examined: 151676 异常点:为了返回 20 条数据,MySQL 实际扫描了 15 万行数据。扫描/返回比极低,说明索引效率存在严重问题。 2.2 执行计划分析 (EXPLAIN) 执行 EXPLAIN 查看当前索引使用情况: ...

December 28, 2025

Kafka Design Philosophy

深入理解 Apache Kafka 设计哲学 前言 Kafka 是一个分布式流处理平台,但它更像是 分布式提交日志 而非传统的消息队列。这种设计哲学贯穿了 Kafka 的每一个核心组件。本文将深入剖析 Kafka 的设计精髓。 一、存储层设计:为磁盘而生 1.1 日志结构存储 Kafka 采用 只追加写(Append-Only) 的日志结构,这带来了几个关键优势: 特性 传统数据库 (B-Tree) Kafka (Log) 写入复杂度 O(log N) O(1) 读取复杂度 O(log N) O(1) 磁盘访问模式 随机 I/O 顺序 I/O 适合场景 随机查询 流式处理 1.2 顺序 I/O 的威力 对于磁盘来说,O(log N) 并不等同于"接近常数时间"。每次磁盘寻道约需 10ms,且无法并行执行。即使少量随机访问也会导致性能急剧下降。 PLAIN顺序写磁盘: ~600MB/s 随机写磁盘: ~100KB/s 差距: 约 6000 倍! 1.3 拥抱操作系统 Page Cache Kafka 不在 JVM 堆内存中维护缓存,而是将数据直接写入操作系统的 Page Cache: graph TD subgraph JVM [JVM 进程] Logic[业务逻辑 不缓存数据] end subgraph Kernel [操作系统内核空间] PC(Page Cache 利用空闲内存 / 自动管理) FS[(磁盘文件系统)] end Logic -->|直接写入| PC PC -.->|异步刷盘 / 后写技术| FS style JVM fill:#f9f9f9,stroke:#333,stroke-width:2px style Kernel fill:#e1f5fe,stroke:#0277bd,stroke-width:2px style PC fill:#b3e5fc,stroke:#0277bd这样做的好处: ...

December 24, 2025