负载与租户隔离

Proxy 是 MatrixOne 在 0.8 版本中引进的新系统组件,它可以通过流量代理和转发的方式实现租户、负载隔离等功能。关于 Proxy 的技术设计,可以参考 Proxy 架构详解

本篇文档主要介绍如何使用 Proxy 来建立不同的 CN 组,以实现租户和负载的独立资源管理。

系统架构

如下图所示,用户首先连接到 Proxy 模块。Proxy 组件根据用户连接串中的身份和标签信息,将用户的数据库连接(connection)分发到相应的 CN 组。其他 CN 组不会接收到此用户连接,也不会参与该连接的计算过程。

CN 组是由一组具有相同属性和大小的 CN 节点组成的逻辑 CN 组,它是 MatrixOne 集群中用于隔离不同资源组的单位。每个 CN 组可包含 1 个到无限个 CN 节点,并可使用一系列标签定义其属性,例如定义某租户对应的 Account 标签,将连接转发至带有相应标签的 CN 组,便可实现租户资源隔离和业务负载隔离功能。结合 CN 组中 CN 节点可无限水平扩展的特性,可实现针对租户或指定负载的独立扩展。

为确保 Proxy 的高可用性,需要在集群中设置至少 2 个副本。

proxy-cn-group

当对 CN 进行缩容时,Proxy 在 YAML 文件的行为如下:

  • 同一个 Label 会话搬迁:当 CN 的副本数量减少时,具有相同 Label 的会话将被迁移到其他缩容后的 CN 节点上。这样可以保持与特定 Label 相关的会话的连续性和可用性。

  • 不同 Label 会话搬迁:如果某个 Label 的 CN 副本被置为 0 或取消,根据 Label 的匹配规则,将会在将来的会话中将这个 Label 相关的会话迁移到空闲的 Label 上。

  • Label 取消并且没有匹配 Label:如果某个 Label 被取消,而且没有与之匹配的 Label,相关会话将被关闭,因为没有目标 CN 可以接收这些会话。

Proxy 在 CN 缩容时通过以上行为处理会话的迁移和关闭,以确保负载和租户之间的隔离以及业务的连续性。

操作步骤

本篇文档所介绍到的使用 Proxy 管理 CN 组的环境将基于 MatrixOne 分布式集群部署的环境。

为了方便你了解资源隔离与分配情况,可以在下面表格中参考 MatrixOne 分布式集群部署环境中各个硬件节点情况分布,具体如下所示:

Host内网 IP外网 IP内存CPUDiskRole
kuboardspray10.206.0.61.13.2.1002G2C50G跳板机
master010.206.134.8118.195.255.2528G2C50Gmaster etcd
node010.206.134.141.13.13.1998G2C50Gworker

第一步:启用 Proxy

