S.EE 上线文件分享功能了。

跟那些套路网盘不一样,没倒计时、没广告、没限速,给链接就能下。

功能一览

  • 直链分享:上传完直接拿到文件直链,可以嵌 Markdown 、README 、论坛、博客,想怎么用怎么用
  • 断点续传:大文件不怕断网,支持 tus 协议
  • 全球 CDN:下载走 CDN ,速度有保障
  • 短域名:官方提供 fs.to / files.to / fileshare.to,也支持绑自己的域名

示例

直链链接可以在分享页面里获取

适合谁用?

  • 运维直接 wget 拉文件
  • 开发者放 Release
  • 设计师发素材
  • 任何「给个链接就能下」的场景

关于稳定性

我们的 SM.MS 图床从 2015 年运营到现在 10 年了,S.EE 是同一个开发团队。

价格

文件分享需要付费账号,套餐详情: https://s.ee/pricing/

相关链接

有问题随时反馈 🙏

另外 SM.MS 付费用户近期会迁移到 S.EE ,届时我们会邮件通知。

大佬们好,我最近花了几个月的时间做了一个英雄联盟云顶之弈自动挂机的软件,初衷是为了全自动刷通行证和宝典。

Github 地址:Tft-Hextech-Helper

软件截图

具体的方案是纯粹的视觉识别:OCR+模版匹配。不涉及任何的内存读取,操作则控制鼠标进行点击。同时使用了 LOL 官方公开的 API 接口来实现自动排队,自动接收对局等,目前可以做到全流程打通,挂一整天完全不用手动。我高强度挂机了两天,从青铜打到了白银三,期间没有被封过。

这里想跟各位大佬交流一下,这种完全不读取内存的方案,存在被封号的可能性吗?会不会检查玩家的鼠标移动是否平滑之类的?希望大佬们积极解答,也欢迎使用和 star 。

把以前写的饭否 iOS 客户端开饭使用 AI 重写了,感觉很不错了,很多功能我以前根本不会写,我只能说 AI 真的太强了

更新日志:

  • 更流畅的体验

  • 转发、回复交互逻辑修改

  • 支持语音输入

  • 支持 ocr 输入

  • 拍照支持多种滤镜

  • iPad 上支持分屏界面

  • 支持自定义 tab 栏

  • 支持自定义字体

  • 支持分享图片、复制图片

  • 使用本机数据库存储 节省流量更流畅

  • 主题只保留黑色、白色和跟随系统

  • 增加一些动画效果

  • 下载链接

https://apps.apple.com/hk/app/开饭-饭否客户端/id1189449526

以前的我:
   这个我不会,这页面好卡,这里怎么闪退了

现在有了 AI 的我:
   我现在强得可怕

我现在强得可怕

团队里越来越多的人开始 vibe coding ,但我还是比较反感的,主要原因如下:

  1. 会生成大量无意义代码。打个比方,它生成的代码就像一个初级开发,不知道从哪里 copy 来的高级代码。有时乍一看,真高端,仔细阅读,完全没起到作用,这啥玩意嘛。
  2. 难以理解。vibe coding 生成的代码量要远远大于常规开发,AI 阅读代码的速度是真的快,但一旦交给人去理解,往往要浪费很多时间。
  3. 最重要的一点,传播性强,像病毒。在一个没有 CodeReview 的项目中,原本屎山代码就算了,好歹代码简单,现在还塞了一堆你不认识的元素进去。项目一旦有人大量使用了,后来的人如果不用,维护起来十分困难。

S.EE 上线文件分享功能了。

跟那些套路网盘不一样,没倒计时、没广告、没限速,给链接就能下。

功能一览

  • 直链分享:上传完直接拿到文件直链,可以嵌 Markdown 、README 、论坛、博客,想怎么用怎么用
  • 断点续传:大文件不怕断网,支持 tus 协议
  • 全球 CDN:下载走 CDN ,速度有保障
  • 短域名:官方提供 fs.to / files.to / fileshare.to,也支持绑自己的域名

示例

直链链接可以在分享页面里获取

适合谁用?

  • 运维直接 wget 拉文件
  • 开发者放 Release
  • 设计师发素材
  • 任何「给个链接就能下」的场景

关于稳定性

我们的 SM.MS 图床从 2015 年运营到现在 10 年了,S.EE 是同一个开发团队。

价格

文件分享需要付费账号,套餐详情: https://s.ee/pricing/

相关链接

有问题随时反馈 🙏

另外 SM.MS 付费用户近期会迁移到 S.EE ,届时我们会邮件通知。

大佬们好,我最近花了几个月的时间做了一个英雄联盟云顶之弈自动挂机的软件,初衷是为了全自动刷通行证和宝典。

Github 地址:Tft-Hextech-Helper

软件截图

具体的方案是纯粹的视觉识别:OCR+模版匹配。不涉及任何的内存读取,操作则控制鼠标进行点击。同时使用了 LOL 官方公开的 API 接口来实现自动排队,自动接收对局等,目前可以做到全流程打通,挂一整天完全不用手动。我高强度挂机了两天,从青铜打到了白银三,期间没有被封过。

这里想跟各位大佬交流一下,这种完全不读取内存的方案,存在被封号的可能性吗?会不会检查玩家的鼠标移动是否平滑之类的?希望大佬们积极解答,也欢迎使用和 star 。

记得之前有个切换年付巨便宜的 bug ,现在又出现了这个升级高级版订阅随机延长免费试用时长 bug 。。。

https://www.microsoft.com/en-us/microsoft-365/college-student-pricing

前提条件:edu 邮箱验证。步骤:

  1. 订阅个人版 https://checkout.microsoft365.com/acquire/purchase?language=en-US&market=US&requestedDuration=Month&scenario=microsoft-365-student&client=poc&campaign=StudentFree12M
  2. 升级高级版 https://checkout.microsoft365.com/acquire/purchase?language=en-US&market=US&requestedDuration=Month&scenario=microsoft-365-premium&client=poc&campaign=StudentPremiumFree12M

升级高级版虽然只显示 1 个月试用,但订阅成功后的邮件里通知 renewal date 都到 5 年后 2031 了。。。无法绑卡但是套 gpay 付款成功,左下角可修改地区。

记得之前有个切换年付巨便宜的 bug ,现在又出现了这个升级高级版订阅随机延长免费试用时长 bug 。。。

https://www.microsoft.com/en-us/microsoft-365/college-student-pricing

前提条件:edu 邮箱验证。步骤:

  1. 订阅个人版 https://checkout.microsoft365.com/acquire/purchase?language=en-US&market=US&requestedDuration=Month&scenario=microsoft-365-student&client=poc&campaign=StudentFree12M
  2. 升级高级版 https://checkout.microsoft365.com/acquire/purchase?language=en-US&market=US&requestedDuration=Month&scenario=microsoft-365-premium&client=poc&campaign=StudentPremiumFree12M

升级高级版虽然只显示 1 个月试用,但订阅成功后的邮件里通知 renewal date 都到 5 年后 2031 了。。。无法绑卡但是套 gpay 付款成功,左下角可修改地区。

可以单纯作为 YouTube 下载器的备用软件。

PS: 如果在使用基于 yt-dlp 的软件时出现没法正常下载的情况,基本都是节点不行,需要更换可用节点


📌 转载信息
原作者:
_BIGFA
转载时间:
2026/1/19 17:55:53

我大概用了两周的 coding agent 工作流:Superpowers(obra/superpowers)。今天看到它出现在 claude-plugins-official 列表里(我这边 /plugin 能看到 source),顺便分享下它的工作流思路。

来源:

它有一套最近大家在聊的很火的 skills,用来把 agent 拉回 “先想清楚、再动手、再验证” 的节奏,核心链路大概是:

  • brainstorming(/superpowers:brainstorm):任何 “要开始写 / 改功能” 之前先用它,把需求 / 约束 / 成功标准摸清楚,先出设计再实现(分段确认)

  • writing-plans(/superpowers:write-plan):把实现拆成很小、可验证的 steps,避免一口气写一大坨

  • executing-plans(/superpowers:execute-plan):按批次执行计划,每批做一次 review/checkpoint

  • test-driven-development:强调 red/green/refactor(先失败的测试,再最小实现)

  • verification-before-completion + systematic-debugging:先验证再宣称 “修好了”,遇到 bug 用更系统的方法追根因

安装我就不复读了:README 里 Claude Code/Codex/OpenCode 都有对应的入口和指令。我个人感觉最有用的是先从 brainstorming 那套问答 / 设计确认开始。

我也在不断熟悉这套工作流中,感觉它就是我想要的 coding agent 工作流。



📌 转载信息
转载时间:
2026/1/19 17:55:41

看了其他佬友的,正常是 2 年,也有 5 年
4 年是什么原理?已有佬友在评论区展现 us 区 + Gpay,欢迎大家分享经验!
注意注意,先领取普通版 365,再去尝试 Premium 团队版 365!

分享下我的踩坑流程,希望能给大家带来帮助

1. 我先在 tw 区的链接,edu 的认证什么的都很顺利,但是卡在了绑卡上,试了 PayPal 和直接输入卡号都不行
https://checkout.microsoft365.com/acquire/purchase?language=zh-TW&market=TW&requestedDuration=Month&scenario=microsoft-365-student&client=poc&campaign=StudentFree12M

2. 于是换成 us 区,还是用之前的 edu(之前屯的 tw 的 edu)使用以下链接 https://checkout.microsoft365.com/acquire/purchase?language=en-US&market=US&requestedDuration=Month&scenario=microsoft-365-student&client=poc&campaign=StudentFree12M
这次还是卡在绑卡上,发现可以使用 Gpay,绑定,顺利通过!

3. 领取普通版本的 365 之后,尝试领取 Premium 版本的 365,也是 us 区,使用如下链接
https://checkout.microsoft365.com/acquire/purchase?language=en-US&market=US&requestedDuration=Month&scenario=microsoft-365-premium&client=poc&campaign=StudentPremiumFree12M

4. 它会一直显示错误,刷新也错误,本来我听别人说封车了,但是不要放弃!在不断尝试刷新、隐私网页再登陆领取,最后和之前一样的流程,绑定 Gpay 之后领取成功了

5. 最后在这里查看订阅时长:https://account.microsoft.com/services/

30 年 2 月 17 日到期,总共领取 4 年!
不清楚为什么和其他人不同,可能和地区或者邮箱有关吧,但是我个人用的是 us 区 + tw 的 edu,这种混搭感觉也不是很靠谱,佬友们参考看看吧

领到的佬友们记得取消自动续期哦


