跳至主要内容

博文

架构学习之路

先啃 DDIA(第 1–6 章),同时拿手头项目做数据层笔记;然后读 Clean Architecture 重构自己的 Go repo 结构;接着 Building Microservices + Learning DDD 两本交叉读;最后 Cloud Native Go 和 Production Kubernetes 一起对着 K8s 集群实操。 几个实践建议: 读 DDIA 时,找项目里用的数据库(PostgreSQL/Redis/Kafka 等)对应章节,立刻去看官方文档验证书里的描述,会记忆深刻得多。 读 Building Microservices 时,不要急着拆服务,而是先用 DDD 的 bounded context 把现有 monolith 的边界画出来,再决定要不要拆。 Cloud Native Go 的代码示例质量很高,建议 fork 下来在本地跑,比只读要有效得多。 有没有哪个方向想进一步深入?比如具体的分布式模式、Go 并发架构,或者 K8s operator 开发?
最新博文

LLM缓存详解

 可以把“大模型缓存”理解成: 把已经算过的结果(或中间结果)存下来,下次尽量复用 。但这里面其实分几层,不只是简单的“问题→答案”缓存。 1️⃣ 常见的几种缓存类型 (1)KV Cache(推理内部缓存) Transformer 在生成时,会把前面 token 的 Key/Value 向量 缓存下来。 本质:避免重复计算 attention 作用: 同一请求内部加速 特点: 👉 只对“同一上下文继续生成”有效 👉 不跨用户、不跨请求 这类缓存是你体感“流式输出越来越快”的原因之一。 (2)Prompt Cache(提示词缓存) 缓存的是: 相同(或高度相似)的 prompt → 对应的中间表示 / 输出 典型场景: 系统提示词(system prompt)很长 多轮对话里前文基本不变 👉 这里能省掉 前缀计算成本(prefill) (3)Embedding / 语义缓存(Semantic Cache) 这个才是你问题的关键 👇 不是按“字符串完全一致”,而是: 把问题转成向量 → 找“语义相似”的历史问题 → 直接复用答案 2️⃣ 为什么命中缓存成本低很多? 因为大模型推理成本主要在两块: (1)Prefill(吃 prompt) 复杂度 ~ O(n²) 很贵(尤其长 prompt) (2)Decode(逐 token 生成) 每个 token 都要算一遍模型 而缓存命中后: KV cache:不用重复 attention Prompt cache:不用重新 encode 语义缓存: 直接跳过模型推理 👉 相当于从: 几十~几百毫秒 + GPU算力 变成: 一次向量检索(毫秒级)+ 直接返回 所以成本差一个数量级是正常的。 3️⃣ “每个人问法不同,怎么命中缓存?” 这是核心难点,也是工程重点👇 ❌ 不能靠字符串匹配 比如: “今天天气怎么样” “今天外面热不热” 字符串完全不同 → 必须 miss ✅ 用语义相似度(Embedding) 流程一般是: 把问题转 embedding(向量) 在向量数据库里找 TopK 相似问题 如果相似度 > 阈值(比如 0.9) 直接返回缓存答案 一个简单示意 Q1: 北京天气怎么样 → embedding A Q2: 北京今天热吗 → embedding B cosine(A, B) ≈ 0.95...

temperature, top_p , frequency_penalty, max_tokens 概念详解

1️⃣ temperature(温度)——控制“概率分布的平滑程度” 模型本来会输出一个概率分布: tokenA: 0.7 tokenB: 0.2 tokenC: 0.1 temperature 会对这个分布做“拉伸/压缩”: 低温(0~0.3) → 分布更尖锐 → 更接近“选概率最高的词” → 更确定、稳定 高温(0.7~1.2) → 分布更平滑 → 小概率词更容易被选中 → 更发散、有创造性 👉 数学上其实是: [ P_i = \frac{e^{logits_i / T}}{\sum e^{logits / T}} ] 👉 直觉一句话: temperature = “敢不敢冒险” 2️⃣ top_p(nucleus sampling)——控制“参与抽奖的候选池” 不是调整概率,而是 裁剪候选集合 。 步骤: 按概率排序 token 从高到低累加,直到总概率 ≥ p 只在这个子集里采样 举个例子: 原始分布: A: 0.5 B: 0.2 C: 0.15 D: 0.1 E: 0.05 top_p = 0.7: 选: A (0.5) + B (0.2) = 0.7 👉 只在 {A, B} 里选 👉 直觉一句话: top_p = “允许多少概率质量参与竞争” 和 temperature 的区别 参数 作用本质 temperature 改概率分布形状 top_p 截断候选集合 👉 组合效果: temperature 决定“洗牌程度” top_p 决定“参与人数” 3️⃣ frequency_penalty ——“你刚说过,就少说点” 这个参数是 对已经生成过的 token 做惩罚 👉 逻辑: 出现次数越多 → 概率被压低 举个例子: 生成中: the cat and the cat and the ... 如果 frequency_penalty > 0: “the”、“cat” 被重复使用 下一次出现概率会下降 👉 数学近似: [ logits_i = logits_i - \lambda \cdot count(i) ] 👉 直觉一句话: frequency_penalty = “别复读” 使用场景 场景 建议 写文章 0.3 ~ 0.8 代码生成 0 列表生成 0.2 4️⃣ max_tokens ——“最多说多少” 这个最简单,但很多...

