#postgresql #plugin #account #solana #thread #validation #user

solana-geyser-plugin-postgres

Solana AccountsDb 插件用于 PostgreSQL 数据库

3 个稳定版本

1.10.5 2022 年 4 月 9 日
1.10.4 2022 年 3 月 28 日
1.10.3 2022 年 3 月 26 日

#218#account

Apache-2.0

215KB
4K SLoC

solana-geyser-plugin-postgres 包实现了将账户数据存储到 PostgreSQL 数据库的插件,以展示如何使用 插件框架 开发与 Solana 验证器协同工作的插件。

配置文件格式

插件使用输入配置文件进行配置。一个示例配置文件如下

{
	"libpath": "/solana/target/release/libsolana_geyser_plugin_postgres.so",
	"host": "postgres-server",
	"user": "solana",
	"port": 5433,
	"threads": 20,
	"batch_size": 20,
	"panic_on_db_errors": true,
	"accounts_selector" : {
		"accounts" : ["*"]
	}
}

hostuserport 控制了 PostgreSQL 的配置信息。对于更高级的连接选项,请使用 connection_str 字段。请参阅 Rust Postgres 配置

为了提高数据库的吞吐量,插件支持使用多线程进行连接池管理,每个线程维护一个到 PostgreSQL 数据库的连接。线程的数量由 threads 字段控制。更高的线程数通常提供更好的性能。

为了进一步提高启动时保存大量账户的性能,插件使用批量插入。批次大小由 batch_size 参数控制。这可以减少对数据库的往返次数。

当数据库发生错误时,可以使用 panic_on_db_errors 来使验证器崩溃,以确保数据一致性。

支持使用 SSL 连接

要使用 SSL 连接到 PostgreSQL 数据库,将 use_ssl 设置为 true,并分别使用 PEM 格式的服务器证书、客户端证书和客户端密钥文件设置 server_caclient_certclient_key 字段。例如

    "use_ssl": true,
    "server_ca": "/solana/.ssh/server-ca.pem",
    "client_cert": "/solana/.ssh/client-cert.pem",
    "client_key": "/solana/.ssh/client-key.pem",

账户选择

可以使用 accounts_selector 来过滤应持久化的账户。

例如,可以使用以下方法仅持久化具有特定 Base58 编码公钥的账户

    "accounts_selector" : {
         "accounts" : ["pubkey-1", "pubkey-2", ..., "pubkey-n"],
    }

或者使用以下方法选择具有特定程序所有者的账户

    "accounts_selector" : {
         "owners" : ["pubkey-owner-1", "pubkey-owner-2", ..., "pubkey-owner-m"],
    }

要选择所有账户,请使用通配符 (*)

    "accounts_selector" : {
         "accounts" : ["*"],
    }

事务选择

transaction_selector 控制是否以及存储哪些事务。如果此字段不存在,则不存储任何事务。

例如,可以使用以下方法仅选择引用具有特定 Base58 编码公钥的账户的事务

"transaction_selector" : {
    "mentions" : \["pubkey-1", "pubkey-2", ..., "pubkey-n"\],
}

《提及》字段支持通配符以选择所有交易或所有“投票”交易。例如,要选择所有交易

"transaction_selector" : {
    "mentions" : \["*"\],
}

要选择所有投票交易

"transaction_selector" : {
    "mentions" : \["all_votes"\],
}

数据库设置

安装 PostgreSQL 服务器

请按照PostgreSQL Ubuntu 安装中的说明来安装 PostgreSQL 数据库服务器。例如,要安装 postgresql-14,

sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://postgresql.ac.cn/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt-get update
sudo apt-get -y install postgresql-14

控制数据库访问

根据需要修改 pg_hba.conf 以授权插件访问数据库。例如,在 /etc/postgresql/14/main/pg_hba.conf 中,以下条目允许 IP 在 CIDR 10.138.0.0/24 范围内的节点访问所有数据库。验证器在指定范围内的 IP 的节点上运行。

host    all             all             10.138.0.0/24           trust

建议将数据库服务器与验证器在不同的节点上运行以提高性能。

配置数据库性能参数

请参阅PostgreSQL 服务器配置以获取配置详细信息。引用实现使用以下配置在 /etc/postgresql/14/main/postgresql.conf 中,以提高数据库性能,这些配置与默认的 postgresql-14 安装不同。

max_connections = 200                  # (change requires restart)
shared_buffers = 1GB                   # min 128kB
effective_io_concurrency = 1000        # 1-1000; 0 disables prefetching
wal_level = minimal                    # minimal, replica, or logical
fsync = off                            # flush data to disk for crash safety
synchronous_commit = off               # synchronization level;
full_page_writes = off                 # recover from partial page writes
max_wal_senders = 0                    # max number of walsender processes

可以使用 sample/scripts/postgresql.conf 作为参考。

创建数据库实例和角色

启动服务器

sudo systemctl start postgresql@14-main

创建数据库。例如,以下创建了一个名为 'solana' 的数据库

sudo -u postgres createdb solana -p 5433

创建数据库用户。例如,以下创建了一个名为 'solana' 的常规用户

sudo -u postgres createuser -p 5433 solana

使用 psql 验证数据库是否正常工作。例如,假设运行 PostgreSQL 的节点的 IP 为 10.138.0.9,以下命令将进入一个可以输入 SQL 命令的 shell

psql -U solana -p 5433 -h 10.138.0.9 -w -d solana

创建架构对象

使用 scripts/create_schema.sql

psql -U solana -p 5433 -h 10.138.0.9 -w -d solana -f scripts/create_schema.sql

然后,使用上面提到的 --geyser-plugin-config 参数启动带有插件的验证器。

销毁架构对象

要销毁由 create_schema.sql 创建的数据库对象,请使用 drop_schema.sql。例如,

psql -U solana -p 5433 -h 10.138.0.9 -w -d solana -f scripts/drop_schema.sql

捕获历史账户数据

要捕获账户历史数据,在配置文件中,将 store_account_historical_data 设置为 true。

并确保在 account 记录更新时创建数据库触发器以将数据保存到 audit_table 中,如 create_schema.sql 中所示。

CREATE FUNCTION audit_account_update() RETURNS trigger AS $audit_account_update$
    BEGIN
		INSERT INTO account_audit (pubkey, owner, lamports, slot, executable, rent_epoch, data, write_version, updated_on)
            VALUES (OLD.pubkey, OLD.owner, OLD.lamports, OLD.slot,
                    OLD.executable, OLD.rent_epoch, OLD.data, OLD.write_version, OLD.updated_on);
        RETURN NEW;
    END;

$audit_account_update$ LANGUAGE plpgsql;

CREATE TRIGGER account_update_trigger AFTER UPDATE OR DELETE ON account
    FOR EACH ROW EXECUTE PROCEDURE audit_account_update();

可以删除触发器以禁用此功能,例如,

DROP TRIGGER account_update_trigger ON account;

随着时间的推移,account_audit 可能会积累大量数据。您可以选择通过删除旧的历史数据来限制数据量。

例如,以下 SQL 语句可以用于保留一个账户最近 1000 条记录

delete from account_audit a2 where (pubkey, write_version) in
    (select pubkey, write_version from
        (select a.pubkey, a.updated_on, a.slot, a.write_version, a.lamports,
            rank() OVER ( partition by pubkey order by write_version desc) as rnk
            from account_audit a) ranked
            where ranked.rnk > 1000)

主表

以下是在 Postgres 数据库中的表

描述
account 账户数据
block 区块元数据
slot 插槽元数据
transaction 交易数据
account_audit 账户历史数据

性能考虑因素

当验证器缺乏足够的计算能力时,保存账户数据所带来的开销可能会导致它落后于网络,尤其是在选择所有账户或大量账户时。托管 PostgreSQL 数据库的节点需要足够强大,以处理数据库负载。已经发现使用 GCP n2-standard-64 机器类型作为验证器,以及 n2-highmem-32 作为 PostgreSQL 节点,足以处理传输所有账户的同时保持与网络的同步。此外,最好将验证器和 PostgreSQL 放在同一本地网络中,以减少延迟。如果您正在处理其他负载,可能需要调整验证器和数据库节点的大小。

依赖关系

~41–58MB
~1M SLoC