📌 转载信息
转载时间:
2026/1/19 17:55:24

PostgreSql 基于 Pacemaker+Corosync+pcs 的高可用实践

简介

在 PostgresSql HA 方案中,流复制方案集性能,可靠性,部署成本低等优点,也是目前被普遍采用的方案
在流复制 HA 集群管理工具中,Pacenmaker+Corosysnc 是相对程序可靠的

功能特性

  • 快速故障转移
  • 支持多节点集群
  • 支持同步和异步复制
  • 提供读写 vip 和只读 vip

基础架构 / 原理

  1. Pacemaker + Corosync 作为集群基础软件,Corosync 负责集群通信和成员关系管理,Pacemaker 负责资源管理。
  2. 集群用到资源包括 PostgreSQL 和 VIP 等,PostgreSQL 对应的 Resource Agent (RA) 为 expgsql,expgsql 负责实施 PostgreSQL 的起停,监视,failover 等操作。
  3. 集群初始启动时 expgsql 通过比较所有节点的 xlog 位置,找出 xlog 最新的节点作为 Master,其它节点作为 Slave 通过读写 VIP 连接到 Master 上进行 WAL 复制。
  4. 集群启动后 expgsql 不断监视 PostgreSQL 的健康状况,当 expgsql 发现 PostgreSQL 资源故障时报告给 Pacemaker,由 Pacemaker 实施相应动作。
    如果是 PostgreSQL 进程故障,原地重启 PostgreSQL,并且该节点上的 fail-count 加 1。
    fail-count 累加到 3 时不再分配 PostgreSQL 资源到这个节点。如果该节点为 Master,会提升一个 Slave 为 Master,即发起 failover。
  5. Corosync 发现节点故障 (主机或网络故障) 时,Pacemaker 也根据情况实施相应动作。
    对多节点集群,未包含过半节点成员的分区将主动释放本分区内的所有资源,包括 PostgreSQL 和 VIP。
    合法的分区中如果没有 Master,Pacemaker 会提升一个 Slave 为 Master,即发起 failover。
  6. Master 上的 expgsql 会不断监视 Slave 的复制健康状况,同步复制下会选定一个 Slave 作为同步 Slave。
  7. 当同步 Slave 出现故障时,Master 上的 expgsql 会临时将同步复制切换到异步复制,防止 Master 上的写操作被 hang 住。如果故障 Slave 恢复或存在另一个健康的 Slave,再切换到同步复制。
  8. 为防止集群分区后,Slave 升级为新 Master 而旧 Master 切换到异步复制导致脑裂和数据双写,引入分布式锁服务进行仲裁。Slave 升级为新 Master 和旧 Master 切换到异步复制前必须先取得锁,避免这两件事同时发生。失去锁的 Master 会主动停止 PostgreSQL 进程,防止出现双主。
  9. 如果分布锁服务发生故障而所有 PostgreSQL 节点都是健康的,expgsql 会忽视锁服务,即不影响集群服务。但在分布锁服务故障期间,Master 发生节点故障 (注意区分节点故障和资源故障),集群将无法正常 failover。
  10. 同步复制下只有同步 Slave 才有资格成为候选 Master,加上有分布式锁的防护,可以确保 failover 后数据不丢失。
  11. 集群初始启动和每次 failover 时通过 pg_ctl promote 提升 Slave 为 Master 并使时间线加 1,同时记录 Master 节点名,时间线和切换时的 xlog 位置到集群 CIB。
  12. 集群重启时根据集群 CIB 中记录的信息确定 Master 节点,并保持时间线不变。
  13. expgsql 启动 PostgreSQL 前会检查该节点的时间线和 xlog,如果和集群 CIB 中记录的信息有冲突,将报错。需要人工通过 cls_repair_by_pg_rewind 等手段修复。
  14. 读写 VIP 和 Master 节点绑定,只读 VIP 和其中一个 Slave 绑定,应用只需访问 VIP,无需关心具体访问哪个节点。

集群常规命令

pcs status //查看集群状态
pcs resource show //查看资源
pcs resource create ClusterIP IPaddr2 ip=192.168.0.120 cidr_netmask=32 //创建一个虚拟IP资源
pcs resource cleanup //xx表示虚拟资源名称,当集群有资源处于unmanaged的状态时,可以用这个命令清理掉失败的信息,然后重置资源状态
pcs resource list //查看资源列表
pcs resource restart //重启资源
pcs resource enable //启动资源
pcs resource disable //关闭资源
pcs resource delete //删除资源
crm_mon -Arf -1 //查看同步状态和资源 

pg_ctl 常用命令

Usage:
  pg_ctl init[db] [-D DATADIR] [-s] [-o OPTIONS]
  pg_ctl start      [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s] [-o OPTIONS] [-p PATH] [-c]
  pg_ctl stop       [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]
  pg_ctl restart    [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s] [-o OPTIONS] [-c]
  pg_ctl reload     [-D DATADIR] [-s]
  pg_ctl status     [-D DATADIR]
  pg_ctl promote    [-D DATADIR] [-W] [-t SECS] [-s]
  pg_ctl logrotate  [-D DATADIR] [-s]
  pg_ctl kill       SIGNALNAME PID

集群实践

环境介绍

操作系统版本

CentOS Linux release 7.9.2009 (Core)

软件版本

pgsql:(14)
PCS 相关版本:

[root@k8s-master01 pgsql_cluster]#  rpm -qa|grep pacemaker
pacemaker-cli-1.1.23-1.el7_9.1.x86_64
pacemaker-cluster-libs-1.1.23-1.el7_9.1.x86_64
pacemaker-1.1.23-1.el7_9.1.x86_64
pacemaker-libs-1.1.23-1.el7_9.1.x86_64

[root@k8s-master01 pgsql_cluster]#  rpm -qa|grep pcs
pcs-0.9.169-3.el7.centos.3.x86_64

[root@k8s-master01 pgsql_cluster]# rpm -qa|grep corosync
corosync-2.4.5-7.el7_9.2.x86_64
corosynclib-2.4.5-7.el7_9.2.x86_64
地址信息
192.168.28.151   pg-151
192.168.28.152   pg-152
192.168.28.153   pg-153
192.168.28.41    vip-master
192.168.28.141   vip-slave

基础环境准备

配置 hostname [all service]
cat /etc/hosts
192.168.28.151   pg-151
192.168.28.152   pg-152
192.168.28.153   pg-153
关闭防火墙.selinux [all service]
#systemctl disable firewalld #systemctl stop firewalld #systemctl status firewalld #sestatus

SELinux status:                 disabled
服务器时间同步
ntpdate ntp1.aliyun.com

集群软件安装

安装 pcs
yum -y install libsmb*

yum install -y pacemaker pcs corosync

yum install  -y autoconf automake libtool

yum install   -y docbook-style-xsl

yum install   -y gcc-c++ glib2-devel

需要注意的是,安装时可能会报 Missing Dependency :kernel-header
安装 安装 kernel-headers 即可解决问题,如下

wget http://mirror.centos.org/centos/7/updates/x86_64/Packages/kernel-headers-3.10.0-1160.102.1.el7.x86_64.rpm
rpm -ivh kernel-headers-3.10.0-1160.102.1.el7.x86_64.rpm
pacemaker resource-agents 更新 [all servers]
wget  https://github.com/ClusterLabs/resource-agents/releases/tag/v4.12.0
unzip resource-agents-4.12.0.zip
./autogen.sh
/configure
make && make install

确认支持 PG12 以上版本
/usr/lib/ocf/resource.d/heartbeat/pgsql 文件,1918 行,包含 ocf_version_cmp “$version” “12”

 if is_replication || [ "$OCF_RESKEY_rep_mode" = "slave" ]; then if [ `printf "$version\n9.1" | sort -n | head -1` != "9.1" ]; then
            ocf_exit_reason "Replication mode needs PostgreSQL 9.1 or higher." return $OCF_ERR_INSTALLED fi
        ocf_version_cmp "$version" "12"
        rc=$?
        if [ $rc -eq 1 ]||[ $rc -eq 2 ]; then # change the standby method for PosrgreSQL 12 or later. 
启动服务 [all service]
systemctl start pcsd
systemctl enable pcsd
systemctl enable corosync
systemctl enable pacemaker

集群设置

1. 设置 hacluster 用户密码 [all service]
echo hacluster|passwd hacluster --stdin
2. 集群认证 (任意节点)
pcs cluster auth -u hacluster -p hacluster pg-151 pg-152 pg-153 
3. 同步配置 (任意节点)
pcs cluster setup --last_man_standing=1 --name pgcluster pg-151 pg-152 pg-153 --force 

注意 --force 会强行覆盖原有集群配置

4. 启动集群 (任意节点)
#启动集群
pcs cluster start --all
#查看集群状态
pcs status --full 

安装 PostgresSQl14 [all service]

yum 安装
sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
sudo yum install -y postgresql14-server
sudo /usr/pgsql-14/bin/postgresql-14-setup initdb
sudo systemctl enable postgresql-14
sudo systemctl start postgresql-14
数据库目录创建 [all servers]

mkdir -p /data/postgresql/pgdata/pg-5432
mkdir -p /data/postgresql/pg_archive/pg-5432
chown postgres:postgres /data/postgresql
chmod 700 /data/postgresql

数据库用户环境变量配置 [all servers]
su - postgres
-bash-4.2$ cat .bash_profile
[ -f /etc/profile ] && source /etc/profile
PGDATA=/data/postgresql/pgdata/pg-5432
export PGDATA
export PATH=/usr/pgsql-14/bin:$PATH # If you want to customize your settings, # Use the file below. This is not overridden # by the RPMS.
[ -f /var/lib/pgsql/.pgsql_profile ] && source /var/lib/pgsql/.pgsql_profile
主节点数据库 (pg-151) 配置
  1. 初始化数据库
initdb -D /data/postgresql/pgdata/pg-5432/ 
  1. 修改配置文件和 hba
    postgresql.conf

pg_hba.conf (用于设置主机访问)

local all all                                     trust
host   all all 192.168.28.0/24          md5
# IPv4 local connections:
host    all all 127.0.0.1/32            trust
# IPv6 local connections:
host    all all             ::1/128                 trust
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     trust
host    replication     repluser        192.168.28.0/24         md5
host    replication     all 127.0.0.1/32            trust
host    replication     all             ::1/128                 trust
创建复制用户 (master 节点)

先运行 matser 数据库
pg_ctl start
再创建复制用户

