Postgres LSN十六进制转十进制:原理、SQL解法与排障实践
一碰到 Postgres 的 LSN 十六进制转十进制这种事很多人的第一反应就是打开计算器。上次处理一个压测环境的复制延迟告警监控面板上主库的pg_current_wal_lsn()显示为1C/6B32E8F0备库的pg_last_wal_replay_lsn()是1C/5B3122A0值班同事随手就找在线进制转换工具想把两个都换成十进制再减。我跟他说如果只是想看延迟直接用pg_wal_lsn_diff()就行一行 SQL 的事根本不用人肉换算但如果你要的是监控采集里的 WAL 字节数、要算每秒钟产生了多少 WAL、或者想把某个工具导出的十进制位置写回recovery_target_lsn那就必须把这串十六进制的结构彻底吃透。这篇文章就当一次排障笔记来写不端着讲课的架子。下面要讲的六件事都是这类换算里真正绕不开的点LSN 为什么长成两段十六进制、手工怎么算、用 SQL 怎么写最稳、算完用在哪儿、我在实际操作中踩过的边界和坑以及最后怎么快速验证你没算错。1. LSN为什么长成两段十六进制的样子1.1 本质上就是一个不停递增的64位计数器Postgres 里每个 WAL 记录都有一个唯一的日志序列号 LSN它的底层类型就是无符号 64 位整数。从这套 WAL 逻辑编号体系开始工作起这个数就一直往上加每次写入一个 WAL 记录它就前进相应的字节数。你可以把它理解成一个累计写入的 WAL 字节数只不过这个计数器的起点不只是 0而且它跨越了无数次服务器启停、日志段轮换依旧在同一个逻辑空间里持续递增。pg_lsn类型在输出时把这个 64 位整数拆成两半左边是高 32 位右边是低 32 位各自用十六进制表示前导零省略中间用斜杠分隔。比如1C/6B32E8F0左边的0x1C是高 32 位的值右边的0x6B32E8F0是低 32 位的值。每一位十六进制代表 4 个二进制位所以两边正好各占 8 位十六进制看起来就像一段内存地址。提示LSN 不是内存地址也不是某个真实文件里的绝对偏移。它是一个逻辑空间的字节位置通过换算可以映射到 WAL 文件名和段内偏移。为什么 PostgreSQL 不直接显示成十进制两个原因。第一这种 X/Y 格式跟 WAL 文件名的生成逻辑天然对应DBA 扫一眼就能大概判断这个位置落在哪个日志段附近第二64 位无符号数很快会变成很大的十进制数反而不如十六进制紧凑。所以 PostgreSQL 从设计上就选了这种两个 32 位十六进制段作为人类可读的展示格式。1.2 高位和低位之间隔了整整 2^32 个字节把 64 位拆成两半之后最容易搞混的就是左边的数每增加 1不代表右边滚了一圈 16MB而是代表跨过了 2^32 个字节也就是 4294967296 字节。默认 WAL 段大小是 16MB2^24 字节2^32 字节正好等于 256 个段。所以 LSN 从0/FFFFFF走到0/1000000时只是跨过了 16MB 的边界此刻左边还是 0要一直到低 32 位写满0xFFFFFFFF下一个位置才会进位成1/0。换句话说左边高 32 位每加 1WAL 已经累计往前推进了 4GB。这个结构直接决定了 WAL 文件名的拼法。WAL 文件名是 24 个十六进制字符由三段组成8 位时间线号、8 位逻辑段号的高 32 位、8 位逻辑段号的低 32 位。逻辑段号本身等于LSN 除以段大小取整段内偏移等于LSN 对段大小取余。理解了这一层后面所有换算就都顺了——你真正要操作的对象是一个连续的 64 位字节计数器而不是两个毫无关系的十六进制数。2. 手工换算拆开、乘以2的32次方、再加回去2.1 核心公式decimal X × 4294967296 Y先把 LSN 字符串按斜杠拆成 X 和 Y 两个十六进制数再把各自转成十进制代入公式LSN 的十进制表示 X 的十进制值 × 4294967296 Y 的十进制值。乘的这个 4294967296 就是 2^32也就是高 32 位每跳 1 所代表的字节数。拿1C/6B32E8F0来算一遍。左边0x1C等于十进制的 28右边0x6B32E8F0按位权展开6×16^7 11×16^6 3×16^5 2×16^4 14×16^3 8×16^2 15×16 0 1610612736 184549376 3145728 131072 57344 2048 240 1798498544于是完整十进制 LSN 28 × 4294967296 1798498544 122057582832。如果嫌逐位乘 16 麻烦Windows 计算器的程序员模式、macOS 系统自带的计算器甚至手机上的进制转换工具都能做。不过终端里最利索的方式是直接用 shell 内置功能printf %d\n 0x6B32E8F0立刻得到 1798498544。低 32 位和完整 64 位都能这么转只要 printf 的宿主 shell 支持 64 位整数运算。我整理了一份常见 LSN 样例的换算对照表方便你核对公式LSN十六进制高32位十进制低32位十进制完整十进制LSN段号段内偏移0/FFFFFF016777215167772150167772150/16C266802386493623864936170877201C/6B32E8F028179849854412205758283272753336432FFFFFFFF/FFFFFFFF4294967295429496729518446744073709551615109951162777516777215这个表里最后一行是理论最大值生产库现实中到不了这个量级但它最能说明为什么中间值必须用 numeric 而不是 bigint后面第 5 节会展开讲。2.2 反向十进制还原成 LSN反过来要把十进制数还原成 X/Y 格式就对这个数做除以 4294967296 的整除和取余商就是 X余数就是 Y。比如 122057582832 除以 4294967296商是 28余数是 1798498544把 1798498544 写成十六进制得到6B32E8F0于是还原为1C/6B32E8F0。这个反向过程很多时候比正向更实用。备份工具、运维平台导出的位置信息经常是十进制字节数而 Postgres 的recovery_target_lsn参数只认1C/6B32E8F0这种格式配置 PITR 时就得做这一步还原。手工做的话用整除取余很快要自动化的话直接跳到下一节用 SQL 里的pg_lsn加法一行就够。2.3 顺手把 WAL 文件名和段内偏移也算出来拿到完整十进制 LSN 之后还能继续算 WAL 日志文件名这在实际排障里价值很大。默认段大小 16MB也就是 16777216 字节。逻辑段号 完整十进制 LSN ÷ 16777216 取整段内偏移 完整十进制 LSN ÷ 16777216 取余。对 122057582832 来说122057582832 ÷ 16777216 7275 余 3336432。段号 7275 写成十六进制是0x1C6B所以在时间线为 1 的情况下WAL 文件名是000000010000000000001C6B段内偏移 3336432 字节也就是从段头开始约 3.18MB 的位置。这个映射关系非常值得记住当监控或日志里出现一个 LSN你先用这个办法定位到具体 WAL 文件然后直接去$PGDATA/pg_wal目录下找对应文件检查比对着十六进制发懵高效得多。如果段大小不是 16MB用完整十进制 LSN 除以实际的段大小字节数即可公式在任何段大小下都成立。3. SQL原生解法让pg_lsn自己完成进位3.1 最省事用 pg_lsn 减法一行搞定如果能直接在数据库里操作最省事的方式不是自己拆字符串而是利用pg_lsn类型自带的减法运算符。pg_lsn减去pg_lsn得到 numeric也就是两个位置之间相差的字节数SELECT pg_current_wal_lsn() - 0/0::pg_lsn AS lsn_decimal; SELECT 1C/6B32E8F0::pg_lsn - 0/0::pg_lsn AS lsn_decimal;第二条语句返回122057582832。它的原理就是拿目标 LSN 跟全零 LSN 做差差值天然就是完整的十进制 LSN 大小。反过来要把十进制变回 LSN直接加回去SELECT 0/0::pg_lsn 122057582832 AS lsn_hex; -- 结果1C/6B32E8F0这是我在脚本里最常用的姿势。让 Postgres 自己处理高低位的进位和类型转换出错概率最低。3.2 通用解法hex字符串用bit(32)::bigint强转有些场景不能直接依赖pg_lsn类型比如你从日志、监控系统拿到的是一个纯文本 LSN 字符串想在一条 SQL 里就地完成换算。这时候可以用 Postgresbit类型的输入解析特性字符串以x开头时bit类型会按十六进制解析。配合lpad补足 8 位十六进制再转成 bigint就能拿到单半边 32 位的十进制值SELECT (x || lpad(1C, 8, 0))::bit(32)::bigint AS high_dec, (x || lpad(6B32E8F0, 8, 0))::bit(32)::bigint AS low_dec;第一行返回 28第二行返回 1798498544。组合成完整 LSN 时要注意如果直接让 bigint 乘 4294967296在 X 很大的情况下会溢出。所以乘法前先把它转成 numeric这是稳妥写法WITH p AS ( SELECT lsn, split_part(lsn::text, /, 1) AS high_hex, split_part(lsn::text, /, 2) AS low_hex FROM (SELECT pg_current_wal_lsn() AS lsn) s ) SELECT ((x || lpad(high_hex, 8, 0))::bit(32)::bigint)::numeric * 4294967296::numeric (x || lpad(low_hex, 8, 0))::bit(32)::bigint::numeric AS lsn_decimal FROM p;如果这套逻辑经常要用建议封装成自定义函数放进公共 schemaCREATE OR REPLACE FUNCTION lsn_to_decimal(lsn pg_lsn) RETURNS numeric LANGUAGE sql IMMUTABLE AS $$ SELECT ((x || lpad(split_part(lsn::text, /, 1), 8, 0))::bit(32)::bigint)::numeric * 4294967296::numeric (x || lpad(split_part(lsn::text, /, 2), 8, 0))::bit(32)::bigint::numeric; $$;再配一个反向函数decimal_to_lsnCREATE OR REPLACE FUNCTION decimal_to_lsn(v numeric) RETURNS pg_lsn LANGUAGE sql IMMUTABLE AS $$ SELECT 0/0::pg_lsn v; $$;两个函数配合使用decimal_to_lsn(lsn_to_decimal(1C/6B32E8F0::pg_lsn))可以原样还原。3.3 先别急着换算有些场景根本不需要十进制很多场景下 Postgres 已经帮你把换算做好了。比较两个 LSN 直接可以用比较运算符因为pg_lsn类型内部就是按 64 位整数比较的计算复制延迟用pg_wal_lsn_diff()要知道某个 LSN 在哪个 WAL 文件、文件里偏移多少用pg_walfile_name_offset()。这些函数返回的都是语义化结果比你手动转十进制再自己算要可靠得多。我自己定位问题时的顺序是先看pg_wal_lsn_diff()能不能满足需求再看pg_walfile_name_offset()最后才考虑自己换算。换算只用于那些必须把 LSN 变成纯数值的场景比如监控采集、跨系统传输、二次计算。4. 换算成十进制之后最常落地的三个场景4.1 监控把两次采样差变成WAL字节数数据库监控里最常见的需求是算每秒钟产生了多少 WAL。大多数监控采集器拿到pg_current_wal_lsn()时它是个文本值不能直接求导。把每次采样换算成十进制后落库两次采样值的差就是这段时间写入的 WAL 字节数除以时间间隔就是速率。举个具体例子。假设 10 分钟内采集到两个 LSNt11C/6B32E8F0→ 122057582832t21C/7B42F398→ 122327069592差值是 269486760 字节约 257MB。除以 600 秒得到每秒约 0.43MB 的 WAL 产生速率。这个数字可以直接喂给 Prometheus 画曲线也可以写成告警规则比如WAL 产生速率超过 X MB/s 时报警。我见过不少团队用这个方法做日志风暴告警——WAL 速率突然飙高往往意味着有大批量更新或者被遗忘的循环写任务在跑。采集 SQL 可以直接复用 3.2 节里的 CTE 写法集成到 postgres_exporter 的自定义查询里即可。注意采样落库时用 numeric 类型不要用 float原因在第 5 节讲。4.2 复制延迟备库落后多少字节复制延迟的标准算法本来就应该用pg_wal_lsn_diff()一条 SQL 精确到字节。在备库上执行SELECT pg_wal_lsn_diff(pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn()) AS receive_replay_lag_bytes;但如果你的监控系统里只存了两条文本 LSN或者你想在事后复盘时用历史数据重新计算那就只能先把两个 LSN 都转成十进制再相减。这里有个细节备库上别用pg_current_wal_lsn()它反映的是本地 WAL 状态容易误导备库该用的是pg_last_wal_receive_lsn()接收到的位置和pg_last_wal_replay_lsn()回放到的位置。这两个函数返回的都是pg_lsn可以直接做差。用十进制换算还有一个附加价值字节数可以跟网络传输速率、磁盘 IO 对账。比如备库接收位置落后主库 800MB按当前网络吞吐估算恢复时间这些都需要字节粒度而不是只看一个看起来差不多的十六进制数。4.3 PITR/归档把十进制位置写回 recovery_target_lsnrecovery_target_lsn参数只接受1C/6B32E8F0这种格式。如果你从备份元数据或某个运维平台拿到的是十进制位置就用反向转换还原成 LSN 再配置psql -XAt -c SELECT 0/0::pg_lsn 122057582832;输出1C/6B32E8F0直接填进 recovery.conf 或 postgresql.conf 的recovery_target_lsn。另外pg_controldata输出的Latest checkpoint location、pg_basebackup的起始位置都是这类 LSN用同样思路做归档对账把某两个备份点的 LSN 差除以段大小就能估算两个备份之间需要保留多少个 WAL 段这对存储规划很有用。LSN差字节÷ 段大小 1 中间跨越的WAL段数量这个公式在规划归档保留策略时比任何估算都准。5. 最容易翻车的几个边界点5.1 bigint放不下整个LSN要用numericLSN 是 64 位无符号整数理论最大值FFFFFFFF/FFFFFFFF换算成十进制是 18446744073709551615而 PostgreSQL 的 bigint 最大只有 9223372036854775807连一半都不到。所以任何把整个 LSN 塞进 bigint 再计算的写法都有溢出隐患。尤其是我前面强调过的组合写法X 一旦超过 0x80000000X × 2^32就爆掉 bigint。正确做法是全程用 numeric。目前生产库的 LSN 远没到溢出阈值但写函数和监控脚本时养成 numeric 习惯能把隐患消灭在设计阶段。顺便说一句pg_wal_lsn_diff()和pg_lsn减法的返回值设计成 numeric不是为了装高精度小数正是为了绕过这个容量问题。另一个隐藏坑是 float 精度。如果你在 Python 里用 float 存 LSN 十进制值float64 只有 53 位有效数字无法精确表示 64 位整数采样多了误差会累积。JSON 接口传大整数也要注意很多语言的 JSON 解析器会把它转成 float。跨系统传递 LSN 十进制值时一律用字符串或数值字符串。5.2 版本差异xlog改名为wal函数别用老了PostgreSQL 10 之前WAL 相关函数叫 xlog函数名里全是 xlog10 之后统一改成 wal。如果你还在维护老版本或者在一堆旧脚本里扒代码这个对照表很实用PostgreSQL 9.4 ~ 9.6PostgreSQL 10pg_current_xlog_location()pg_current_wal_lsn()pg_xlogfile_name(lsn)pg_walfile_name(lsn)pg_xlogfile_name_offset(lsn)pg_walfile_name_offset(lsn)pg_xlog_location_diff(a, b)pg_wal_lsn_diff(a, b)另外 PG13 开始多了pg_current_wal_insert_lsn()返回的是插入位置pg_current_wal_lsn()返回的是刷盘位置。算 WAL 产生速率时如果写入很频繁两者会有细微差别。选一个口径并保持一致就行别在同一个报表里混用两个函数。5.3 wal_segment_size 未必是 16MB默认 16MB 在绝大多数环境里成立但 PG11 之后initdb支持用--wal-segsize指定 1MB、4MB、16MB、64MB、256MB。一旦段大小不是 16MB我前面提过的高位换算文件号那套位运算就不成立。但好消息是只要你不是死记位运算而是用完整十进制 LSN 直接除以实际段大小的字节数公式在任何段大小下都成立。判断当前实例的段大小SHOW wal_segment_size;拿到的是类似16MB的字符串写脚本时记得转成字节数再去除。处理历史备份时也要注意不同实例可能用不同段大小初始化从旧备份恢复前先确认目标实例的段大小否则算出的文件号对不上。5.4 lpad和bit强转的细节坑用(x || hex)::bit(32)::bigint这个技巧时我踩过两次坑。第一次是忘了 lpad左侧高 32 位在很多真实 LSN 里只有一两位十六进制比如0/16C2668如果直接对0做::bit(32)会因为位数不够而报错。所以不管哪半边都先用lpad补足 8 个十六进制字符。第二次是输入来源不干净。如果 LSN 字符串来自外部系统可能带0x前缀、带空格、大小写混用甚至因为 JSON 解析被截断。进 SQL 之前最好统一做一次trim、replace(0x,)等清洗。大小写其实没问题bit 类型的十六进制解析大小写都认但前缀和空格一定要处理干净。6. 花一分钟验证换算结果附shell/Python速转6.1 往返验证法最靠谱的验证方式是去又回。算完十进制之后马上用反向加法还原成pg_lsn看是否等于原始值。拿第 3 节的两个自定义函数SELECT lsn_to_decimal(1C/6B32E8F0::pg_lsn) AS dec, decimal_to_lsn(lsn_to_decimal(1C/6B32E8F0::pg_lsn)) AS back, lsn_to_decimal(1C/6B32E8F0::pg_lsn) 122057582832 AS ok;如果ok列是t说明函数逻辑和手工计算全部对上。任何换算逻辑上线前先用几个已知 LSN 做一遍往返验证能拦下绝大多数低级错误。6.2 用pg_walfile_name_offset和磁盘文件对拍另一个更贴近实际的验证是看换算结果跟 Postgres 官方函数是否一致。把同一个 LSN 交给pg_walfile_name_offset()让它返回文件名和偏移再跟你自己算的 7275 号和 3336432 偏移对比SELECT * FROM pg_walfile_name_offset(1C/6B32E8F0::pg_lsn);返回(000000010000000000001C6B, 3336432)。然后去数据目录看一眼这个文件的大小是不是 16777216 字节ls -l $PGDATA/pg_wal/000000010000000000001C6B再往前一步用十六进制查看器或者xxd读一下文件头部确认不是空文件、没被截断xxd -l 64 $PGDATA/pg_wal/000000010000000000001C6BWAL 文件头部有固定的魔数字段HxD 这类编辑器也能直接打开看。这一套对拍做完基本可以放心把换算逻辑写进任何脚本。6.3 终端里秒换算日常排查时我一般直接在终端处理没必要开数据库。三个顺手命令分享一下# 低32位十六进制转十进制bash内置printf printf %d\n 0x6B32E8F0 # 任意完整LSN转十进制Python python3 -c x,y1C/6B32E8F0.split(/); print(int(x,16)*2**32 int(y,16)) # 有psql环境就直接用类型自带的减法 psql -XAt -c SELECT 1C/6B32E8F0::pg_lsn - 0/0::pg_lsn;三个输出的结果应该完全一样122057582832。这也是我最推荐的验证思路——不同工具算同一个数结果一致才是真的正确。最后分享一点个人体会不要在脑子里死记 LSN 和 WAL 文件号之间的位运算更不要写死 16MB。把LSN 是一个 64 位无符号字节计数器这个认知建立起来所有换算都围绕十进制字节数展开遇到任何段大小、任何版本、任何函数名都能快速推导。真到了要算偏移的时候先试试 Postgres 自带的pg_walfile_name_offset()能不能直接满足需求——能就别自己造轮子。

