使用 PostgreSQL 16.1 + Citus 12.1 作为多个微服务的分布式 Sharding 存储后端

在本教程中,我们将使用 PostgreSQL 16.1 + Citus 12.1 作为多个微服务的存储后端,演示此类集群的样例设置和基本操作。
Citus 12.1 实验环境设置
Docker 快速启动 Citus 分布式集群
docker-compose.yml
version: "3"
services:
master:
container_name: "${COMPOSE_PROJECT_NAME:-citus}_master"
image: "citusdata/citus:12.1.1"
ports: ["${COORDINATOR_EXTERNAL_PORT:-5432}:5432"]
labels: ["com.citusdata.role=Master"]
environment: &AUTH
POSTGRES_USER: "${POSTGRES_USER:-postgres}"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-citus}"
PGUSER: "${POSTGRES_USER:-postgres}"
PGPASSWORD: "${POSTGRES_PASSWORD:-citus}"
POSTGRES_HOST_AUTH_METHOD: "${POSTGRES_HOST_AUTH_METHOD:-trust}"
worker:
image: "citusdata/citus:12.1.1"
labels: ["com.citusdata.role=Worker"]
depends_on: [manager]
environment: *AUTH
command: "/wait-for-manager.sh"
volumes:
- healthcheck-volume:/healthcheck
manager:
container_name: "${COMPOSE_PROJECT_NAME:-citus}_manager"
image: "citusdata/membership-manager:0.3.0"
volumes:
- "${DOCKER_SOCK:-/var/run/docker.sock}:/var/run/docker.sock"
- healthcheck-volume:/healthcheck
depends_on: [master]
environment: *AUTH
volumes:
healthcheck-volume:
启动拥有 3 个 worker 的集群
docker-compose -p citus up --scale worker=3

查看 worker 节点
docker exec -it citus_master psql -U postgres
SELECT master_get_active_worker_nodes();
master_get_active_worker_nodes
--------------------------------
(citus-worker-3,5432)
(citus-worker-1,5432)
(citus-worker-2,5432)
(3 rows)
微服务的 Citus 存储后端实战
Citus 官方示例源码
在我们的示例中,我们将使用三个服务:
userservicetimeservicepingservice
Distributed schemas(分布式模式)
分布式模式可以在 Citus 集群中重新定位。系统可以在可用节点之间将它们作为一个整体重新平衡,从而允许有效地共享资源,而无需手动分配。
根据设计,微服务拥有自己的存储层,我们不会对它们将创建和存储的表和数据的类型做任何假设。但是,我们将为每个服务提供一个 schema,并假设它们将使用不同的 ROLE 连接到数据库。当用户连接时,他们的角色名称将放在 search_path 的开头,因此,如果 role 与 schema 名称匹配,则不需要更改任何应用程序来设置正确的 search_path。
连接到 Citus 协调器
docker exec -it citus_master psql -U postgres
为服务创建数据库角色与密码
CREATE USER user_service;
CREATE USER time_service;
CREATE USER ping_service;
在 Citus 中,模式有两种分布方式:
手动调用 citus_schema_distribute(schema_name) 函数:
CREATE SCHEMA AUTHORIZATION user_service;
CREATE SCHEMA AUTHORIZATION time_service;
CREATE SCHEMA AUTHORIZATION ping_service;
SELECT citus_schema_distribute('user_service');
SELECT citus_schema_distribute('time_service');
SELECT citus_schema_distribute('ping_service');
此方法还允许将现有的常规模式转换为分布式模式。
只能分发不包含分布式表和引用表的模式。
另一种方法是启用 citus.enable_schema_based_sharding 配置变量:
SET citus.enable_schema_based_sharding TO ON;
CREATE SCHEMA AUTHORIZATION user_service;
CREATE SCHEMA AUTHORIZATION time_service;
CREATE SCHEMA AUTHORIZATION ping_service;
这个变量可以在当前会话中修改,也可以在 postgresql.conf 中永久修改。将参数设置为 ON 时,默认情况下将分发所有创建的模式。
你可以列出当前分布的模式:
select * from citus_schemas;
schema_name | colocation_id | schema_size | schema_owner
--------------+---------------+-------------+--------------
user_service | 1 | 0 bytes | user_service
time_service | 2 | 0 bytes | time_service
ping_service | 3 | 0 bytes | ping_service
(3 rows)
创建表
现在需要为每个微服务连接到 Citus 协调器。可以使用 \c 命令在现有的 psql 实例中切换用户。
\c postgres user_service
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL
);
\d
List of relations
Schema | Name | Type | Owner
--------------+---------------+----------+--------------
public | citus_schemas | view | postgres
public | citus_tables | view | postgres
user_service | users | table | user_service
user_service | users_id_seq | sequence | user_service
\c postgres time_service
CREATE TABLE query_details (
id SERIAL PRIMARY KEY,
ip_address INET NOT NULL,
query_time TIMESTAMP NOT NULL
);
\c postgres ping_service
CREATE TABLE ping_results (
id SERIAL PRIMARY KEY,
host VARCHAR(255) NOT NULL,
result TEXT NOT NULL
);
配置服务
citus-example-microservices 存储库包含 ping、time 和 user 服务。它们都有一个我们要运行的 app.py。
$ tree
.
├── LICENSE
├── README.md
├── ping
│ ├── app.py
│ ├── ping.sql
│ └── requirements.txt
├── time
│ ├── app.py
│ ├── requirements.txt
│ └── time.sql
└── user
├── app.py
├── requirements.txt
└── user.sql
为了保障快速测试 Demo,这里我为大家提供已经构建好的示例服务的 docker 镜像,大家直接用就好。
在构建镜像之前,我已经针对每个服务的 app.py 做了一定的修改,如下:
user/app.py
db_config = {
'host': 'citus_master',
'database': 'postgres',
'user': 'user_service',
'port': 5432
}
...
app.run(host="0.0.0.0", port=5000)
time/app.py
db_config = {
'host': 'citus_master',
'database': 'postgres',
'user': 'time_service',
'port': 5432
}
...
app.run(host="0.0.0.0", port=5000)
ping/app.py
db_config = {
'host': 'citus_master',
'database': 'postgres',
'user': 'ping_service',
'port': 5432
}
...
app.run(host="0.0.0.0", port=5000)
当然,你也可以切换到每个 app 目录,直接在各自的 python 环境中运行它们。
Docker 快速启动 user 服务
docker run -d --name usersvc -p 6000:5000 \
--network=citus_default \
registry.cn-heyuan.aliyuncs.com/hacker-linner/citus-microsvc-user:1.0.0
Docker 快速启动 time 服务
docker run -d --name timesvc -p 6001:5000 \
--network=citus_default \
registry.cn-heyuan.aliyuncs.com/hacker-linner/citus-microsvc-time:1.0.0
Docker 快速启动 ping 服务
docker run -d --name pingsvc -p 6002:5000 \
--network=citus_default \
registry.cn-heyuan.aliyuncs.com/hacker-linner/citus-microsvc-ping:1.0.0
创建一些用户
curl -X POST -H "Content-Type: application/json" -d '[
{"name": "John Doe", "email": "john@example.com"},
{"name": "Jane Smith", "email": "jane@example.com"},
{"name": "Mike Johnson", "email": "mike@example.com"},
{"name": "Emily Davis", "email": "emily@example.com"},
{"name": "David Wilson", "email": "david@example.com"},
{"name": "Sarah Thompson", "email": "sarah@example.com"},
{"name": "Alex Miller", "email": "alex@example.com"},
{"name": "Olivia Anderson", "email": "olivia@example.com"},
{"name": "Daniel Martin", "email": "daniel@example.com"},
{"name": "Sophia White", "email": "sophia@example.com"}
]' http://localhost:6000/users
{"message":"Users created successfully","user_ids":[1,2,3,4,5,6,7,8,9,10]}
列出已创建的用户
curl http://localhost:6000/users
获取当前时间
curl http://localhost:6001/current_time
{"current_time":"2023-12-25 06:19:28","ip_address":"192.168.65.1"}
对 baidu.com 执行 ping 命令:
curl -X POST -H "Content-Type: application/json" -d '{"host": "baidu.com"}' http://localhost:6002/ping
{"host":"baidu.com","result":"PING baidu.com (110.242.68.66): 56 data bytes\n64 bytes from 110.242.68.66: icmp_seq=0 ttl=63 time=56.996 ms\n64 bytes from 110.242.68.66: icmp_seq=1 ttl=63 time=84.375 ms\n64 bytes from 110.242.68.66: icmp_seq=2 ttl=63 time=99.899 ms\n64 bytes from 110.242.68.66: icmp_seq=3 ttl=63 time=130.946 ms\n--- baidu.com ping statistics ---\n4 packets transmitted, 4 packets received, 0% packet loss\nround-trip min/avg/max/stddev = 56.996/93.054/130.946/26.731 ms\n"}
探索数据库
现在我们调用了一些 API 函数,数据已经存储,我们可以检查 citus_schemas 是否反映了我们所期望的:
docker exec -it citus_master psql -U postgres
select * from citus_schemas;
schema_name | colocation_id | schema_size | schema_owner
--------------+---------------+-------------+--------------
user_service | 1 | 32 kB | user_service
time_service | 2 | 32 kB | time_service
ping_service | 3 | 32 kB | ping_service
(3 rows)
当我们创建模式时,我们没有告诉 citus 在哪些 worker 机器上创建 schema。它已经自动为我们完成了这些。我们可以通过下面的查询查看每个 schema 所在的位置:
select nodename,nodeport, table_name, pg_size_pretty(sum(shard_size))
from citus_shards
group by nodename,nodeport, table_name;
nodename | nodeport | table_name | pg_size_pretty
----------------+----------+----------------------------+----------------
citus-worker-1 | 5432 | ping_service.ping_results | 32 kB
citus-worker-2 | 5432 | user_service.users | 32 kB
citus-worker-3 | 5432 | time_service.query_details | 32 kB
(3 rows)
OK! 我们可以看到,各个微服务的后端存储已经默认被分配到不同的 worker 机器节点了。
使用 PostgreSQL 16.1 + Citus 12.1 作为多个微服务的分布式 Sharding 存储后端的更多相关文章
- Kubernetes 部署微服务电商平台(16)
一.概念 微服务就是很小的服务,小到一个服务只对应一个单一的功能,只做一件事.这个服务可以单独部署运行,服务之间可以通过RPC来相互交互,每个微服务都是由独立的小团队开发,测试,部署,上线,负责它的整 ...
- 分布式 PostgreSQL 集群(Citus)官方示例 - 实时仪表盘
Citus 提供对大型数据集的实时查询.我们在 Citus 常见的一项工作负载涉及为事件数据的实时仪表板提供支持. 例如,您可以是帮助其他企业监控其 HTTP 流量的云服务提供商.每次您的一个客户端收 ...
- 分布式 PostgreSQL 集群(Citus)官方示例 - 时间序列数据
在时间序列工作负载中,应用程序(例如一些实时应用程序查询最近的信息,同时归档旧信息. https://docs.citusdata.com/en/v10.2/sharding/data_modelin ...
- 分布式 PostgreSQL 集群(Citus),分布式表中的分布列选择最佳实践
确定应用程序类型 在 Citus 集群上运行高效查询要求数据在机器之间正确分布.这因应用程序类型及其查询模式而异. 大致上有两种应用程序在 Citus 上运行良好.数据建模的第一步是确定哪些应用程序类 ...
- 分布式 PostgreSQL 集群(Citus)官方教程 - 迁移现有应用程序
将现有应用程序迁移到 Citus 有时需要调整 schema 和查询以获得最佳性能. Citus 扩展了 PostgreSQL 的分布式功能,但它不是扩展所有工作负载的直接替代品.高性能 Citus ...
- 分布式 PostgreSQL 集群(Citus)官方安装指南
单节点 Citus Docker (Mac 与 Linux) Docker 镜像仅用于开发/测试目的, 并且尚未准备好用于生产用途. 您可以使用一个命令在 Docker 中启动 Citus: # st ...
- 分布式 PostgreSQL 集群(Citus),官方快速入门教程
多租户应用程序 在本教程中,我们将使用示例广告分析数据集来演示如何使用 Citus 来支持您的多租户应用程序. 注意 本教程假设您已经安装并运行了 Citus. 如果您没有运行 Citus,则可以使用 ...
- GoldenGate 12.3微服务架构与传统架构的区别
随着Oracle GoldenGate 12c(12.3.0.1.0)的发布,引入了可用于复制业务数据的新架构. 多年来,这种架构有着不同的称谓,Oracle终于在最后GA发布的版本中,以“Micro ...
- 【12】JMicro微服务-Zookeeper
如非授权,禁止用于商业用途,转载请注明出处作者:mynewworldyyl 往下看前,建议完成前面1到11小节 1. CuratorFramework支持 JMicro目前基于Zookeeper实现统 ...
- Docker1.12 + Swarm 构建动态微服务应用
导读 我们在之前提到过一个示例,即一款由前端与多项后端服务共同构成的微服务应用.其中前端为Traefik HTTP代理,负责将各项请求路由至后端服务.而后端则非常简单,是一套基于Go的HTTP Web ...
随机推荐
- Hugging News #0904:🤗 登陆 AWS Marketplace
每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新.社区活动.学习资源和内容更新.开源库和模型更新等,我们将其称之为「Hugging Ne ...
- springboot集成seata1.5.2+nacos2.1.1
一.前言 Seata出现前,大部分公司使用的都是TCC或者MQ(RocketMq)等来解决分布式事务的问题,TCC代码编写复杂,每个业务均需要实现三个入口,侵入性强,RocketMQ保证的是最终一致性 ...
- yum&二进制安装PostgreSQL 12
一.yum安装&配置PostgreSQL 12 目录 一.yum安装&配置PostgreSQL 12 一.前言 1.本文主要内容 2.本文环境信息与适用范围 二.PostgreSQL安 ...
- Azure Data Factory(八)数据集验证之服务主体(Service Principal)
一,引言 如下图所示,今天我们接着上一篇内容,继续讲解 Azure Data Factory 中的数据集连接服务的认证方式:Service Principal 关于 Service Principal ...
- 【RcoketMQ】RcoketMQ 5.0新特性(一)- Proxy
为了向云原生演进,提高资源利用和弹性能力,RcoketMQ在5.0进行了架构的调整与升级,先来看新特性之一,增加了Proxy层. 增加Proxy代理层 计算存储分离 计算存储分离是一种分层架构,将计算 ...
- 如何使用SHC对Shell脚本进行封装和源码隐藏
在许多情况下,我们需要保护我们的shell脚本源码不被别人轻易查看.这时,使用shc工具将shell脚本编译成二进制文件是一个有效的方法.本文将详细介绍如何在线和离线条件下安装shc,并将其用于编译你 ...
- Error resolving template [sys/prod/prod/list], template might not exist or might not be accessible by any of the configured Template Resolvers
新的商城模板调试接口,一个商品列表的接口调用,返回报错 org.thymeleaf.exceptions.TemplateInputException: Error resolving templat ...
- 【日常收支账本】【Day04】优化编辑动账记录的操作——QTableWidget单元格设置QComboBox控件
一.项目地址 https://github.com/LinFeng-BingYi/DailyAccountBook 二.新增 1. 在表格中设置选项列表,让用户更快地编辑动账记录 1.1 功能详述 为 ...
- 使用Github Copilot生成单元测试并执行
上一篇文章我们介绍了 使用Github Copilot完成代码编写 本文我们继续使用Github Copilot在已有代码的基础上生成代码测试并执行. 一.先说一下代码的背景 需要上需要提供一个度量衡 ...
- SNN_文献阅读_Text Classification in Memristor-based Spiking Neural Networks
SNN中局部学习和非局部学习,基于梯度的规则都需要对用于表示单个连续值的脉冲训练窗口上的累积误差进行平均,这种方法在更新权重时考虑了每一个脉冲的影响.在计算速度和空间效率等方面,特别是当代表单个数值的 ...