psql (14.10)
Type "help" for help.
postgres=# create user repluser with replication password 'repluser'; 
创建 slave 节点 (pg-152 pg-152)
pg_basebackup -h pg-151 -U repluser -p 5432  -D /data/postgresql/pgdata/pg-5432/ -X stream -P 
停止 master 节点 (pg-151)

pg_ctl stop

配置 pgsql 集群

1. 设置 cluster_setup.sh 脚本
pcs cluster cib pgsql_cfg
pcs -f pgsql_cfg property set no-quorum-policy="ignore"
pcs -f pgsql_cfg property set stonith-enabled="false"
pcs -f pgsql_cfg resource defaults resource-stickiness="INFINITY"
pcs -f pgsql_cfg resource defaults migration-threshold="1"
pcs -f pgsql_cfg resource create vip-master IPaddr2 \
   ip="192.168.28.41" \
   nic="eth0" \
   cidr_netmask="24" \
   op start   timeout="60s" interval="0s"  on-fail="restart" \
   op monitor timeout="60s" interval="10s" on-fail="restart" \
   op stop    timeout="60s" interval="0s"  on-fail="block"
pcs -f pgsql_cfg resource create vip-slave IPaddr2 \
   ip="192.168.28.141" \
   nic="eth0" \
   cidr_netmask="24" \
   meta migration-threshold="0" \
   op start   timeout="60s" interval="0s"  on-fail="stop" \
   op monitor timeout="60s" interval="10s" on-fail="restart" \
   op stop    timeout="60s" interval="0s"  on-fail="ignore"
pcs -f pgsql_cfg resource create pgsql pgsql \
   pgctl="/usr/pgsql-14/bin//pg_ctl" \
   psql="/usr/pgsql-14/bin//psql" \
   pgdata="/data/postgresql/pgdata/pg-5432" \
   config="/data/postgresql/pgdata/pg-5432/postgresql.conf" \
   rep_mode="async" \
   node_list="pg-151 pg-152 pg-153" \
   master_ip="192.168.28.41" \
   repuser="repluser" \
   primary_conninfo_opt="password=repluser keepalives_idle=60 keepalives_interval=5 keepalives_count=5" \
   restart_on_promote='true' \
   op start   timeout="60s" interval="0s"  on-fail="restart" \
   op monitor timeout="60s" interval="4s"  on-fail="restart" \
   op monitor timeout="60s" interval="3s"  on-fail="restart" role="Master" \
   op promote timeout="60s" interval="0s"  on-fail="restart" \
   op demote  timeout="60s" interval="0s"  on-fail="stop" \
   op stop    timeout="60s" interval="0s"  on-fail="block" \
   op notify  timeout="60s" interval="0s"
pcs -f pgsql_cfg resource master msPostgresql pgsql \
   master-max=1 master-node-max=1 clone-max=5 clone-node-max=1 notify=true
pcs -f pgsql_cfg resource group add master-group vip-master
pcs -f pgsql_cfg resource group add slave-group vip-slave
pcs -f pgsql_cfg constraint colocation add master-group with master msPostgresql INFINITY
pcs -f pgsql_cfg constraint order promote msPostgresql then start master-group symmetrical=false score=INFINITY
pcs -f pgsql_cfg constraint order demote  msPostgresql then stop  master-group symmetrical=false score=0
pcs -f pgsql_cfg constraint colocation add slave-group with slave msPostgresql INFINITY
pcs -f pgsql_cfg constraint order promote msPostgresql then start slave-group symmetrical=false score=INFINITY
pcs -f pgsql_cfg constraint order demote  msPostgresql then stop  slave-group symmetrical=false score=0
pcs cluster cib-push pgsql_cfg

运行脚本

chmox +x cluster_setup.sh
sh cluster_setup.sh 
2. 如何修改集群配置
cibadmin --query > tmp.xml
//将当前集群配置信息保存到tmp.xml文件中 cibadmin --query > tmp.xml
vi tmp.xml
//使用编辑器对XML文件进行修改  vim tmp.xml
cibadmin --replace --xml-file tmp.xml
//将修改后的XML文件替换掉当前集群的配置信息 cibadmin --replace --xml-file tmp.xml 

cibadmin 是用于操作 Heartbeat CIB 的低级管理命令。它可以用来转储、更新或修改所有或部分 CIB,删除整个 CIB 或执行各种 CIB 管理操作。

集群配置信息是 Pacemaker 集群中 CIB 信息的关键组成部分,Pacemaker 的集群配置信息决定了集群最终应该如何工作以及集群最终的运行状态,因为只有一个正确的集群配置才能驱动集群资源运行在正常的状态。通常情况下,集群的配置信息由集群配置选项 (crm_config)、集群节点 (nodes)、集群资源 (resources) 和资源约束 (constraints) 四个配置段组成,通过 cibadmin --query 可查。

3. 集群状态检查

1. 启动集群并设置开机自启动
数据库无需配置自启动,由集群软件自动拉起

pcs cluster start --all
pcs cluster enable --all 

2. 查看集群状态

[root@k8s-master01 pgsql_cluster]# pcs status Cluster name: pgcluster Stack: corosync Current DC: pg-153 (version 1.1.23-1.el7_9.1-9acf116022) - partition with quorum Last updated: Tue Nov 21 16:47:19 2023 Last change: Tue Nov 21 16:38:42 2023by root via crm_attribute on pg-151 3 nodes configured 7 resource instances configured Online: [ pg-151 pg-152 pg-153 ]

Full list of resources: Master/Slave Set: msPostgresql [pgsql]
     Masters: [ pg-151 ]
     Slaves: [ pg-152 pg-153 ]
 Resource Group: master-group vip-master (ocf::heartbeat:IPaddr2): Started pg-151 Resource Group: slave-group vip-slave  (ocf::heartbeat:IPaddr2): Started pg-152 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled 

3、查看本机集群状态及资源状态
crm_mon -Afr -1

[root@k8s-master01 pgsql_cluster]# crm_mon -Afr -1
Stack: corosync
Current DC: pg-153 (version 1.1.23-1.el7_9.1-9acf116022) - partition with quorum
Last updated: Tue Nov 21 16:47:54 2023
Last change: Tue Nov 21 16:38:42 2023 by root via crm_attribute on pg-151

3 nodes configured
7 resource instances configured

Online: [ pg-151 pg-152 pg-153 ]

Full list of resources:

 Master/Slave Set: msPostgresql [pgsql]
     Masters: [ pg-151 ]
     Slaves: [ pg-152 pg-153 ]
 Resource Group: master-group
     vip-master (ocf::heartbeat:IPaddr2):       Started pg-151
 Resource Group: slave-group
     vip-slave  (ocf::heartbeat:IPaddr2):       Started pg-152

Node Attributes:
* Node pg-151:
    + master-pgsql                      : 1000      
    + pgsql-data-status                 : LATEST    
    + pgsql-master-baseline             : 00000000220000A0
    + pgsql-status                      : PRI       
* Node pg-152:
    + master-pgsql                      : -INFINITY 
    + pgsql-data-status                 : STREAMING|ASYNC
    + pgsql-status                      : HS:async  
* Node pg-153:
    + master-pgsql                      : -INFINITY 
    + pgsql-data-status                 : STREAMING|ASYNC
    + pgsql-status                      : HS:async  

Migration Summary:
* Node pg-153:
* Node pg-152:
* Node pg-151:

4. 查看主节点流复制状态 (master)

su - postgres
-bash-4.2$ psql
psql (14.10)
Type "help" for help.

postgres=# select client_addr,sync_state from pg_stat_replication;
  client_addr   | sync_state 
----------------+------------
 192.168.28.153 | async 192.168.28.152 | async
(2 rows)

5. 验证 vip [all service]

ipconfig
验证数据同步

在主节点上创建一个新表

postgres=# create table ysl(id int);
CREATE TABLE
postgres=# insert into ysl values(1);
INSERT 0 1
postgres=# select * from ysl;
 id 
----
  1
(1 row)

在 slave 节点上查看

-bash-4.2$ psqlpsql (14.10)
Type "help" for help.

postgres=# select * from ysl; id 
----
  1
(1 row)

故障模拟

停掉主库 pg-151,备库 pg-152 提升为主节点

-bash-4.2$ pg_ctl stop
waiting for server to shut down.... done

[root@k8s-master01 pgsql_cluster]# pcs status
Cluster name: pgcluster
Stack: corosync
Current DC: pg-153 (version 1.1.23-1.el7_9.1-9acf116022) - partition with quorum
Last updated: Tue Nov 21 16:59:30 2023
Last change: Tue Nov 21 16:59:29 2023 by root via crm_attribute on pg-152

3 nodes configured
7 resource instances configured

Online: [ pg-151 pg-152 pg-153 ]

Full list of resources:

 Master/Slave Set: msPostgresql [pgsql]
     Masters: [ pg-152 ]
     Slaves: [ pg-153 ]
     Stopped: [ pg-151 ]
 Resource Group: master-group
     vip-master (ocf::heartbeat:IPaddr2):       Started pg-152
 Resource Group: slave-group
     vip-slave  (ocf::heartbeat:IPaddr2):       Started pg-153

Failed Resource Actions:
* pgsql_monitor_3000 on pg-151 'not running' (7): call=92, status=complete, exitreason='',
    last-rc-change='Tue Nov 21 16:58:59 2023', queued=0ms, exec=0ms

Daemon Status:
  corosync: active/enabled
  pacemaker: active/enabled
  pcsd: active/enabled

注意 master 节点挂掉之后,使用 crm_mon -Arf -1 命令看到末尾有 "You have to remove /var/lib/pgsql/tmp/PGSQL.lock file to force start." 字样,master 宕机启动时,需要删除临时锁文件方可进行集群角色转换。即执行 rm -rf /var/lib/pgsql/tmp/PGSQL.lock
拉起数据库不需要执行 pg_ctl start, 只需要 pcs resource cleanup

[root@k8s-master01 pgsql_cluster]# pcs resource cleanup
Cleaned up all resources on all nodes
Waiting for 1 reply from the CRMd. OK
[root@k8s-master01 pgsql_cluster]# pcs status
Cluster name: pgcluster
Stack: corosync
Current DC: pg-153 (version 1.1.23-1.el7_9.1-9acf116022) - partition with quorum
Last updated: Tue Nov 21 17:01:57 2023
Last change: Tue Nov 21 17:01:26 2023 by hacluster via crmd on pg-151

3 nodes configured
7 resource instances configured

Online: [ pg-151 pg-152 pg-153 ]

