Go 并发编程:goroutine 与 channel
Go 并发编程:goroutine 与 channel Go 语言以简洁的并发模型著称。本文梳理 goroutine 与 channel 的核心用法。 goroutine启动一个 goroutine 非常简单: 123go func() { fmt.Println("hello from goroutine")}() 注意: main 结束时不会等待 goroutine 完成 goroutine 泄漏是常见 bug channel无缓冲 channel12345ch := make(chan int)go func() { ch <- 42 // 阻塞直到有接收者}()fmt.Println(<-ch) // 阻塞直到有数据 有缓冲 channel1234ch := make(chan int, 3)ch <- 1ch <- 2// 不会阻塞 常用并发模式1. Worker Pool123456789101112131415jobs := make(chan int, ...
Kubernetes 入门与生产实践
Kubernetes 入门与生产实践 Kubernetes 是云原生时代的事实标准。本文从核心概念到生产部署,系统梳理 K8s 学习路径。 核心概念1234567891011Pod(最小部署单元) ↓Deployment(无状态部署) ↓StatefulSet(有状态部署) ↓Service(服务发现) ↓Ingress(外部入口) ↓ConfigMap / Secret(配置管理) 为什么需要 K8s 自动伸缩:HPA 根据 CPU/内存/自定义指标扩缩容 自愈能力:Pod 异常自动重启 滚动更新:零停机发布 资源隔离:namespace + resource quota 生产部署要点1. 资源 requests / limits1234567resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 512Mi 2. 健康检查 livenessProbe:存活探针 readinessProbe:就绪探针 sta...
K3s NodePort 为什么只有一个节点能访问
K3s NodePort 为什么只有一个节点能访问 这类”诡异”的网络问题最能体现一个人的排障能力。本文完整记录一次 K3s NodePort 服务异常的真实排查过程。 问题现象集群有 3 个节点,部署了一个 NodePort 类型的服务。理论上,通过任意节点的 NodePort 端口都能访问到这个服务。但实际情况是: 节点 A 上访问:正常 ✅ 节点 B、C 上访问:超时 ❌ 排查思路遇到网络问题,先从数据包路径一层层排除。 第一层:服务本身是否正常在节点 A 上访问正常,说明服务本身没问题。问题出在”跨节点”的链路。 第二层:NodePort 规则是否生效1iptables -t nat -L -n | grep -A 5 NODEPORT 检查发现 B、C 节点上的 NodePort 转发规则是有的,问题不在 iptables。 第三层:跨节点 Pod 网络NodePort 流量进来后,最终要转发到 Pod。而 Pod 可能调度在别的节点上,流量要经过跨节点的容器网络(Flannel 隧道)。 在 B 节点上 ping Pod IP,发现不通。基本锁定是 Flann...
做完 RAG 技术培训之后的一些想法
最近花了一些时间整理 RAG 相关的内容,也算是把之前零零散散接触过的东西重新过了一遍。 刚开始接触 RAG 的时候,其实觉得这个东西挺简单。 把文档丢进去,切一下,做 Embedding,存到向量库里,用户提问的时候检索一下,再把检索结果交给大模型。 整个流程并不复杂。 真正自己去做、去讲的时候,才发现里面有不少细节。 最开始觉得问题都在模型以前遇到回答不准确,第一反应比较容易想到模型。 是不是模型能力不够? 是不是 Prompt 写得不好? 是不是换个模型就好了? 但把 RAG 的整个流程拆开之后,会发现很多问题其实和模型没什么关系。 比如一个很简单的问题: 知识库里明明有这条内容,为什么就是没搜出来? 这个问题继续往下查,可能发现是文档解析的问题,也可能是 Chunk 切得不合适,也可能是用户的问题和原文表达差异比较大,甚至可能是本来应该做关键词匹配,却只做了向量检索。 最后到了大模型这里,已经没有多少发挥空间了。 它拿到的内容都不对,你让它怎么回答? 所以现在再看到”RAG 幻觉”这个词,我不会第一时间把问题归到大模型身上。 很多时候,应该先看看: 到底给模型了什么。 文...
海量轨迹数据存储与分区优化
海量轨迹数据存储与分区优化 轨迹数据是典型的”海量时序 + 空间”双重特征的数据,存储设计不好,查询直接卡死。本文复盘一次轨迹数据存储方案的演进。 轨迹数据的特征以巡检人员定位为例,每个终端每隔几秒上报一个 GPS 点,一天下来就是海量数据: 单终端:约 2 万点/天 数百终端:数百万点/天 一年:上亿条 轨迹点有三个维度的特征:时间(何时)、空间(在哪)、对象(谁的)。查询场景也围绕这三者展开。 演进一:单表裸奔最初所有轨迹点堆在一张表里,按时间倒序查最近轨迹还算快(走时间索引)。但一旦查”某个时间段 + 某个区域”的历史轨迹,就要在几千万行里扫描,查询直接超时。 问题本质:单表没有利用时间这个天然的切分维度。 演进二:按时间分区轨迹数据最有效的优化是按时间分区。PostgreSQL 原生支持分区表: 12345678910CREATE TABLE track_points ( id BIGSERIAL, device_id VARCHAR(32), geom GEOMETRY(Point, 4326), ts TIMESTAM...
PostgreSQL + PostGIS 地理数据实践
PostgreSQL + PostGIS 地理数据实践 当业务里出现”点、线、面、轨迹、空间关系”这些概念时,PostGIS 是 PostgreSQL 最有力的扩展。本文梳理它的核心用法。 为什么不用 MySQL 存地理数据MySQL 也有空间类型,但能力远弱于 PostGIS。PostGIS 提供: 完整的几何类型(点、线、面、多点、集合) 丰富的空间函数(距离、包含、相交、缓冲区) 空间索引(GiST),让空间查询走索引 对 GIS 相关业务,PostgreSQL + PostGIS 是事实上的标准组合。 核心数据类型12345678-- 点SELECT ST_GeomFromText('POINT(121.4737 31.2304)', 4326);-- 线(轨迹)SELECT ST_GeomFromText('LINESTRING(121.47 31.23, 121.48 31.24)', 4326);-- 面(区域)SELECT ST_GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 ...
K3s 轻量级集群搭建与踩坑
K3s 轻量级集群搭建与踩坑 对很多中小规模团队来说,完整 Kubernetes 太重,K3s 是更现实的选择。本文记录我在政企内网环境搭建 K3s 集群并承载生产服务的完整过程。 为什么选 K3s我们面临的环境是:内网隔离、机器资源有限(几台普通服务器)、没有专职 SRE。在这种条件下: 完整 K8s 的 etcd、控制面组件开销大、维护成本高 K3s 把控制面打包成单个二进制,默认用 SQLite 存数据,资源占用极低 更重要的是,K3s 保留了标准 Kubernetes API,业务上的编排能力一点不少。 搭建过程安装本身非常简单: 12345# 主节点curl -sfL https://get.k3s.io | sh -# 查看节点 token,供 worker 加入cat /var/lib/rancher/k3s/server/node-token worker 节点加入: 12curl -sfL https://get.k3s.io | K3S_URL=https://<master-ip>:6443 \ K3S_TOKEN=<node-t...
MySQL 索引优化实战
MySQL 索引优化实战 索引是 MySQL 性能优化的第一抓手。本文系统梳理索引原理与实战经验。 索引基础B+ Tree 索引InnoDB 默认索引结构是 B+ Tree: 叶子节点存储数据(聚簇索引)或主键(二级索引) 非叶子节点只存储键值和指针 叶子节点之间通过链表相连,适合范围查询 聚簇索引 vs 二级索引 聚簇索引:叶子节点存完整行数据(每张表只有一个) 二级索引:叶子节点存主键值,需要回表查询 索引失效的常见情况 SQL 写法 是否走索引 WHERE col + 1 = 5 ❌ 函数失效 WHERE col LIKE '%abc' ❌ 前导模糊 WHERE col IS NULL ⚠️ 取决于数据分布 WHERE col IN (...) ✅ 命中索引 WHERE col = 'a' AND col2 = 'b' ✅ 联合索引 索引设计原则 高频查询字段建索引 区分度高的字段建索引(如 user_id,避免在 gender 上建索引) 联合索引注意顺序:最左前缀原则 不要过度索引:写...