在 MatrixOne 分布式集群中启用 Proxy 组件,你需要在创建集群时指定所需的 Proxy 拓扑,或者在现有集群中添加 Proxy 拓扑后,执行 kubectl apply 以启用 Proxy 组件。详细步骤如下:

  1. 修改 MatrixOne 集群的 mo.yaml 文件:

    1. metadata:
    2. name: mo
    3. namespace: mo-hn
    4. spec:
    5. + proxy:
    6. + replicas: 2 #为了高可用,proxy 的 replicas 需要至少 2 个
  2. 修改完成后,使用下面的命令行运行 mo.yaml 文件:

    1. kubectl apply -f mo.yaml
  3. 运行 kubectl get pod -nmo-hn 检查 Proxy 状态是否正常启动:

    1. root@HOST-10-206-134-16:~# kubectl get pod -nmo-hn
    2. NAME READY STATUS RESTARTS AGE
    3. mo-tn-0 1/1 Running 0 2m51s
    4. mo-log-0 1/1 Running 0 3m25s
    5. mo-log-1 1/1 Running 0 3m25s
    6. mo-log-2 1/1 Running 0 3m25s
    7. mo-proxy-69zjf 1/1 Running 0 2m51s
    8. mo-proxy-fpn2g 1/1 Running 0 2m51s
    9. mo-tp-cn-0 1/1 Running 0 2m25s
  4. 正常启动后的代码示例如上述所示。这样最小化的 Proxy 组件就启动完成了。你可以使用 kubectl get svc -nmo-hn 通过 Proxy 的 SVC 地址即可以连接到该集群:

    1. root@HOST-10-206-134-16:~# kubectl get svc -nmo-hn
    2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    3. mo-tn-headless ClusterIP None <none> <none> 70m
    4. mo-log-discovery ClusterIP 10.96.3.186 <none> 32001/TCP 71m
    5. mo-log-headless ClusterIP None <none> <none> 71m
    6. mo-proxy NodePort 10.96.1.153 <none> 6001:31429/TCP 70m
    7. mo-tp-cn ClusterIP 10.96.1.43 <none> 6001/TCP 70m
    8. mo-tp-cn-headless ClusterIP None <none> <none> 70m
    9. root@HOST-10-206-134-16:~# mysql -h 10.96.1.153 -P6001 -uroot -p111
    10. mysql: [Warning] Using a password on the command line interface can be insecure.
    11. Welcome to the MySQL monitor. Commands end with ; or \g.
    12. Your MySQL connection id is 2064
    13. Server version: 8.0.30-MatrixOne-v0.5.0 MatrixOne
    14. Copyright (c) 2000, 2023, Oracle and/or its affiliates.
    15. Oracle is a registered trademark of Oracle Corporation and/or its
    16. affiliates. Other names may be trademarks of their respective owners.
    17. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    18. mysql>

若整个集群中有多个 CN 的话,Proxy 会自动实现连接级别的负载均衡,将用户的连接均匀分配到不同的 CN 上。你可以查询系统表 system_metrics.server_connections 来查看每个 CN 上的用户连接个数。

第二步:设置 CN 组

在 MatrixOne 集群的 mo.yaml 文件中,你需要通过设置 cnGroups 字段来配置 CN 组,并在每个 cnGroups 中配置 cnLabels 字段,以设定该 CN 组中所有 CN 的标签。Proxy 会根据连接标签进行路由转发。例如,在以下示例中,你设置了名为 cn-set1cn-set2 的两个 CN 组。每个 CN 组可以具有自己的独立副本数、不同的日志级别、CN 参数配置以及 CN 标签。

CN 组的标签采用一到多组 Key/value 格式,其中每组 Key 与 value 之间存在一对多的关系,即每个 Key 可拥有多个 value。

详细步骤如下:

  1. 参照下面的配置参数示例,配置 CN 组的标签:

    1. metadata:
    2. name: mo
    3. namespace: mo-hn
    4. spec:
    5. + cnGroups:
    6. + - name: cn-set1
    7. + replicas: 1
    8. + cnLabels:
    9. + - key: "cn-set1"
    10. + values: ["1", "high"]
    11. + - key: "account"
    12. + values: ["acc1"]
    13. +
    14. + - name: cn-set2
    15. + replicas: 1
    16. + cnLabels:
    17. + - key: "cn-set2"
    18. + values: ["2", "medium"]
    19. + - key: "account"
    20. + values: ["acc2"]
  2. 修改完成后,使用下面的命令行运行 mo.yaml 文件:

    1. kubectl apply -f mo.yaml
  3. 运行 kubectl get pod -nmo-hn 检查 Proxy 状态是否正常启动:

  1. root@HOST-10-206-134-16:~# kubectl get pod -nmo-hn
  2. NAME READY STATUS RESTARTS AGE
  3. mo-cn-set1-cn-0 1/1 Running 0 6s
  4. mo-cn-set2-cn-0 1/1 Running 0 6s
  5. mo-tn-0 1/1 Running 0 97m
  6. mo-log-0 1/1 Running 0 97m
  7. mo-log-1 1/1 Running 0 97m
  8. mo-log-2 1/1 Running 0 97m
  9. mo-proxy-69zjf 1/1 Running 0 97m
  10. mo-proxy-fpn2g 1/1 Running 0 97m

正常启动后的代码示例如上述所示。

CN 组的标签设置非常灵活,但是一般最常见的还是用在租户和负载的隔离上。

关于如何实现租户隔离和负载隔离,请继续参加下面的章节。

实现租户隔离

MatrixOne 0.7 版本已实现对多租户数据隔离的支持。若要实现租户负载隔离,则需通过配置 Proxy 和 CN 组来完成。

普通租户

在 CN 组的标签设置中,account 标签是保留字段,用作匹配租户。

在本章中,假设需要为 acc1acc2 这两个租户实现租户负载隔离,你可以参见下面的详细步骤:

Note

仅支持拥有系统租户权限的用户才能为普通租户配置负载隔离。

  1. 使用系统租户登录到 MatrixOne 集群,用户名和密码请咨询你所在公司的数据库管理员。登录到 MatrixOne 集群后,分别创建两个新租户 acc1acc2

    1. -- 创建新租户 acc1,密码为 123456(在这里设置简单密码,仅做为示例讲解使用)
    2. mysql> create account acc1 admin_name 'admin' identified by '123456';
    3. -- 创建新租户 acc2,密码为 123456(在这里设置简单密码,仅做为示例讲解使用)
    4. mysql> create account acc2 admin_name 'admin' identified by '123456';
  2. 修改 MatrixOne 集群的 mo.yaml 文件,将两个 CN 组分别打上了 account:acc1account:acc2 的标签,分别对应名为 acc1acc2 的租户:

    1. metadata:
    2. name: mo
    3. namespace: mo-hn
    4. spec:
    5. + cnGroups:
    6. + - name: cn-set1
    7. + replicas: 1
    8. + cnLabels:
    9. + - key: "account"
    10. + values: ["acc1"]
    11. +
    12. + - name: cn-set2
    13. + replicas: 1
    14. + cnLabels:
    15. + - key: "account"
    16. + values: ["acc2"]
  3. 分别使用 acc1acc2 登录,登录后,您可以使用 show backend servers 检查实际登录使用了哪些 CN 组。以下日志显示不同的帐户已登录并使用了相应的 CN 组

  1. -- acc1 租户登录 MatrixOne
  2. root@HOST-10-206-134-7:~# mysql -h 10.96.1.153 -uacc1:admin -P6001 -p123456
  3. mysql: [Warning] Using a password on the command line interface can be insecure.
  4. Welcome to the MySQL monitor. Commands end with ; or \g.
  5. Your MySQL connection id is 32309
  6. Server version: 8.0.30-MatrixOne-v0.5.0 MatrixOne
  7. Copyright (c) 2000, 2023, Oracle and/or its affiliates.
  8. Oracle is a registered trademark of Oracle Corporation and/or its
  9. affiliates. Other names may be trademarks of their respective
  10. owners.
  11. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
  12. -- acc1 查看实际登录使用的 CN 组是哪些
  13. mysql> show backend servers;
  14. +--------------------------------------+-------------------------------------------------------+------------+------------------------------+
  15. | UUID | Address | Work State | Labels |
  16. +--------------------------------------+-------------------------------------------------------+------------+------------------------------+
  17. | 32333337-3966-3137-3032-613035306561 | mo-cn-set1-cn-0.mo-cn-set1-cn-headless.mo-hn.svc:6001 | Working | account:acc1;cn-set1:1,high; |
  18. +--------------------------------------+-------------------------------------------------------+------------+------------------------------+
  19. 1 row in set (0.00 sec)
  1. -- acc2 租户登录 MatrixOne
  2. root@HOST-10-206-134-7:~# mysql -h 10.96.1.153 -uacc2:admin -P6001 -p123456
  3. mysql: [Warning] Using a password on the command line interface can be insecure.
  4. Welcome to the MySQL monitor. Commands end with ; or \g.
  5. Your MySQL connection id is 32640
  6. Server version: 8.0.30-MatrixOne-v0.5.0 MatrixOne
  7. Copyright (c) 2000, 2023, Oracle and/or its affiliates.
  8. Oracle is a registered trademark of Oracle Corporation and/or its
  9. affiliates. Other names may be trademarks of their respective
  10. owners.
  11. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
  12. -- acc2 查看实际登录使用的 CN 组是哪些
  13. mysql> show backend servers;
  14. +--------------------------------------+-------------------------------------------------------+------------+--------------------------------+
  15. | UUID | Address | Work State | Labels |
  16. +--------------------------------------+-------------------------------------------------------+------------+--------------------------------+
  17. | 33663265-3234-3365-3737-333030613535 | mo-cn-set2-cn-0.mo-cn-set2-cn-headless.mo-hn.svc:6001 | Working | account:acc2;cn-set2:2,medium; |
  18. +--------------------------------------+-------------------------------------------------------+------------+--------------------------------+
  19. 1 row in set (0.00 sec)

如果一个普通租户没有对应的 CN 组,那么租户无法登录成功。例如,你如果创建一个没有 CN 组标签对应的租户 acc3,并尝试登录,会出现 no available CN server 错误。

  1. mysql> create account acc3 admin_name 'admin' identified by '123456';
  2. root@HOST-10-206-134-7:~# mysql -h 10.96.1.153 -uacc3:admin -P6001 -p123456
  3. mysql: [Warning] Using a password on the command line interface can be insecure.
  4. ERROR 1045 (28000): internal error: no available CN server
系统租户

对于系统租户,MatrixOne 将按照以下顺序自动选择合适的 CN 组进行连接:

  • 最高优先级:选择配置了 account 标签为 sys 的 CN 组。
  • 次高优先级:选择配置了其他标签,但未配置 account 标签的 CN 组。
  • 中优先级:选择未配置任何标签的 CN 组。
  • 低优先级:若以上 CN 组均不存在,则从现有 CN 组中随机选择。

根据这一原则,系统租户会优先选择专为自己保留或未被其他租户预留的 CN 组。然而,如果以上条件均不满足,系统租户可能会与其他租户共享 CN 组,从而无法确保系统租户与普通租户之间的负载隔离。

实现负载隔离

Proxy 代理使用场景是负载隔离。在许多标准业务环境中,如高并发写入、报表生成、备份和大数据导出等,传统数据库方案通常需求部署特定的实例以实现负载隔离。这种方式同时还会导致额外的数据同步负担。

MatrixOne 利用 Proxy 来实现资源组的划分,它能够灵活地将 CN 组与用户指定的负载标签结合。在负载变动的情况下,MatrixOne 能够通过软件配置调整资源组的规模,从而更好地适应变化。

以上述为例,你可以尝试将两个 CN 的负载标签分别设置为 olapoltp。然后,使用 SSB 模拟 OLTP 负载,并使用 TPCH 模拟 OLAP 负载。

Note

在进行性能测试时,你首先需要对整个集群进行扩展。

  1. metadata:
  2. name: mo
  3. namespace: mo-hn
  4. spec:
  5. + cnGroups:
  6. + - name: cn-set1
  7. + replicas: 1
  8. + cnLabels:
  9. + - key: "workload"
  10. + # 负载标签设置为 olap
  11. + values: ["olap"]
  12. +
  13. + - name: cn-set2
  14. + replicas: 1
  15. + cnLabels:
  16. + - key: "workload"
  17. + # 负载标签设置为 oltp
  18. + values: ["oltp"]

配置完集群的负载之后,可以连接到集群进行负载测试:

  1. 通过 JDBC 连接:

    在 JDBC 的连接串中指定 connectionAttributes,并设置相应的 key 和 value,key 和 value 之间用冒号 : 间隔,多个 key-value 之间用逗号 , 间隔。示例如下:

    1. jdbc:mysql://localhost:6001/test_db1?serverTimezone=UTC&connectionAttributes=workload:olap,another_key:test_value
  2. 通过 MySQL 客户端实现连接:

    通过扩展用户名(username)字段,实现使用 MySQL 客户端进行连接。在用户名(username)后添加 ?,随后的编写方式遵循 JDBC 中的 connectionAttributes 格式,与 JDBC 中的 connectionAttributes 格式不同的是,key 和 value 之间用 = 间隔,多个 key-value 之间用逗号 , 间隔,示例如下:

    1. mysql -h127.0.0.1 -uuser1?workload=olap,another_key=test_value -P6001 -pxxx