云服务器(Linux + Nginx)网站服务器优化配置指南

## 一、Linux系统层优化 ### 1. 安全基础配置 - **系统更新**:定期执行 `sudo apt update && sudo apt upgrade`(Debian系)或 `sudo dnf update`(RHEL系),保持内核与软件包最新。 - **防火墙**:仅开放必要端口(22/SSH、80/HTTP、443/HTTPS)。     Ubuntu:`sudo ufw allow 22,80,443/tcp && sudo ufw enable`     RHEL系:`sudo firewall-cmd --permanent --add-service={ssh,http,https} && sudo firewall-cmd --reload` - **SSH加固**:     - 修改默认端口(`/etc/ssh/sshd_config` 中 `Port`)     - 禁用root登录(`PermitRootLogin no`)     - 启用密钥认证(`PasswordAuthentication no`)     - 配置Fail2ban防止暴力破解 - **专用服务账户**:创建非root用户(如 `www-data`)运行Nginx,遵循最小权限原则。 ### 2. 内核与资源调优(`/etc/sysctl.conf`) ```conf # 网络连接优化 net.core.somaxconn = 65535 net.ipv4.tcp_max_syn_backlog = 65535 net.core.netdev_max_backlog = 65535 net.ipv4.ip_local_port_range = 1024 65535 net.ipv4.tcp_fin_timeout = 30 # 注:tcp_tw_reuse 需谨慎使用(仅适用于客户端连接场景,服务器端建议结合业务评估) ``` 生效命令:`sudo sysctl -p`   文件描述符限制:   ...

Go 工程实践:常见坑与设计注意事项

一、指针 vs 值传递(核心原则) ✅ 判断规则 1. 需要修改数据 → 用指针 2. 对象很大 → 用指针 3. 小对象 + 只读 → 用值(推荐) 4. 方法接收者一致 → 保持一致 ❌ 常见误区 func distance(p *Point) {} // ❌ 不必要的指针 问题: 增加 nil 风险 语义误导(看起来会修改) 可能增加 GC 压力 ✅ 推荐写法 func distance(p Point) {} // ✅ 二、interface 使用原则 1️⃣ 不要使用 *interface (反模式) func f(w *io.Writer) {} // ❌ 原因: interface 本身已是引用语义 增加一层间接访问,没有收益 破坏抽象 2️⃣ interface 的本质 interface = (type, data pointer) 👉 已经包含指针语义 三、nil 设计与风险控制 核心原则 不要让 nil 在系统中“流动” ✅ 正确做法 1️⃣ 构造函数保证非 nil func NewUser() *User { return &User{} } 2️⃣ 边界检查(而不是内部检查) func Handle(u *User) error { if u == nil { return errors.New("nil user") } return u.do() } 3️⃣ 小对象优先值传递 func Process(p Point) {} // 永远不会 nil ❌ 错误做法 func (u *User) Save() { if u == nil { // ❌ 到处防御 return } } 四、interface “假 nil”陷阱(高危) 现象 var e *MyError = nil var err error = e fmt.Println(err == nil) // false ❗ 原因 err = (type: *MyError, data: nil) 👉 interface 判断 nil 要求: type == nil && data == nil ✅ 规避方法 if e == nil { retu...

事务的ACID是什么

 事务的 ACID 是数据库事务必须满足的四个基本性质,用来保证在并发和故障情况下数据的正确性与可靠性: A(Atomicity,原子性) 一个事务中的操作要么 全部成功 ,要么 全部失败回滚 ,不存在“只做了一半”的中间状态。 C(Consistency,一致性) 事务执行前后,数据库都必须处于 一致的合法状态 ,满足约束(如主键、外键、唯一性、业务规则等)。 I(Isolation,隔离性) 并发执行的多个事务之间 相互隔离 ,一个事务未提交的中间结果对其他事务不可见(具体强弱由隔离级别决定)。 D(Durability,持久性) 一旦事务提交成功,其结果会被 永久保存 ,即使系统崩溃也不会丢失(通常依赖 WAL/redo log 等机制)。 一句话记忆: 要么全做完、前后不破坏规则、互不干扰、做完不丢。