相关新闻

DeepSeek-Harness实操手册:CLI与Web UI双路径快速上手

DeepSeek-Harness实操手册:CLI与Web UI双路径快速上手

这篇其实拖了一阵子,之前写第一篇的时候还在讲架构,收到了不少读者反馈说“能不能别铺垫了,直接让我跑一遍”。那这次就直接点,把 DeepSeek-Harness 的 CLI 和 Web UI 两条路径从头到尾走一遍,带配置、带命令、带排坑记…

2026/9/24 20:13:35 阅读更多 →
HD/FHD/UHD分辨率本质:人眼、屏幕与物理极限的真相

HD/FHD/UHD分辨率本质:人眼、屏幕与物理极限的真相

1. 这不是参数游戏,而是人眼与屏幕的物理对话你刷短视频时突然被弹出一条广告:“4K超清画质,细节纤毫毕现!”——下一秒切到朋友发来的旅行视频,标着“HD”,画面却莫名发虚;再点开某平台自制剧&…

2026/9/24 20:13:35 阅读更多 →
基于Python与机器学习的房价预测系统全流程开发指南

基于Python与机器学习的房价预测系统全流程开发指南

1. 为什么“房价预测系统”是每年毕设选题里的常青树 先说个可能和你想的相反的现象:房价预测系统在各大毕设选题平台上一抓一大把,很多人看一眼就觉得“太大众了”“没新意”,但实际上每年靠这个题目拿到优秀毕设的人不在少数。原因不复杂—…

