笔记
0工具
0此页用于记录用户反馈问题后的每一次改进
关于
“写笔记”支持四种格式——Word 文档、Excel 表格、Markdown、纯文本,起稿或二次编辑时都能随时切换,同一篇笔记想用哪种形态来记,都由你说了算。
md、txt、csv、json 这类纯文本则原样载入,不做多余加工。拿一张现成的表倒进来、改几笔、再导出去,等于白用一台免费的格式转换器。
要带走就在右上角点“下载”,可导出 PDF、Word、Markdown、Excel、TXT 等格式;列表卡片“⋯”菜单里,也有同样的下载入口。
在“工具”页点“+ 上传工具”即可发布:填好名称与链接,再用 Markdown 把使用方法写清楚——能解决什么问题、怎么装、怎么用,比堆介绍实在。
要分发安装包就一并上传压缩包(ZIP、RAR、7Z、TAR.GZ,最大 35MB),别人在详情页一键下载;只放链接不带附件也可以。
工具按大家的收藏热度排序,好用的自然会被顶上来。发布后可在详情页或卡片菜单里编辑、下架。
写笔记时勾上“隐藏”,这篇就只存在于你自己的账号里:不进列表、不进搜索、不上首页精选,也不会出现在任何公开的页面,链接发给别人同样打不开。
适合放密码、草稿、日记这类只给自己看的内容;想公开,去“发布”打开它,把“隐藏”的勾去掉再保存,之后编辑会默认保持原状态,不会悄悄变回公开。
不想公开、只想临时给人看:点“分享”生成一条带密码和有效期的链接,到期自动失效,你也能随时撤销。
你的内容会同时保存在多个副本上,系统定期做备份与完整性校验,再配合异地容灾机制:就算某台机器出问题,数据也不会丢,可以长期放心存放;特别重要的资料,仍建议你另外再留一份备份。
全站跑在容器化、模块化的现代架构上,更新、部署、回滚都很快,扩展性和稳定性都按长期运营的标准来设计(Built for reliability, designed to scale)。
这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。
不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。
产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。
如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。
趋势
PgDog:一个保留完整 Postgres 特性的连接池代理
PgDog 是一个新的 Postgres 连接池,它通过保留 SET、LISTEN/NOTIFY 等原生特性,解决了现有池化工具的抽象泄漏问题。
为什么还需要另一个连接池?
在 Postgres 生态中,连接池是一个老生常谈的话题。市面上已经有 PgBouncer、RDS Proxy、Pgpool-II、Supavisor 等成熟工具,但 PgDog 的开发团队仍然选择从头构建一个新的连接池代理,核心原因在于:现有工具都引入了“泄漏的抽象”(leaky abstraction)。
大多数 Postgres 生态工具遵循 Unix 哲学:只做一件事,并把它做好。这种设计哲学催生了像 PgBouncer 这样稳定可靠的软件。但当你部署这些工具时,很快就会发现它们改变了你使用数据库的方式。你需要做出权衡,通常还需要修改应用程序代码。对于已经运行一段时间的应用——这恰恰是大多数需要连接池的场景——这意味着要修改数千行生产代码,而且往往缺乏测试覆盖。
连接状态:第一个被牺牲的特性
当你添加一个连接池时,首先失去的是会话控制,也就是 SET 命令。SET 用于临时覆盖数据库设置,例如执行慢查询:
sql
SET statement_timeout TO '5m';
SELECT * FROM users WHERE banned IS true;
问题在于,连接池会在客户端之间复用连接。一个客户端的连接状态会“泄漏”到另一个客户端。在生产环境中,这可能导致严重后果。最好情况下,一个慢查询会运行很长时间,引发数据库事故;最坏情况下,依赖会话变量的行级安全(RLS)策略会失效,导致数据行静默消失。
因此,迁移到连接池时的典型建议是:不再使用 SET。但 SET 是 Postgres 的原生功能,如果你不能使用数据库的原生功能,就意味着你做出了权衡,必须改变应用开发方式。如果你在 RLS 等关键场景中使用 SET,那么你根本无法使用连接池。
PgDog 如何处理 SET 语句
PgDog 内置了一个 SQL 解析器。它可以检测 SET 语句,提取变量名和值,并将它们存储在代理的每个客户端连接上。当客户端执行查询时,PgDog 首先检查客户端状态是否与服务器状态匹配。如果不匹配,它会通过执行一系列 SET 语句来更新服务器状态。
检测 SET 语句的算法非常高效。如果多个变量不同,PgDog 使用查询流水线(query pipelining)在一次往返中完成更新。这使得性能影响非常小,让你在扩展数据库时仍然可以继续使用依赖的 Postgres 特性。
LISTEN/NOTIFY:发布订阅的困境
LISTEN 和 NOTIFY 是 Postgres 实现的发布/订阅队列命令。这是一个很酷的特性,无需额外的数据库就能很好地工作。但当你添加连接池,尤其是使用事务模式时,这个特性也必须放弃。如果你在过去十年(PostgreSQL 10 于 2017 年发布)构建过应用,很可能在迁移到 SQS 或 Redis 之前使用过它。
PgDog 让 LISTEN/NOTIFY 也能正常工作。它在内部处理这两个命令,同时在多个 PgDog 进程之间传递消息。对客户端来说,PgDog 看起来就是消息代理,但实际后端仍然是 Postgres。PgDog 还完整保留了 NOTIFY 的事务语义——甚至包括那些曾导致某些朋友数据库崩溃的边缘情况(团队已经修复了这个问题)。
内部实现相当有趣:PgDog 使用 Tokio 的广播通道在同一个进程内的客户端之间传递消息。为了支持多个 PgDog 进程(例如生产环境中运行多个容器),它还会通过专用连接将所有 LISTEN 和 NOTIFY 命令发送到 Postgres。因此,PgDog 实际上充当了一个发布/订阅客户端,代理其他发布/订阅客户端,而 Postgres 作为真正的消息代理。这是一种创造性的工程实践,目标只是让一个常用特性“开箱即用”。
多线程:超越传统进程模型
PgDog 基于 Tokio 构建,这是一个支持多线程工作器的 Rust 异步运行时。每个客户端由独立的异步任务处理,任务数量随连接数线性扩展。利用 Tokio,PgDog 可以充分利用多核 CPU,从单个进程服务更多客户端和每秒更多查询。
对比来看,PgBouncer 支持 SO_REUSEPORT,RDS Proxy 支持“无服务器”自动扩展,但两者都需要你“分片”连接池。每个代理进程拥有自己专用的一组 Postgres 连接。一旦客户端连接,就不能再切换实例。因此,如果某个进程过载,所有连接到它的客户端都会被阻塞。
通过多线程利用多核 CPU,PgDog 进程可以处理更多流量,用更少的服务器连接池化更多客户端,从而提高连接利用率和效率。多线程进程还能更好地处理突发查询,因为它们无需等待自动扩展。如果你的应用有延迟 SLA,你不会希望代理成为瓶颈。
最后但同样重要的是,管理多线程进程的运行手册更简洁:只需监控一个指标和健康检查源,无需将复杂性推送到难以调试的地方(如 Linux 内核或 AWS RDS 控制平面)。
总结
替换像 PgBouncer 这样有 20 年历史的项目并不容易,但当我们认为某些地方不太对劲时,就会去修复它。PgDog 已经投入生产超过一年,在 2M QPS 的负载下稳定运行。它是自由开源软件,你可以自由使用和修改,并且可以部署在任何地方。
原文链接:https://pgdog.dev/blog/why-yet-another-connection-pooler