Full list of resources:

 Master/Slave Set: msPostgresql [pgsql]
     Masters: [ pg-152 ]
     Slaves: [ pg-153 ]
     Stopped: [ pg-151 ]
 Resource Group: master-group
     vip-master (ocf::heartbeat:IPaddr2):       Started pg-152
 Resource Group: slave-group
     vip-slave  (ocf::heartbeat:IPaddr2):       Started pg-153

Failed Resource Actions:
* pgsql_start_0 on pg-151 'unknown error' (1): call=127, status=complete, exitreason='My data may be inconsistent. You have to remove /var/lib/pgsql/tmp/PGSQL.lock file to force start.',
    last-rc-change='Tue Nov 21 17:01:28 2023', queued=1ms, exec=615ms

Daemon Status:
  corosync: active/enabled
  pacemaker: active/enabled
  pcsd: active/enabled

此时可以看到 pg-153,pg-151 成为 pg-152 的备机

postgres=# select * from pg_stat_replication;
  pid  | usesysid | usename  | application_name |  client_addr   | client_hostname | client_port |     
    backend_start         | backend_xmin |   state   |  sent_lsn  | write_lsn  | flush_lsn  | replay_ls
n | write_lag | flush_lag | replay_lag | sync_priority | sync_state |          reply_time           
-------+----------+----------+------------------+----------------+-----------------+-------------+-----
--------------------------+--------------+-----------+------------+------------+------------+----------
--+-----------+-----------+------------+---------------+------------+-------------------------------
 13234 |    16384 | repluser | pg-153           | 192.168.28.153 |                 |       60624 | 2023
-11-21 08:59:27.197402+00 |        12918 | streaming | 0/2D004748 | 0/2D004748 | 0/2D004748 | 0/2D00474
8 |           |           |            |             0 | async      | 2023-11-21 09:04:16.90261+00
 31795 |    16384 | repluser | pg-151           | 192.168.28.151 |                 |       44678 | 2023
-11-21 09:04:05.741284+00 |        12918 | streaming | 0/2D004748 | 0/2D004748 | 0/2D004748 | 0/2D00474
8 |           |           |            |             0 | async      | 2023-11-21 09:04:15.822551+00
(2 rows)

参考:

PgSQL Replicated Cluster:


📌 转载信息
原作者:
xxdtb
转载时间:
2026/1/19 17:53:11

如果加入家庭组后还是《free》。
如果账号突然《账号无权限,已跳过自动刷新》。

都去验证一下年龄,验证通过。等个几分钟就好了!

https://antigravity.google/docs/faq#why-am-i-ineligible-for-google-one-ai-quotas-even-though-i-am-a-subscribed-to-a-plan

verify your age

希望能帮到大家

上面是我的经验之谈,我的号是这么恢复的,可能我接触得少。看完大家的回复,得出结论,方法不一定有效,大家可以试试,不行也没办法了。


📌 转载信息
原作者:
xsc
转载时间:
2026/1/19 17:52:54

Skill 与 MCP 深度对比

首先,官方文档非常值得细细品味,看完官方文档倒也可以考虑不用看其他的文章了(针对 skill,mcp 这一块感觉描述一般,mcp 太多东西了):

# Agent Skills

# Agent Skills 概览

# 通过 MCP 将 Claude Code 连接到工具


一、Token 占用对比,这个大家应该都知道,不过多描述

1.1 MCP:全量加载模式

MCP 在会话启动时全量加载所有工具定义到上下文:

会话启动 → 加载所有 MCP 服务器 → 注入全部工具定义(JSON-Schema

就拿我使用的 mcp 来说

MCP 服务器工具数Token 占用
auggie-mcp1~1k
grok-search5~3k
memory9~5k
sequential-thinking1~2k
多服务器叠加-轻松突破 10k+

随便用几个占用就非常大了

1.2 Skill:按需加载模式

Skill 采用渐进式披露,仅在需要时加载:

阶段加载内容Token 占用
启动时name + description 索引~10-100 tokens/skill
触发时完整 SKILL.md 内容~1,000-5,000 tokens/skill

我使用的 skill:90K 的 Skills 目录,/context 仅显示 513 tokens,和 mcp 对比起来,非常直观。

1.3 简单对比

维度MCPSkill
启动时占用全量(10k+ tokens)索引(~500 tokens)
使用时增量无(已加载)按需逐步加载


二、设计模式对比

2.1 MCP:全量注入 + JSON-Schema

什么是 MCP?

MCP(Model Context Protocol)即模型上下文协议,采用 Host-Client-Server 三层架构:

Host (Claude Code)
    │
    ├── Client ←──JSON-RPC──→ context7 Server              
    ├── Client ←──JSON-RPC──→ sequential-thinking Server   
    └── Client ←──JSON-RPC──→ your Server 
角色是什么
HostAI 应用程序(比如 Claude Code、VS Code、Cursor 等)
Client通信管道,负责与 Server 建立连接、发送 JSON-RPC 请求、接收响应
Server提供工具 / 上下文的程序(== 日常说的「安装 MCP」就是安装 Server==)
JSON-RPCClient 与 Server 之间传输的数据格式(所有 MCP 都遵守此协议)
Tool Schema启动时 Server 返回的「工具说明书」,告诉 Claude 有哪些工具、怎么调用

Host 和 Client 由应用自动管理,开发者 / 使用者只需关注 Server。再比如 FastMCP 框架会自动处理协议细节。

MCP Server 目录结构(这里以 Python 为例)

my-mcp-server/
├── pyproject.toml            # 包定义(必需)
│   ├── name = "mcp-server-xxx"
│   └── version = "1.0.0"
├── src/
│   ├── server.py             # 入口,初始化 FastMCP
│   ├── tools.py              # Tool 定义(单文件,适合 <10 个工具)
│   ├── tools/                # Tool 定义(多文件,按功能拆分)
│   │   ├── __init__.py
│   │   ├── search.py
│   │   └── fetch.py
│   └── resources.py          # Resource 提供者(可选)
└── README.md

tools.pytools/ 二选一,可根据数量决定。

Tool 定义示例

从这里就可以看出,其实和接口非常像,请求 -> 回调数据,实际上多数的 mcp 也都可以理解成三方接口。

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("weather")

@mcp.tool() async def get_weather(location: str) -> str:
    """Get weather for a location.""" return f"Weather in {location}: 72°F, Sunny" if __name__ == "__main__":
    mcp.run(transport="stdio")

客户端配置结构(mcpServers)

配置示例

{ "args": [ "-y", "@upstash/context7-mcp" ], "command": "npx", "type": "stdio" } 

mcp 服务器的 json 格式,让配置起来非常方便,cv 万岁

2.2 Skill:渐进式披露 + Markdown

什么是 Skill?

Skill 是 Claude Code 的知识 / 流程包,本质是一个 Markdown 文件夹,用于:

  • 注入领域知识(如代码规范、业务逻辑)
  • 定义工作流程(如代码审查 SOP、部署流程)
  • 封装可复用的脚本和模板 ==(这直接导致 Skill 与 MCP 在使用体验上趋于相似)==

额外说明:

Skill 只能提供指导,无法执行外部 API 调用、网络请求、会话管理等操作,毕竟只是 md 文件夹,但是能指导 cc 运行脚本,包括但不限于自带的脚本资源,这句话应该会有嚼头。

Skill 目录结构(双层架构)

以下规范取自 skill-creator Skill, 我觉得配置比 cc 官方文档里面的描述更详细

skill-name/ ├── SKILL.md (必需)  ├── YAML frontmatter ──→ 索引层(始终加载,~100 words)   ├── name: (必需)   └── description: (必需,唯一触发机制)  └── Markdown 正文 ────→ 内容层(触发时加载,建议 <500 行) └── Bundled Resources (可选) ──→ 内容层(按需加载) ├── scripts/ - 可执行脚本(Python/Bash) ├── references/ - 参考文档(Claude 判断需要时加载) └── assets/ - 输出资源(模板、图片,不加载到上下文) 

双层架构说明

  • 索引层:YAML frontmatter 中的 name/description,始终在上下文中
  • 内容层:SKILL.md 正文 + 捆绑资源,仅在触发时选择性加载

核心设计原则

description 是唯一触发机制

# ✅ 好的 description(包含触发场景) description: >
Comprehensive document creation and editing with tracked changes.
Use when Claude needs to work with .docx files for:
(1) Creating new documents, (2) Modifying content,
(3) Working with tracked changes, (4) Adding comments
# ❌ 差的 description(太模糊) description: A useful document tool

渐进式披露模式

是不是觉得模式 1,3 非常相似?我也觉得。不过 skill-creator 还是分成了这三种,就全罗列出来了

模式 1:高层指南 + 引用

# PDF Processing ## Quick start
[核心代码示例]

## Advanced features - **Form filling**: See [FORMS.md](references/FORMS.md)
- **API reference**: See [REFERENCE.md](references/REFERENCE.md)

Claude 仅在需要时加载 FORMS.md 或 REFERENCE.md。

模式 2:按领域 / 变体组织

cloud-deploy/
├── SKILL.md (工作流 + 选择指南)
└── references/
├── aws.md    ← 用户选 AWS 时才加载
├── gcp.md
└── azure.md

模式 3:条件详情

## Editing documents
For simple edits, modify XML directly.

**For tracked changes**: See [REDLINING.md](references/REDLINING.md)
**For OOXML details**: See [OOXML.md](references/OOXML.md)

工作流程

用户请求 → Claude 扫描所有 Skill 的 description → 匹配 → 加载 SKILL.md 正文 → 按需加载 references → 执行

特点

  • 宽松定义:Markdown 格式,自然语言描述
  • 懒加载:渐进式加载
  • 可编排:Markdown 可表达流程顺序和条件分支
  • 本质:流程 / 知识包(SOP 手册)


三、版本管理与更新便利性

结论先行:MCP 在版本管理上绝对优于 Skill。

3.1 MCP:成熟的包管理生态

核心机制

MCP 直接复用 npm/PyPI 成熟生态,版本管理由包管理器自动处理。

工作原理

  • MCP 服务器以 npm 包(js/ts)或 PyPI 包(Python)形式发布
  • 使用 npxuvx 命令启动时,包管理器会自动处理下载和缓存
  • 版本号定义在 package.json(npm)或 pyproject.toml(PyPI)中

更新行为

模式行为启动速度适用场景
默认使用本地缓存,不查询 registry日常使用
强制更新每次查询 registry,版本变化时才下载(@latest--refresh需要最新版本时

获取方式对比

获取方式配置示例更新机制
npx (npm)npx -y @pkg/server默认用缓存,需 @latest 或清缓存强制更新
uvx (pip)uvx mcp-server-fetch默认用缓存,需 --refresh 或清缓存强制更新
本地命令auggie --mcp需手动 pip install --upgrade

配置示例

// ~/.claude.json { "mcpServers": { "memory": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-memory"] } } } 

如何更新

推荐方式:手动清理缓存

当 MCP 服务器有新版本时,清理缓存即可:

# 清理 npx 缓存 rm -rf ~/.npm/_npx #(不推荐!不推荐!不推荐!) # 清理 uvx 缓存
uv cache clean #(不推荐!不推荐!不推荐!) # 上述的清理会清理系统中所有的缓存,但mcp的缓存位置各有不同,需要主动寻找,且无规律可言,最好还是让cc自己来吧 

工作流程

  1. 清理缓存
  2. 重启 Claude Code
  3. 自动下载最新版本

优点:日常启动快,需要更新时才清理缓存

不推荐使用 @latest 或 --refresh

虽然可以自动更新,但会显著影响启动速度(每次都查询 registry)。

配置示例:

{ "mcpServers": { "memory": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-memory@latest"] // npx 使用 @latest }, "fetch": { "command": "uvx", "args": ["--refresh", "mcp-server-fetch"] // uvx 使用 --refresh } } } 


3.2 Skill:普遍缺乏版本管理

现状:一般来说 Skill 没有版本管理

与 MCP 不同,一般来说 Skill 没有任何版本管理机制

  • 没有版本号定义
  • 没有版本锁定
  • 手动管理

Skill 在某些时候更像可以随意定制的小玩具,在原本的基础上又能随意修改

Skill 的获取与更新方式

获取方式更新方式版本控制
GitHub 克隆git pull 手动更新依赖 Git commit hash
下载 ZIP 文件手动替换文件
CC 直接生成即时生效

问题

  • 用户不知道 Skill 是否有新版本
  • 无法回滚到特定版本(除非使用 Git)


例外:官方 Marketplace(需登录)

唯一的版本管理方案是官方 Marketplace,但有严格限制:

  • 必须登录:API Key 用户无法使用
  • 非标准化:没有强制的版本号格式

Marketplace 版本管理示例

// marketplace.json { "name": "my-plugins", "plugins": [ { "name": "review-plugin", "source": "./plugins/review-plugin", "version": "2.1.0" // ← 需要手动维护 } ] } 

限制

  • 仅适用于官方 Marketplace 中的 Skill
  • 无法用于自定义或第三方 Skill
  • API Key 用户完全无法使用

ps:这一块应该是这样的吧,没有官号诶


Skill 的独特优势

尽管缺乏版本管理,Skill 还有一个 MCP 无法比拟的优势:

即时生效:修改 Skill 文件后无需重启服务,下次触发时自动加载最新内容。

对比 MCP

  • MCP:修改后需重启 Claude Code 才能生效
  • Skill:适合快速迭代和调试,改完即用

适用场景

  • 个人定制化 Skill(频繁调整)
  • 快速原型验证


四、我推荐:使用 Slash Command 稳定触发

事先声明: 这里的 /ccg 不是使用的 skill,我才发现,哎呀!!

但是我都按照这个写了,不想再改了。

/ccg 的工作流程是 /cmd → 自己的脚本
请你们假装 是 /cmd → skill → skill 的脚本

4.1 Skill 的触发不确定性问题

Skill 依赖 Claude 自动匹配描述,存在以下问题:

  • 该触发时未触发(描述不够精准)
  • 不该触发时误触发(描述过于宽泛)

实际体验:虽然 Skill 理论上能够自动触发,但实际触发率较低。比如我即使在 CLAUDE.md 中明确写了 "让 Codex 和 Gemini 参与协作",Claude 偶尔还是会忽略。所以之前我都会主动在需求后面添加这句话。

解决方案:使用 cmd 可以 100% 稳定触发。例如:/ccg:feat 需求描述 总比主动描述或者期待 cc 记得安心。

4.2 最佳实践:Skill + Command 工作流组合

为什么需要 Command

Skill 可能包含复杂的命令调用和参数配置,这些细节难以通过自然语言稳定触发。例如:

  • 外部工具调用:/home/nobug/.claude/bin/codeagent-wrapper --backend gemini
  • 带参数的指令:--backend codex--SESSION_ID xxx
  • 多阶段工作流:需要按特定顺序执行多个步骤

这些精确的指令和参数通过语言描述很难稳定触发,而 Command 可以将这些细节明确定义在文件中。

模式 1 示例(简单流程):

场景:应用主题到 Artifact

├── ~/.claude/skills/theme-factory/
│   └── SKILL.md                    # 主题定义、应用指南
└── ~/.claude/commands/
    └── theme-factory.md            # 内容:"Execute the theme-factory skill"

用户输入 /theme-factory 应用深色主题
    ↓
Command 触发 → Claude 加载 SKILL.md → 自主执行

模式 2 示例(复杂流程):

场景:前端专项开发

└── ~/.claude/commands/ccg/
    └── frontend.md                 # 完整工作流定义

用户输入 /ccg:frontend 实现响应式导航栏
    ↓
Claude 加载 frontend.md 内容
    ↓
按照 Command 中定义的 6 个阶段执行:
  1. Prompt 增强(可选)
  2. 研究(代码检索)
  3. 构思(调用 Gemini 分析)
  4. 计划(调用 Gemini 规划)
  5. 执行(Claude 实施)
  6. 优化(调用 Gemini 审查)

外部工具说明:像 codeagent-wrapper 这样的工具是外部可执行文件(位于 ~/.claude/bin/),不是 Skill。Skill 只能提供指导,无法执行外部 API 调用、网络请求、会话管理等操作,这些必须由外部工具完成。

核心原则

  • 稳定性优先:复杂流程用 Command 定义,确保稳定执行
  • 外部工具必须用 Command:Skill 无法执行外部命令
  • 简单场景用 Skill:减少维护成本,提高灵活性


第一次写文章,本来只是想说 mcp 的包管理很爽 ,其他的都是为了这碟醋包的饺子


📌 转载信息
原作者:
Shuiyell
转载时间:
2026/1/19 17:52:41

又到年终汇报时间,又要搞 word 格式,又要 ppt 形式述职,下面总结一下经验可以给佬们参考。

  1. 先根据每个月的月总按照公司模板生成年总需要填写的内容,这里我用的 Google AI Studio - Gemini 3 pro。没有月总的可以看看自己 Git 提交记录找找今年做了什么。

  2. 使用 Z.ai 生成 PPT。

这里导出的 PPTX 打开后,会发现样式有变化。

可以使用先导出 PDF,之后使用 Python 脚本将 PDF 转为图片,图片再转为 PPTX,这样就解决样式变化的问题了。

  1. 先安装库
pip install pymupdf python-pptx
  1. 创建文件 pdf2pptx.py,内容:
import fitz  # PyMuPDF
from pptx import Presentation
from pptx.util import Inches
import io
import os

def pdf_to_pptx(pdf_path, pptx_path, dpi=300):
    """
    将 PDF 转换为 PPTX(每一页作为一张全屏图片)
    :param pdf_path: 输入 PDF 文件路径
    :param pptx_path: 输出 PPTX 文件路径
    :param dpi: 渲染清晰度,300 已经非常清晰,如果文件太大可以降到 200
    """
    # 1. 打开 PDF
    pdf_doc = fitz.open(pdf_path)
    prs = Presentation()

    # 2. 获取 PDF 第一页的尺寸,并设置为 PPT 的幻灯片尺寸
    # PDF 默认单位是点 (points), 1 inch = 72 points
    first_page = pdf_doc[0]
    width_pts, height_pts = first_page.rect.width, first_page.rect.height
    
    prs.slide_width = Inches(width_pts / 72)
    prs.slide_height = Inches(height_pts / 72)

    print(f"开始转换: {pdf_path}")
    print(f"总页数: {len(pdf_doc)}")

    # 3. 逐页处理
    for page_num in range(len(pdf_doc)):
        page = pdf_doc.load_page(page_num)
        
        # 渲染页面为图片 (设置缩放倍数以提高清晰度)
        zoom = dpi / 72
        mat = fitz.Matrix(zoom, zoom)
        pix = page.get_pixmap(matrix=mat, alpha=False)
        
        # 将图片存入内存流中,避免产生临时文件
        img_stream = io.BytesIO(pix.tobytes("png"))
        
        # 添加一张空白幻灯片 (6 是空白布局)
        slide_layout = prs.slide_layouts[6]
        slide = prs.slides.add_slide(slide_layout)
        
        # 将图片插入幻灯片,铺满全屏
        slide.shapes.add_picture(img_stream, 0, 0, width=prs.slide_width, height=prs.slide_height)
        
        print(f"正在处理第 {page_num + 1} 页...")

    # 4. 保存文件
    prs.save(pptx_path)
    pdf_doc.close()
    print(f"转换完成!已保存至: {pptx_path}")

if __name__ == "__main__":
    # === 使用说明 ===
    # 将下面的文件名替换为你实际的文件名
    input_pdf = "input.pdf" 
    output_pptx = "output.pptx"

    if os.path.exists(input_pdf):
        pdf_to_pptx(input_pdf, output_pptx)
    else:
        print(f"错误:找不到文件 {input_pdf}")
  1. 将 pdf 文件重名为 input.pdf,然后执行:
python pdf2pptx.py
  1. 输出文件 output.pptx。可以再让 AI 帮你输出一份口述草稿配合起来就行了。


有尝试过在线 ILovePDF 网站去转,但是样式还是有问题。

试过 NotebookLM 生成 PPT,效果一般般,没想到 Z.ai 生成的效果还挺好看的


📌 转载信息
转载时间:
2026/1/19 17:52:31

介绍
发布和订阅使用了 pg 的逻辑复制功能,通过发布端创建 publication 与表绑定,订阅端创建 subscription 同时会在发布端创建逻辑复制槽实现逻辑复制功能

逻辑复制基于 发布(Publication) 与 订阅(Subscription)模型

一个 发布者(Publisher) 上可以有多个发布,一个 订阅者(Subscriber) 上可以有多个 订阅 。
一个发布可被多个订阅者订阅,一个订阅只能订阅一个发布者,但可订阅同发布者上的多个不同发布。

典型用法

迁移,跨 PostgreSQL 大版本,跨操作系统平台进行复制。
CDC,收集数据库(或数据库的一个子集)中的增量变更,在订阅者上为增量变更触发触发器执行定制逻辑。
分拆,将多个数据库集成为一个,或者将一个数据库拆分为多个,进行精细的分拆集成与访问控制。

复制标识

一个被纳入发布中的表,必须带有复制标识(Replica Identity),只有这样才可以在订阅者一侧定位到需要更新的行,完成 UPDATE 与 DELETE 操作的复制。
默认情况下,主键 (Primary Key)是表的复制标识,非空列上的唯一索引 (UNIQUE NOT NULL)也可以用作复制标识。
如果没有任何复制标识,可以显式将复制标识设置为 FULL,也就是把整个行当作复制标识
使用 FULL 模式的复制标识效率很低(因为每一行修改都需要在订阅者上执行全表扫描,很容易把订阅者拖垮),所以这种配置只能是保底方案。
使用 FULL 模式的复制标识还有一个限制,订阅端的表上的复制身份所包含的列,要么与发布者一致,要么比发布者更少

创建发布订阅

环境介绍

version: pg16
发布端: 5433
订阅端: 5434
主机 IP: 192.168.28.11

创建发布订阅

在发布者端,wal_level 必须被设置为 logical,而 max_replication_slots 中设置的值必须至少是预期要连接的订阅数加上保留给表同步的连接数。max_wal_senders 应该至少被设置为 max_replication_slots 加上同时连接的物理复制体的数量。
订阅者必须配置 max_replication_slots。它必须设置为至少是订阅者数,加上一些用于表同步的预留。max_logical_replication_workers 必须至少被设置为订阅数加上保留给表同步的连接数。此外,可能需要调整 max_worker_processes 以容纳复制工作者,至少为 (max_logical_replication_workers + 1)。注意,一些扩展和并行查询也会从 max_worker_processes 中取得工作者槽。

发布端
  1. 修改配置文件
vim postgres.conf
wal_level = logical 
max_wal_senders = 100 #max_wal_senders大于max_replication_slots 
vim pg_hba.conf
host    all    repl    订阅者IP/32    md5

重启 pgsql ,配置生效

su postgres
pg_ctl restart -D /data/postgresql/pgdata/pg-5433/ 
  1. 发布者节点创建用户,赋权
su postgres
psql -P 5433
psql (16.9 (Ubuntu 16.9-0ubuntu0.24.10.1))
Type "help" for help.
#创建用户
postgres=# create user repuser password 'repuser' replication;
CREATE ROLE
#在postgres库中创建表,并插入一条数据
postgres=# create table test1(id int primary key,name varchar(10) );
postgres=# insert into test1 values(1,'a'); # 赋予复制用户select表权限
postgres=# grant select on table test1 to repuser; 
  1. 创建表 test1 的发布
create publication pub_test01 for table test1;
订阅端
  1. 修改 posetgres.conf
vim postgres.conf
max_replication_slots=8
max_logical_replication_workers=10
max_worker_processes=8

max_logical_replication_workers 逻辑复制进程数,应大于订阅节点的数量,并且给表同步预留一些进程数量
2. 重启 pgsql

pg_ctl restart -D /data/postgresql/pgdata/pg-5434/ 
  1. 创建订阅
CREATE SUBSCRIPTION subs_test01  CONNECTION 'host=192.168.28.11 dbname=postgres port=5433 user=repuser password=repuser' PUBLICATION pub_test01;
  1. 查看表是否同步
    在发布端执行 test1 表的 insert、delete、update、truncate 操作,看订阅端是否能同步

新加表同步

发布端
  1. 新建表
    create table test3 (id int,name varchar(10));
  2. 设置复制标识
    alter table test3 REPLICA IDENTITY full;
  3. 将表加入发布
    ALTER PUBLICATION pub1 ADD TABLE test3;
订阅端

在订阅端执行刷新
ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION ;
在发布端执行 test3 表的 insert、delete、update、truncate 操作,看订阅端是否能同步

发布订阅查询状态语句

发布端
select * from pg_replication_slots; --查看所有复制槽 select * from pg_stat_replication; --查看复制槽的同步状态 select * from pg_publication; --查看所有发布 select * from pg_publication_tables; --查看所有发布对应的表 select usename,a.pubname,c.*,pubinsert,pubupdate,pubdelete,pubtruncate from pg_publication a,pg_user b,pg_publication_tables c where a.pubowner=b.usesysid and c.pubname=a.pubname;
订阅端
select * from pg_subscription; --查看所有订阅 select srrelid::regclass from pg_subscription_rel; --查看订阅的所有表 select usename,datname,subname,srrelid::regclass,srsublsn,subconninfo from pg_subscription a,pg_user b,pg_subscription_rel c ,pg_database d where a.oid=c.srsubid and a.subowner=b.usesysid and a.subdbid=d.oid;

删除发布订阅

删除订阅

订阅在运行的情况下,需要一下操作:

ALTER SUBSCRIPTION pub_test01;
##首先需要停止当前的订阅 ALTER SUBSCRIPTION subs_test01 (slot_name =NONE);
##然后将订阅的复制槽设置成空
drop subscription subs_test01;
##最后就可以删除订阅了。 ##另外一个问题,复制订阅中,如果订阅的服务停止,或无法再次连接的情况下,需要关注 发布端的数据wal log 无法清理以及膨胀的问题。 ##所以在复制订阅中的订阅停止后,如果确认订阅无法再次恢复,或者不确认多长时间恢复,则需要删除复制槽 select * from pg_replication_slots;

select pg_drop_replication_slot(slot_name) from pg_replication_slots where slot_name = 'pub_test01';

📌 转载信息
原作者:
xxdtb
转载时间:
2026/1/19 17:52:23

概述
使用 postgresql + etcd + patroni + haproxy + keepalived 可以实现 PG 的高可用集群,其中,以 postgresql 做数据库,Patroni 监控本地的 PostgreSQL 状态,并将本地 PostgreSQL 信息 / 状态写入 etcd 来存储集群状态,所以,patroni 与 etcd 结合可以实现数据库集群故障切换(自动或手动切换),而 haproxy 可以实现数据库读写分离 + 读负载均衡(通过不同端口实现),keepalived 实现 VIP 跳转,对 haproxy 提供了高可用,防止 haproxy 宕机。

Patroni 介绍

Patroni 是一个基于 Python 的用于实现 PostgreSQL HA 解决方案的框架。为了最大程度的兼容性,它支持多种分布式配置存储,包括 ZooKeeper、etcd、Consul 或 Kubernetes。旨在帮助数据库工程师、DBA、DevOps 工程师和 SRE 快速部署数据中心(或任何地方)的 HA PostgreSQL 环境。

当前支持的 PostgreSQL 版本从 9.3 到 16。支持自动化故障转移、物理复制和逻辑复制、提供 RESTful API 接口,允许外部应用或运维工具直接操作 PostgreSQL 集群,进行如启停、迁移等操作,与 Linux watchdog 集成,以避免脑裂现象。

项目地址: GitHub - patroni/patroni: A template for PostgreSQL High Availability with Etcd, Consul, ZooKeeper, or Kubernetes

ETCD 介绍

etcd 是一个分布式键值存储数据库,支持跨平台,拥有强大的社区。etcd 的 Raft 算法,提供了可靠的方式存储分布式集群涉及的数据。etcd 广泛应用在微服务架构和 Kubernates 集群中,不仅可以作为服务注册与发现,还可以作为键值对存储的中间件。从业务系统 Web 到 Kubernetes 集群,都可以很方便地从 etcd 中读取、写入数据。
etcd 完整的 cluster(集群)至少有三台,这样才能选举出一个 master 节点,两个 slave 节点。如果小于 3 台则无法进行选举,造成集群不可用。Etcd 使用 2379 和 2380 端口。
2379 端口:提供 HTTP API 服务,和 etcdctl 交互
2380 端口:集群中节点间通讯
项目地址:[[GitHub - etcd-io/etcd: Distributed reliable key-value store for the most critical data of a distributed system]]

环境说明

服务器信息
服务器名ip 地址os数据库读写端口只读端口组件组件端口
k8s-mater01192.168.28.11ubuntu 24.101543325433PostgreSQL,Patroni、Etcd,haproxy、keepalived8008
k8s-mater02192.168.28.12ubuntu 24.101543325433PostgreSQL,Patroni、Etcd,haproxy、keepalived8008
k8s-mater01192.168.28.13ubuntu 24.101543325433PostgreSQL,Patroni、Etcd,haproxy、keepalived8008
vip192.168.28.10PostgreSQL,Patroni、Etcd,haproxy、keepalived8008
软件信息
软件名版本
Patroni4.0.6
Etcd3.5.16
Keepalived2.3.1
Haproxy2.9.10-1ubuntu1.2
PostgreSQL16.9
watchdog5.16
python3.12.7
架构图

这个架构中,PostgreSQL 提供数据服务,Patroni 负责主从切换,etcd 提供一致性存储,HAProxy 提供访问路由,Keepalived 提供网络 VIP 高可用,Watchdog 提供节点存活及脑裂防护机制。 六者协同组成一个企业级高可用数据库集群

预先准备

网络设置
防火墙设置

关闭防火墙 (相对简单,但是不安全)
放行对应的端口(安全)

安装 PostgreSQL

通过 apt 安装 PostgreSQL (所有节点)
sudo apt install curl ca-certificates  
sudo install -d /usr/share/postgresql-common/pgdg  
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc  
. /etc/os-release  
sudo sh -c "echo 'deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $VERSION_CODENAME-pgdg main' > /etc/apt/sources.list.d/pgdg.list" sudo apt update  
sudo apt -y install postgresql
数据库目录设置 (所有节点)
mkdir -p /data/postgresql/pgdata/
mkdir -p /data/postgresql/pg_archive/
chown -R postgres:postgres /data/postgresql/
postgres 用户设置
设置家目录
mkdir -p /home/postgres/
chown -R postgres:postgres /home/postgres/
vim /etc/passwd
#修改postgres 家目录为/home/postgres postgres:x:114:113:PostgreSQL administrator,,,:/home/postgres:/bin/bash 
设置环境变量
vim /home/postgres/.bashrc

[ -f /etc/profile ] && source /etc/profile
export PATH=/usr/lib/postgresql/16/bin:$PATH # If you want to customize your settings, # Use the file below. This is not overridden # by the RPMS.
[ -f /var/lib/pgsql/.pgsql_profile ] && source /var/lib/pgsql/.pgsql_profile
设置 sudo 免密
vim /etc/sudoers
#行末新增
postgres  ALL=(ALL)       NOPASSWD: ALL 

安装 ETCD 集群 (所有节点)

安装 ectd
下载 etcd
wget https://github.com/etcd-io/etcd/releases/download/v3.6.4/etcd-v3.6.4-linux-amd64.tar.gz

tar -xf etcd-v3.6.4-linux-amd64.tar.gz --strip-components=1 -C /usr/local/bin etcd-v3.6.4-linux-amd64/etcd etcd-v3.6.4-linux-amd64/etcdctl


mkdir -p /etc/etcd/
mkdir -p /data/etcd/

编辑 etcd 配置文件
touch /etc/etcd/etcd-pg.config.yml

#节点1配置文件
vim /etc/etcd/etcd-pg.config.yml

#节点名
name: pg-etcd01
#数据目录 
data-dir: /data/etcd
snapshot-count: 5000
#选举和心跳参数
heartbeat-interval: 100
election-timeout: 1000
#存储新能优化
quota-backend-bytes: 8589934592
max-request-bytes: 10485760
max-concurrent-requests: 5000
#自动压缩与碎片整理
auto-compaction-mode: periodic
auto-compaction-retention: "2h"
#集群通信配置
listen-peer-urls: "http://192.168.28.11:12380"
listen-client-urls: "http://192.168.28.11:12379,http://127.0.0.1:12379"
max-snapshots: 3
max-wals: 5
cors:
initial-advertise-peer-urls: "http://192.168.28.11:12380"
advertise-client-urls: "http://192.168.28.11:12379"
discovery:
discovery-fallback: 'proxy'
discovery-proxy:
discovery-srv:
initial-cluster: "pg-etcd01=http://k8s-etcd01:12380,pg-etcd02=http://k8s-etcd02:12380,pg-etcd03=http://k8s-etcd03:12380"
initial-cluster-token: 'etcd-cluster-pg'
initial-cluster-state: 'new'
strict-reconfig-check: false
enable-v2: true
enable-pprof: true
proxy: 'off'
proxy-failure-wait: 5000
proxy-refresh-interval: 30000
proxy-dial-timeout: 1000
proxy-write-timeout: 5000
proxy-read-timeout: 0


#节点2配置文件
name: pg-etcd02
data-dir: /data/etcd

snapshot-count: 5000
#选举和心跳参数
heartbeat-interval: 100
election-timeout: 1000
#存储新能优化
quota-backend-bytes: 8589934592
max-request-bytes: 10485760
max-concurrent-requests: 5000
#自动压缩与碎片整理
auto-compaction-mode: periodic
auto-compaction-retention: "2h"
#集群通信配置
listen-peer-urls: "http://192.168.28.12:12380"
listen-client-urls: "http://192.168.28.12:12379,http://127.0.0.1:12379"
max-snapshots: 3
max-wals: 5
cors:
initial-advertise-peer-urls: "http://192.168.28.12:12380"
advertise-client-urls: "http://192.168.28.12:12379"
discovery:
discovery-fallback: 'proxy'
discovery-proxy:
discovery-srv:
initial-cluster: "pg-etcd01=http://k8s-etcd01:12380,pg-etcd02=http://k8s-etcd02:12380,pg-etcd03=http://k8s-etcd03:12380"
initial-cluster-token: 'etcd-cluster-pg'
initial-cluster-state: 'new'
strict-reconfig-check: false
enable-v2: true
enable-pprof: true
proxy: 'off'
proxy-failure-wait: 5000
proxy-refresh-interval: 30000
proxy-dial-timeout: 1000
proxy-write-timeout: 5000
proxy-read-timeout: 0


#节点3配置文件
name: pg-etcd03
data-dir: /data/etcd
snapshot-count: 5000
#选举和心跳参数
heartbeat-interval: 100
election-timeout: 1000
#存储新能优化
quota-backend-bytes: 8589934592
max-request-bytes: 10485760
max-concurrent-requests: 5000
#自动压缩与碎片整理
auto-compaction-mode: periodic
auto-compaction-retention: "2h"
#集群通信配置
listen-peer-urls: "http://192.168.28.13:12380"
listen-client-urls: "http://192.168.28.13:12379,http://127.0.0.1:12379"
max-snapshots: 3
max-wals: 5
cors:
initial-advertise-peer-urls: "http://192.168.28.13:12380"
advertise-client-urls: "http://192.168.28.13:12379"
discovery:
discovery-fallback: 'proxy'
discovery-proxy:
discovery-srv:
initial-cluster: "pg-etcd01=http://k8s-etcd01:12380,pg-etcd02=http://k8s-etcd02:12380,pg-etcd03=http://k8s-etcd03:12380"
initial-cluster-token: 'etcd-cluster-pg'
initial-cluster-state: 'new'
strict-reconfig-check: false
enable-v2: true
enable-pprof: true
proxy: 'off'
proxy-failure-wait: 5000
proxy-refresh-interval: 30000
proxy-dial-timeout: 1000
proxy-write-timeout: 5000
proxy-read-timeout: 0
创建 etcd 服务
vim /etc/systemd/system/etcd-pg.service 
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
ExecStart=/usr/local/bin/etcd --config-file=/etc/etcd/etcd-pg.config.yml
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

启动 etcd-pg 服务

systemctl daemon-reload
systemctl start etcd-pg.service
systemctl enable etcd-pg.service
检查 etcd 集群健康状态
root@k8s-master01:~# etcdctl --endpoints="k8s-etcd01:12379,k8s-etcd02:12379,k8s-etcd03:12379" member list  -w=table

+------------------+---------+-----------+-------------------------+----------------------------+------------+
|        ID        | STATUS  |   NAME    |       PEER ADDRS        |        CLIENT ADDRS        | IS LEARNER |
+------------------+---------+-----------+-------------------------+----------------------------+------------+
| 2bb79737c88dd84d | started | pg-etcd03 | http://k8s-etcd03:12380 | http://192.168.28.13:12379 |      false |
| 354b7a6aa8551f4a | started | pg-etcd02 | http://k8s-etcd02:12380 | http://192.168.28.12:12379 |      false |
| 84101e54de967367 | started | pg-etcd01 | http://k8s-etcd01:12380 | http://192.168.28.11:12379

为了简化命令,可以通过 alisa 配置

cd ~
vim .profile
alias  etcdctlpg="etcdctl --endpoints="k8s-etcd01:12379,k8s-etcd02:12379,k8s-etcd03:12379" " source .profile

root@k8s-master01:~# etcdctlpg member list -w=table
+------------------+---------+-----------+-------------------------+----------------------------+------------+
|        ID        | STATUS  |   NAME    |       PEER ADDRS        |        CLIENT ADDRS        | IS LEARNER |
+------------------+---------+-----------+-------------------------+----------------------------+------------+
| 2bb79737c88dd84d | started | pg-etcd03 | http://k8s-etcd03:12380 | http://192.168.28.13:12379 |      false |
| 354b7a6aa8551f4a | started | pg-etcd02 | http://k8s-etcd02:12380 | http://192.168.28.12:12379 |      false |
| 84101e54de967367 | started | pg-etcd01 | http://k8s-etcd01:12380 | http://192.168.28.11:12379 |      false |

Etcd 可视化工具

安装 watchdog (所有节点)

watchdog 防止脑裂。Patroni 支持通过 Linux 的 watchdog 监视 patroni 进程的运行,当 patroni 进程无法正常往 watchdog 设备写入心跳时,由 watchdog 触发 Linux 重启。

# 安装软件,linux内置功能 sudo apt install -y watchdog
# 初始化watchdog字符设备 sudo modprobe softdog
# 修改/dev/watchdog设备权限 sudo chmod 666 /dev/watchdog
sudo chown postgres:postgres /dev/watchdog
# 启动watchdog服务 sudo systemctl start watchdog
sudo systemctl enable watchdog


安装 Patroni (所有节点)

安装
1. pip3 install --break-system-packages  psycopg2-binary
2. pip3 install --break-system-packages  patroni[etcd]
3. pip3 install --break-system-packages python-json-logger   
4. mkdir -p /etc/patroni 
创建配置文件
创建 Patroni 服务
cat /etc/systemd/system/patroni-5433.service 
[Unit]
Description=Patroni high-availability PostgreSQL
After=syslog.target network.target etcd.service
Requires=etcd-pg.service

[Service]
Type=simple
User=postgres
Group=postgres
# 使用watchdog进行服务监控 ExecStartPre=-/usr/bin/sudo /sbin/modprobe softdog ExecStartPre=-/usr/bin/sudo /bin/chown postgres /dev/watchdog
PermissionsStartOnly=true
WorkingDirectory=/home/postgres/
ExecStart=/usr/local/bin/patroni /etc/patroni/patroni-5433.yaml
ExecReload=/bin/kill -HUP 
KillMode=process
Restart=always
RestartSec=10
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

systemctl daemon-reload
配置免密登录
su postgres
cd ~
#备库从主库同步WAL日志使用,主备倒换后,主库降备库,新备库使用,所以备库也配置
touch .pgpass
vim .pgpass
192.168.28.11:5433:*:replica:replica 192.168.28.12:5433:*:replica:replica 192.168.28.13:5433:*:replica:replica 
创建 日志目录
sudo mkdir -p /var/log/patroni/
sudo chown -R postgres:postgres /var/log/patroni/
启动 Patroni

根据节点依次启动 Patroni

sudo systemctl daemon-reload
sudo systemctl restart patroni-5433.service
sudo systemctl enable patroni-5433.service
sudo systemctl status patroni-5433.service

查看服务状态,默认情况下,根据配置文件中,initdb 内容,Patroni 会自动对数据库进行初始化操作,并创建用户,配置文件,拉起数据库并建立主从关系及流复制

查看状态
root@k8s-master01:~# patronictl  -c /etc/patroni/patroni-5433.yaml list
+ Cluster: pg_patroni_etcd () ---+-----------+----+-----------+ | Member | Host               | Role    | State     | TL | Lag in MB | + | pg_patroni_5433_01 | 192.168.28.11:5433 | Leader  | running | 17 | | | pg_patroni_5433_02 | 192.168.28.12:5433 | Replica | streaming | 17 | 0 | | pg_patroni_5433_03 | 192.168.28.13:5433 | Replica | streaming | 17 | 0 | + 

通过 alisa 设置简易命令

alias  patr5433="patronictl  -c /etc/patroni/patroni-5433.yaml" 

patroni 维护命令 (所有节点)

列出节点信息
patronictl -c /etc/patroni/patroni-5433.yaml list
重做备库

reinit 先是移除了整个 data 目录。然后选择正确的节点进行备份恢复。

patronictl -c /etc/patroni/patroni-5433.yaml reinit [nodename]
查看配置
patronictl -c /etc/patroni/patroni-5433.yaml show-config
更改参数
patronictl -c /etc/patroni/patroni-5433.yaml edit-config
#重载参数
patronictl -c /etc/patroni/patroni-5433.yaml reload [nodename]
重启节点 / 关闭节点
  1. 仅重启当前节点
patronictl -c /etc/patroni/patroni-5433.yaml restart [clustername] [nodename] 
  1. 如果节点是 pending 状态的,才会执行重启操作
patronictl -c /etc/patroni/patroni-5433.yaml restart [clustername] --pending 
  1. 重启所有成员
patronictl -c /etc/patroni/patroni-5433.yaml restart [clustername]
维护模式 脱离 patroni 的集群管理
patronictl pause

patronictl pause 暂时将 Patroni 集群置于维护模式并禁用自动
在某些情况下,Patroni 需要暂时退出集群管理,同时仍然在 DCS 中保留集群状态。可能的用例是集群上不常见的活动,例如主要版本升级或损坏恢复。在这些活动期间,节点经常因为 Patroni 不知道的原因而启动和停止,有些节点甚至可以暂时提升,这违反了只运行一个主节点的假设。因此,Patroni 需要能够与正在运行的集群 “分离”,在 Pacemaker 中实现与维护模式相当的功能。

patronictl resume

patronictl resume 将使 Patroni 集群退出维护模式,并重新启用自动故障转移。
自动拉起所有数据库

switchover 主备切换
patronictl switchover
# Switchover
root@k8s-master01:~# patr5433   switchover
Current cluster topology
+ Cluster: pg_patroni_etcd (7540584003720074567) ---+-----------+----+-----------+
| Member             | Host               | Role    | State     | TL | Lag in MB |
+--------------------+--------------------+---------+-----------+----+-----------+
| pg_patroni_5433_01 | 192.168.28.11:5433 | Leader  | running   | 22 |           |
| pg_patroni_5433_02 | 192.168.28.12:5433 | Replica | streaming | 22 |         0 |
| pg_patroni_5433_03 | 192.168.28.13:5433 | Replica | streaming | 22 |         0 |
+--------------------+--------------------+---------+-----------+----+-----------+
Primary [pg_patroni_5433_01]: 
Candidate ['pg_patroni_5433_02', 'pg_patroni_5433_03'] []: pg_patroni_5433_02
When should the switchover take place (e.g. 2025-08-26T12:26 )  [now]: now
Are you sure you want to switchover cluster pg_patroni_etcd, demoting current leader pg_patroni_5433_01? [y/N]: y 
2025-08-26 11:26:32.31189 Successfully switched over to "pg_patroni_5433_02"
+ Cluster: pg_patroni_etcd (7540584003720074567) ---+---------+----+-----------+
| Member             | Host               | Role    | State   | TL | Lag in MB |
+--------------------+--------------------+---------+---------+----+-----------+
| pg_patroni_5433_01 | 192.168.28.11:5433 | Replica | stopped |    |   unknown |
| pg_patroni_5433_02 | 192.168.28.12:5433 | Leader  | running | 22 |           |
| pg_patroni_5433_03 | 192.168.28.13:5433 | Replica | running | 22 |         0 |
+--------------------+--------------------+---------+---------+----+-----------+
root@k8s-master01:~# patr5433   list
+ Cluster: pg_patroni_etcd (7540584003720074567) ---+-----------+----+-----------+
| Member             | Host               | Role    | State     | TL | Lag in MB |
+--------------------+--------------------+---------+-----------+----+-----------+
| pg_patroni_5433_01 | 192.168.28.11:5433 | Replica | streaming | 23 |         0 |
| pg_patroni_5433_02 | 192.168.28.12:5433 | Leader  | running   | 23 |           |
| pg_patroni_5433_03 | 192.168.28.13:5433 | Replica | streaming | 23 |         0 |
+--------------------+--------------------+---------+-----------+----+-----------+
接口切换
 数据库从 pg_patroni_5433_01 switchover 到 pg_patroni_5433_02
[root@pgtest1 ~]# curl -s http://192.168.28.11:8008/switchover -XPOST -d '{"leader":"pg_patroni_5433_01","candidate":"pg_patroni_5433_02"}'
Successfully switched over to "pg_patroni_5433_02" 
failover 切换

patronictl failover

# Failover
[postgres@pgtest1 ~]$ patronictl -c /etc/patroni/patroni-5433.yaml  failover
Candidate ['pg_patroni_5433_01', 'pg_patroni_5433_02','pg_patroni_5433_03'] []: pg_patroni_5433_01
Current cluster topology
... ...
Are you sure you want to failover cluster pg_cluster, demoting current master pg_patroni_5433_02? [y/N]: y
2021-10-28 03:47:56.13486 Successfully failed over to "pg_patroni_5433_01"
... ...

获取主节点 dsn 信息
root@k8s-master01:~# patronictl -c /etc/patroni/patroni-5433.yaml  dsn
host=192.168.28.12 port=5433 

安装 Haproxy (所有节点)

安装 Haproxy
sudo apt install haproxy
编辑 Haproxy 配置文件
sudo vim /etc/haproxy/haproxy.cfg 

global
 maxconn 2000
 ulimit-n 16384
 log 127.0.0.1 local0 err
 stats timeout 30s

defaults
 log global
 mode http
 option httplog
 timeout connect 5000
 timeout client 50000
 timeout server 50000
 timeout http-request 15s
 timeout http-keep-alive 15s

listen status_page
    bind *:8888
    stats enable
    stats uri /haproxy-status
    stats auth    admin:admin
    stats realm "Welcome to the haproxy load balancer status page of k8s-master"

frontend monitor-in
 bind *:33305
 mode http
 option httplog
 monitor-uri /monitor
# 主库读写端口
listen master
    bind *:15433
    mode tcp
    option tcplog
    balance roundrobin
    option httpchk OPTIONS /master
    http-check expect status 200
    default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
    server pgtest1 192.168.28.11:5433 maxconn 1000 check port 8008 inter 5000 rise 2 fall 2
    server pgtest2 192.168.28.12:5433 maxconn 1000 check port 8008 inter 5000 rise 2 fall 2
    server pgtest3 192.168.28.13:5433 maxconn 1000 check port 8008 inter 5000 rise 2 fall 2

#从库读端口
listen replicas
    bind *:25433
    mode tcp
    option tcplog
    balance roundrobin
    option httpchk OPTIONS /replica
    http-check expect status 200
    default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
    server pgtest1 192.168.28.11:5433 maxconn 1000 check port 8008 inter 5000 rise 2 fall 2
    server pgtest2 192.168.28.12:5433 maxconn 1000 check port 8008 inter 5000 rise 2 fall 2
    server pgtest3 192.168.28.13:5433 maxconn 1000 check port 8008 inter 5000 rise 2 fall 2
启动 haproxy
sudo systemctl enable haproxy
sudo systemctl start haproxy
HAProxy 监控页面

登录地址:[[http://192.168.28.11:8888/haproxy-status]] (也可以通过各个节点 IP + 端口登录)

默认用户密码:admin/admin

安装 Keepalived (所有节点)

安装
sudo apt install -y keepalived
配置文件
主服务配置文件
vim /etc/keepalived/keepalived.conf

global_defs {

router_
id LVS_DEVEL00

script_
user root enable_script_security } vrrp_script check_haproxy { script "/etc/keepalived/check_haproxy.sh" interval 2 weight 5 fall 3 rise 5 timeout 2 } vrrp_instance VI_1 { state Master interface ens18 virtual_router_id 80 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 12345 } virtual_ipaddress { 192.168.28.10/24 } track_script { check_haproxy } }
备库节点 1 配置文件
vim /etc/keepalived/keepalived.conf
global_defs {

router_
id LVS_DEVEL01

script_
user root enable_script_security } vrrp_script check_haproxy { script "/etc/keepalived/check_haproxy.sh" interval 2 weight 5 fall 3 rise 5 timeout 2 } vrrp_instance VI_1 { state BACKUP interface ens18 virtual_router_id 80 priority 90 advert_int 1 authentication { auth_type PASS auth_pass 12345 } virtual_ipaddress { 192.168.28.10/24 } track_script {

check_
haproxy } }
备库节点 2 配置文件
vim /etc/keepalived/keepalived.conf

global_defs {

router_
id LVS_DEVEL02

script_
user root enable_script_security } vrrp_script check_haproxy { script "/etc/keepalived/check_haproxy.sh" interval 2 weight 5 fall 3 rise 5 timeout 2 } vrrp_instance VI_1 { state BACKUP interface ens18 virtual_router_id 80 priority 80 advert_int 1 authentication { auth_type PASS auth_pass 12345 } virtual_ipaddress { 192.168.24.15/24 } track_script {

check_
haproxy } }
检查脚本
vim /etc/keepalived/check_haproxy.sh

#!/bin/bash
count=`ps aux | grep -v grep | grep haproxy | wc -l`
if [ $count -eq 0 ]; then exit 1
else exit 0
fi 

赋予执行权限

chmod +x /etc/keepalived/check_haproxy.sh
依次启动
sudo systemctl start keepalived
sudo systemctl enable keepalived

📌 转载信息
原作者:
xxdtb
转载时间:
2026/1/19 17:52:08

感谢 @elky 大佬开源此项目

大佬沉迷 coding ,更新了也不发贴

我近期也是疯狂的给大佬提需求 (偶尔提交几个 PR

更新说明: 本次更新距离上次版本已有较长时间,带来了多项功能新增和改进

1. 中转站 & 公益站余额监控

  • 支持通过 New-API 接口获取账户余额信息

2. 模型正则映射

  • 通过正则表达式自动匹配和映射模型别名,无需手动逐个修改模型配置

3. 模块管理与 OAuth 登录

  • 模块化系统架构,支持功能模块的独立管理
  • 集成 OAuth 2.0 协议,支持第三方平台登录认证 (目前只支持 Linux Do)

4. 端点密钥分离与智能分配

  • 密钥与端点解耦,单个密钥支持配置多个端点
  • 支持自动获取模型功能

5. 请求详情对话视图

  • 请求体和响应体以对话形式展示
  • 优化了调试信息的可读性

后续计划

  • 支持上游 New-api 签到
  • 增加中转站的 周 / 天 / 小时 等限制
  • 工单系统,用于额度申请等
  • 基于提供商模型列表的健康监控,用于展示每个提供商模型的健康度
  • Chat / 生图 / 操练场

📌 转载信息
原作者:
AAEE86
转载时间:
2026/1/19 17:46:21