2026/9/24 20:13:35 阅读更多 →

最新新闻

如何优雅处理“AI bs”:从需求澄清到架构隔离的完整指南

如何优雅处理“AI bs”:从需求澄清到架构隔离的完整指南

你正在写一个无关紧要的配置模块,经理从线上开会回来,丢下一句"我们得在这个版本里把AI加上"。你问加什么AI、解决什么问题、给谁用,经理说"就是那种AI,你懂的,别人都有了,我们不能落后&quo…

2026/9/24 21:34:32 阅读更多 →
ZooKeeper投票五元组深度解析:从选举原理到故障排查

ZooKeeper投票五元组深度解析:从选举原理到故障排查

1. 从一次诡异的集群故障说起先说个真实案例。有一次我在测试环境搭了一套三节点的 ZooKeeper 集群,版本是 3.5.7,机器配置都正常,网络也通。启动之后我例行检查了一下状态,发现 leader 节点一直不稳定,隔几分钟就重新…

2026/9/24 21:34:32 阅读更多 →
交换机路由器配置实战:从Console到业务通的全链路解析

交换机路由器配置实战:从Console到业务通的全链路解析

1. 为什么“交换机、路由器配置”不是一句空话,而是网络工程师每天要拆解的活儿你有没有遇到过这样的场景:刚接手一台新到的华为S5720交换机,连上Console线,敲完system-view,手却停在了那里——接下来该输什么&#xf…

2026/9/24 21:34:32 阅读更多 →
中文命名实体识别实战:BERT+BiLSTM+CRF技术栈详解

中文命名实体识别实战:BERT+BiLSTM+CRF技术栈详解

简介:这是一份基于BERTBiLSTMCRF实现中文命名实体识别的Python课程设计源码,主要面向需要完成NLP方向课程设计、期末大作业或毕业设计的本专科学生。项目实现了从原始语料处理、字符编码、BERT向量表征、BiLSTM特征提取到CRF序列解码的完整NER流程&#…

2026/9/24 21:34:32 阅读更多 →
OpenWiki 实战:本地 Markdown 知识库与 AI Agent 集成指南

OpenWiki 实战:本地 Markdown 知识库与 AI Agent 集成指南

1. 从命令行到知识库:OpenWiki 到底解决了什么问题第一次听说 OpenWiki 是在一个做 AI Agent 开发的朋友群里,有人甩了张截图:终端里敲一行命令,本地的 Markdown 文件夹瞬间变成一套可检索、可对话的知识库,还能直接挂…

2026/9/24 21:34:32 阅读更多 →
Uni LLM Bench:自托管LLM API基准测试平台实战指南

Uni LLM Bench:自托管LLM API基准测试平台实战指南

1. 为什么要自己做一套 LLM API 基准测试平台先说个真实场景。我们团队做多租户平台,上游接了好几家大模型 API,有官方的,也有走聚合网关的。上个月某个渠道换了底层模型,线上监控没做细,等业务方反馈"回答变慢了…

2026/9/24 21:33:32 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →