OceanBase 读写分离方案全攻略

2024年 5月 7日 23.4k 0

在企业数据库里有一种需求是读写分离,本文介绍 OB 的读写分离方案的部署和测试过程,希望可以减少分布式数据库选型时不必要的基本功能测试。读写分离听起来简单,实际内部设计还是有很多巧妙之处,刚学习完 OBCP 的 朋友们不妨也看看。

本文测试内容如下,有相应截图:

  • OCP 的安装部署
  • OB 集群部署
  • OB 只读副本部署及其只读访问测试
  • OB 只读副本和全功能副本的在线转换
  • OB 单副本备集群部署及其只读访问测试

机器准备

硬件资源

机器全部使用公有云 ECS,配置是 32c128G2T。

[root@observer00:/root/t-oceanbase-antman]# lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                32
On-line CPU(s) list:   0-31
Thread(s) per core:    2
Core(s) per socket:    16
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
<...>

[root@observer00:/root/t-oceanbase-antman]# free -g
              total        used        free      shared  buff/cache   available
Mem:            125           1         104           0          19         118
Swap:             0           0           0

[root@observer00:/root/t-oceanbase-antman]# df -h
Filesystem                     Size  Used Avail Use% Mounted on
/dev/vda1                       50G   42G  5.1G  90% /
devtmpfs                        63G     0   63G   0% /dev
tmpfs                           63G     0   63G   0% /dev/shm
tmpfs                           63G  820K   63G   1% /run
tmpfs                           63G     0   63G   0% /sys/fs/cgroup
/dev/mapper/ob_vg-ocp_home     296G  2.0G  279G   1% /home
/dev/mapper/ob_vg-docker_home  493G   73M  467G   1% /docker
/dev/mapper/ob_vg-ob_data      2.2T   85M  2.1T   1% /data/1
/dev/mapper/ob_vg-ob_log       504G   73M  479G   1% /data/log1
[root@observer00:/root/t-oceanbase-antman]#

机器初始化

机器初始化是很重要的一步,使用 OceanBase 提供的软件包t-oceanbase-antman-1.3.6-1917679.alios7.x86_64.rpm 可以做一些自动化初始工作。

这部分不再重复描述。详情请参考 https://mp.weixin.qq.com/s/Q-4ksIRFWYa4xbl4Yccw1g 以前的初始化步骤。

OCP 部署

ocp 的部署可以先参考 OceanBase 2.x 试用版安装体验——OCP 2.3 。

镜像文件准备

一共三个 docker 镜像文件,分别是 OBProxy、OCP、OceanBase。

[root@observer00:/root/t-oceanbase-antman]# ls -lrth *.gz
-rw-r--r-- 1 126593 users 404M Jan  3 22:18 obproxy173.tar.gz
-rw-r--r-- 1 root   root  688M Jan 17 14:02 ocp-all-in-one-2.5.0-x86.tar.gz
-rw-r--r-- 1 root   root  1.4G Jan 17 14:09 OB2273_x86_20201214.tar.gz
[root@observer00:/root/t-oceanbase-antman]#

加载镜像文件

[root@observer00:/root/t-oceanbase-antman]# for img in `ls *.gz`;do echo $img; docker load -i $img; done
OB2273_x86_20201214.tar.gz
<...>
Loaded image: reg.docker.alibaba-inc.com/antman/ob-docker:OB2273_x86_20201214
obproxy173.tar.gz
<...>
Loaded image: reg.docker.alibaba-inc.com/antman/obproxy:OBP173_20200603_1923
ocp-all-in-one-2.5.0-x86.tar.gz
<...>
Loaded image: reg.docker.alibaba-inc.com/oceanbase/ocp-all-in-one:2.5.0-1918031

查看镜像文件。不同版本的镜像文件在版本号上会有一点区别。注意看 tag 标签。镜像文件命名并不重要。实际版本以 tag 为准。

[root@observer00:/root/t-oceanbase-antman]# docker images
REPOSITORY                                            TAG                    IMAGE ID            CREATED             SIZE
reg.docker.alibaba-inc.com/oceanbase/ocp-all-in-one   2.5.0-1918031          2e635ca841b8        2 weeks ago         1.55GB
reg.docker.alibaba-inc.com/antman/ob-docker           OB2273_x86_20201214    4da7b6c59465        5 weeks ago         2.89GB
reg.docker.alibaba-inc.com/antman/obproxy             OBP173_20200603_1923   781b6520e237        7 months ago        1.15GB
[root@observer00:/root/t-oceanbase-antman]#

OCP部署配置文件 obcluster.conf

下面直接给出关键的几个配置.

第一次跑的时候在 /root/t-antman-oceanbase/ 下没有这个目录。执行脚本初始化一个 

[root@observer00:/root/t-oceanbase-antman]#sh init_obcluster_conf.sh
[root@observer00:/root/t-oceanbase-antman]# vim obcluster.conf
## obcluster.conf
##
SINGLE_OCP_MODE=TRUE
################################   根据环境必须修改 / MUST CHANGE ACCORDING ENVIRONMENT   ################################
############  填写机器IP和root/admin密码 / Edit Machine IP and Password Of root/admin  ############
ZONE1_RS_IP=172.23.152.220
OBSERVER01_ROOTPASS=*******
OBSERVER01_ADMINPASS=******
SSH_PORT=22


############  根据服务器CPU、内存设置容器资源编排 / Allocate Container Resources According To Server  ############
OB_docker_cpus=20
OB_docker_memory=92G
OCP_docker_cpus=6
OCP_docker_memory=16G
OBProxy_docker_cpus=2
OBProxy_docker_memory=6G


############  填写OCP各组件容器的版本信息 / Edit Docker Image, Repo And Tag of OCP Components  ############
# OB docker
docker_image_package=OB2273_x86_20201214.tar.gz
OB_image_REPO=reg.docker.alibaba-inc.com/antman/ob-docker
OB_image_TAG=OB2273_x86_20201214
# OCP docker
ocp_docker_image_package=ocp-all-in-one-2.5.0-x86.tar.gz
OCP_image_REPO=reg.docker.alibaba-inc.com/oceanbase/ocp-all-in-one
OCP_image_TAG=2.5.0-1918031
# OBPROXY docker
obproxy_docker_image_package=obproxy173.tar.gz
obproxy_image_REPO=reg.docker.alibaba-inc.com/antman/obproxy
obproxy_image_TAG=OBP173_20200603_1923

自动化安装

OCP的部署命令非常简单。只要机器环境没有问题,安装部署就是一个命令,自动过。

[root@observer00:/root/t-oceanbase-antman]# ./install.sh -i 1-
run install.sh with DEBUG=FALSE, INSTALL_STEPS=1 2 3 4 5 6 7 8 CLEAR_STEPS= CONFIG_FILE=/root/t-oceanbase-antman/obcluster.conf
[2021-01-23 15:51:01.148954] INFO [start antman API service]
LB_MODE=none
[2021-01-23 15:51:01.534776] INFO [step1: making ssh authorization, logfile: /root/t-oceanbase-antman/logs/ssh_auth.log]
[2021-01-23 15:51:04.782001] INFO [step1: ssh authorization done]
[2021-01-23 15:51:04.792041] INFO [step2: no action is required when LB_MODE=none]
[2021-01-23 15:51:04.795448] INFO [step3: check whether OBSERVER port 2881,2882 are in use or not on 172.23.152.220]
[2021-01-23 15:51:09.462947] INFO [step3: OBSERVER port 2881,2882, 2022 are idle on 172.23.152.220]
[2021-01-23 15:51:09.466502] INFO [step3: installing ob cluster, logfile: /root/t-oceanbase-antman/logs/install_ob.log]
[2021-01-23 15:51:35.760209] INFO [start container: docker run -d -it --name META_OB_ZONE_1 --net=host     -e OBCLUSTER_NAME=obcluster      -e DEV_NAME=eth0     -e ROOTSERVICE_LIST="172.23.152.220:2882:2881"     -e DATAFILE_DISK_PERCENTAGE=90     -e CLUSTER_ID=100000     -e ZONE_NAME=META_OB_ZONE_1     -e OCP_VIP=172.23.152.220     -e OCP_VPORT=8080     -e METADB_CLUSTER_NAME=obcluster     -e app.password_root=ro0T@20#Ra     -e app.password_admin=ro0T@20#Ra     -e OPTSTR="cpu_count=20,memory_limit=89G,__min_full_resource_pool_memory=1073741824,_ob_enable_prepared_statement=false,memory_limit_percentage=90"     --cpu-period 100000     --cpu-quota 2000000     --cpuset-cpus 0-19     --memory 92G     -v /home/admin/oceanbase:/home/admin/oceanbase     -v /data/log1:/data/log1     -v /data/1:/data/1     -v /backup:/backup     --restart on-failure:5     reg.docker.alibaba-inc.com/antman/ob-docker:OB2273_x86_20201214]
0dbbc671f4cbf3792067e64eade064a397f46cacabd65af63de699826c4d940c
[2021-01-23 15:51:35.971611] INFO [installing OB docker and starting OB server on 172.23.152.220, pid: 19062, log: /root/t-oceanbase-antman/logs/install_OB_docker.log and /home/admin/logs/ob-server/ inside docker]
[2021-01-23 15:51:39.090756] INFO [install_OB_docker.sh finished and reg.docker.alibaba-inc.com/antman/ob-docker:OB2273_x86_20201214 started on 172.23.152.220]
[2021-01-23 15:51:39.094245] INFO [waiting on observer ready on 172.23.152.220]
[2021-01-23 15:54:39.103957] INFO [waiting on observer ready on 172.23.152.220 for 3 Minitues]
[2021-01-23 15:55:39.114452] INFO [waiting on observer ready on 172.23.152.220 for 4 Minitues]
[2021-01-23 15:55:39.504591] INFO [observer on 172.23.152.220 is ready]
[2021-01-23 15:55:39.514450] INFO [observer installation on all hosts done]
[2021-01-23 15:55:39.521402] INFO [Now, start bootstrap on 172.23.152.220: alter system bootstrap REGION "OCP_META_REGION" ZONE "META_OB_ZONE_1" SERVER "172.23.152.220:2882"]
[2021-01-23 15:56:59.700068] INFO [bootstrap done, observer now ready]
[2021-01-23 15:56:59.710201] INFO [major_freeze start]
[2021-01-23 15:57:59.759744] INFO [major_freeze done]
[2021-01-23 15:57:59.763844] INFO [step3: installation of ob cluster done]
[2021-01-23 15:57:59.767362] INFO [step4: initializing ocp metadb, logfile: /root/t-oceanbase-antman/logs/init_metadb.log]
[2021-01-23 15:58:04.640267] INFO [step4: initialization of ocp metadb done]
[2021-01-23 15:58:04.643938] INFO [step5: check whether OCP port 8080 is in use or not on 172.23.152.220]
[2021-01-23 15:58:06.202247] INFO [step5: OCP port 8080 is idle on 172.23.152.220]
[2021-01-23 15:58:06.206098] INFO [step5: installing temporary ocp, logfile: /root/t-oceanbase-antman/logs/install_tmp_ocp.log]
[2021-01-23 15:58:26.476181] INFO [ob server is ready on host 172.23.152.220]
[2021-01-23 15:58:26.625129] INFO [init metadb: docker run --net host --workdir=/home/admin/ocp-init/src/ocp-init --entrypoint=python reg.docker.alibaba-inc.com/oceanbase/ocp-all-in-one:2.5.0-1918031 create_metadb.py 172.23.152.220 2881 root@ocp_meta X21FRlH9{@ ocp root@ocp_monitor ^I4SH6HsU@ ocp_monitor]
create_metadb.py:356: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.
  data = yaml.load(file)
<...>

[root@observer00:/root/t-oceanbase-antman]#
[root@observer00:/root/t-oceanbase-antman]# docker ps
CONTAINER ID        IMAGE                                                               COMMAND                  CREATED             STATUS              PORTS               NAMES
5333a8797e7b        reg.docker.alibaba-inc.com/oceanbase/ocp-all-in-one:2.5.0-1918031   "/usr/bin/supervisor…"   7 minutes ago       Up 7 minutes                            ocp
60bd06244095        reg.docker.alibaba-inc.com/antman/obproxy:OBP173_20200603_1923      "sh start_obproxy.sh"    8 minutes ago       Up 8 minutes                            obproxy
0dbbc671f4cb        reg.docker.alibaba-inc.com/antman/ob-docker:OB2273_x86_20201214     "/usr/bin/supervisor…"   20 minutes ago      Up 20 minutes                           META_OB_ZONE_1
[root@observer00:/root/t-oceanbase-antman]#


如果安装报错了,就把报错的步骤 回滚掉 -c 。

OB 集群部署

部署规划

目标:

  • 部署一个 1-1-1 的 OB 集群。
  • 部署一个只读副本。
  • 部署一个单副本备集群。

主机名IPREGIONIDCZone备注observer01172.23.152.221RG1IDC1ZONE_1OB 主副本observer02172.30.118.66RG1IDC2ZONE_2OB 备副本observer03172.30.118.67RG2IDC3ZONE_3OB 备副本observer04172.26.154.55RG2IDC22ZONE_4OB 只读副本observer05172.26.154.54RG3IDC4ZONE_1OB 备集群单副本

注意:这里的 REGION 和 IDC 信息都是特别设计的,后面可以看到效果。

做到后面发现这里的 IDC22 应该命名为 IDC33 更贴切一些。不过不好调整了。在实际生产环境里,IDC22 跟 IDC3 通常是同一个物理机房或者同一个城市,属于同一个 REGION。

机器资源池录入

  • 新增机型

OceanBase 读写分离方案全攻略-1

  • 新增凭据

OceanBase 读写分离方案全攻略-2图片

  • 新增机房

OceanBase 读写分离方案全攻略-3图片

  • 添加主机

OceanBase 读写分离方案全攻略-4图片

重复添加所有主机后,OCP 管理的机器资源如下:

图片OceanBase 读写分离方案全攻略-5

部署 OB 集群

注意,选机器的时候,ZONE、IDC、IP 都要跟规划一致。

OceanBase 读写分离方案全攻略-6

  • 可选:指定一些 OB 集群参数。

OceanBase 读写分离方案全攻略-7

这些参数是常用的,性能测试时会有用。不是必须的。有关参数介绍请参考:OB 开发测试建议 (中)

OceanBase 读写分离方案全攻略-8

提交后生成安装任务。

OceanBase 集群的自动化安装任务相比手动安装是更严谨一些,这符合企业级数据库运维平台的基本要求。子任务切分很细,并且有很多环境检查准备等工作。OCP 提供了图形化的进度浏览。多个节点能同时安装。

OceanBase 读写分离方案全攻略-9

OceanBase 集群的安装时间绝大部分都是这一步任务的时间。这一步是为了测试主机上 IO 的综合能力,然后生成一个文件 `/home/admin/oceanbase/etc/io_resource.conf 。

[admin@observer01:/home/admin]# ps -ef|grep ob_admin
admin     7002  6963 99 17:47 ?        00:08:40 /home/admin/oceanbase/bin/ob_admin io_bench -c /home/admin/oceanbase/etc -d /data/1/obdemo
admin    10848  5779  0 17:49 pts/0    00:00:00 grep --color=auto ob_admin
[admin@observer01:/home/admin]#

部署 OBProxy 集群

给业务部署一个 OBProxy,用于业务读写。由于测试环境我没有 VIP,所以这里集群的 IP 填写了第一个后端 OBProxy 的 IP。

OceanBase 读写分离方案全攻略-10图片

创建 OB 租户

新建 OB 的 ORALCE 租户

OCP 可以创建租户,选择兼容 MySQL 或者 ORACLE。这个细节就不重复了。

图片OceanBase 读写分离方案全攻略-11

初始化 ORACLE 租户数据

这里用 BenchmarkSQL 工具初始化 TPCC 场景数据。

vim props.ob
db=oceanbase
driver=com.alipay.oceanbase.obproxy.mysql.jdbc.Driver
conn=jdbc:oceanbase://172.30.118.66:2883/tpcc?useAffectedRows=true&emulateUnsupportedPstmts=false&characterEncoding=utf8&enableQueryTimeouts=false&useLocalSessionState=false&useLocalTransactionState=false&rewriteBatchedStatements=true&allowMultiQueries=true&socketTimeout=600000
user=tpcc@oboracle01#obdemo
password=123456

warehouses=100
loadWorkers=10

图片

OB 只读副本部署

新增一个 ZONE

在集群 obdemo的管理界面里点击“新增 Zone”,选一个机器,用于只读副本。

图片OceanBase 读写分离方案全攻略-12

新增一个只读副本

在租户里新增一个副本,类型选择“只读副本”。

OceanBase 读写分离方案全攻略-13

OB 单副本备集群部署

新建备集群

在集群 obdemo 的集群管理界面,点击“新建备集群”。

OceanBase 读写分离方案全攻略-14

OceanBase 读写分离方案全攻略-15

新建备集群的任务里面也会有 IO 测试,bootstrap 操作。搭建备集群并不是增加一个备副本,而是搭建一个独立的 OB 集群。

OceanBase 读写分离方案全攻略-16图片

新增 OBProxy

新增一个 OBProxy 访问只读副本。

目前 OCP 还不支持创建 2 个 OBProxy 集群关联到一个 OB 集群。所以这个 OBProxy 暂时只能手动创建。

OBProxy 启动的时候指定 obconfig_url 。

OceanBase 读写分离方案全攻略-17

图片

需要取这个值中的 IP 和端口部分,替换下面参数中的 IP和端口。

[admin@observer04:/opt/taobao/install/obproxy]# cd /opt/taobao/install/obproxy && bin/obproxy -p2883 -cobdemo -o "obproxy_config_server_url=http://172.23.152.220:8080/services?Action=GetObProxyConfig&User_ID=alibaba-inc&uid=ocpmaster,proxy_idc_name=IDC22"
bin/obproxy -p2883 -cobdemo -o obproxy_config_server_url=http://172.23.152.220:8080/services?Action=GetObProxyConfig&User_ID=alibaba-inc&uid=ocpmaster,proxy_idc_name=IDC22
listen port: 2883
cluster_name: obdemo
optstr: obproxy_config_server_url=http://172.23.152.220:8080/services?Action=GetObProxyConfig&User_ID=alibaba-inc&uid=ocpmaster,proxy_idc_name=IDC22

[admin@observer04:/opt/taobao/install/obproxy]# ps -ef|grep obproxy
admin     6761     1 30 19:31 ?        00:00:01 bin/obproxy -p2883 -cobdemo -o obproxy_config_server_url=http://172.23.152.220:8080/services?Action=GetObProxyConfig&User_ID=alibaba-inc&uid=ocpmaster,proxy_idc_name=IDC22
admin     7192 31451  0 19:31 pts/0    00:00:00 grep --color=auto obproxy
[admin@observer04:/opt/taobao/install/obproxy]#

注意:备副本的 OBPROXY 我在启动的时候特地指定了 proxy_idc_name=IDC22这个参数。当通过这个 OBPROXY 发起弱一致性读时,会按下面顺序路由:

  • 同一个 IDC 下的备副本所在的 OBSERVER 节点。
  • 同一个 REGION 下的其他 IDC 下的备副本所在的 OBSERVER 节点。
  • 其他 REGION 下的备副本所在的 OBSERVER 节点

集群拓扑

  • 主集群视角的拓扑

OceanBase 读写分离方案全攻略-18图片

  • 备集群视角的拓扑

OceanBase 读写分离方案全攻略-19图片

也可以在集群里通过 SQL 确认:

select t1.name resource_pool_name, t3.unit_id, t2.`name` unit_config_name, t2.max_cpu, t2.min_cpu, round(t2.max_memory/1024/1024/1024) max_mem_gb, round(t2.min_memory/1024/1024/1024) min_mem_gb, t3.unit_id, t3.zone, concat(t3.svr_ip,':',t3.`svr_port`) observer,t4.tenant_id, t4.tenant_name
from __all_resource_pool t1 join __all_unit_config t2 on (t1.unit_config_id=t2.unit_config_id)
    join __all_unit t3 on (t1.`resource_pool_id` = t3.`resource_pool_id`)
    left join __all_tenant t4 on (t1.tenant_id=t4.tenant_id)
order BY t1.tenant_id ,t1.`resource_pool_id`, t2.`unit_config_id`, t3.unit_id
;

SELECT * FROM __all_zone WHERE name IN ('region','idc');

图片

图片

OceanBase 读写分离方案全攻略-20

OceanBase 读写分离方案全攻略-21

测试验证

确认集群租户资源分布

这个不是必须的。只是顺道展示一下 OCP 新增的功能。也方便大家对只读副本的理解。

OceanBase 读写分离方案全攻略-22图片

确认表(分区)的位置

以表bmsql_item为例。这是个单表。

OceanBase 读写分离方案全攻略-23图片

运行下面 SQL 查询这个表分区的位置

SELECT  t.tenant_id, a.tenant_name, d.database_name, t.table_name,  tg.tablegroup_name , t.part_num , t2.partition_id, t2.ZONE, t2.svr_ip, t2.ROLE, t2.data_size
    , a.primary_zone      , IF(t.locality = '' OR t.locality IS NULL, a.locality, t.locality) AS locality   
FROM oceanbase.__all_tenant AS a  
    JOIN oceanbase.__all_virtual_database AS d ON ( a.tenant_id = d.tenant_id  ) 
    JOIN oceanbase.__all_virtual_table AS t  ON (t.tenant_id = d.tenant_id AND t.database_id = d.database_id)   
    JOIN oceanbase.__all_virtual_meta_table t2 ON (t.tenant_id = t2.tenant_id AND (t.table_id=t2.table_id OR t.tablegroup_id=t2.table_id)  AND t2.ROLE IN (1,2) )
    LEFT JOIN oceanbase.__all_virtual_tablegroup AS tg ON (t.tenant_id = tg.tenant_id and  t.tablegroup_id = tg.tablegroup_id) 
WHERE a.tenant_id IN (1001 ) AND  t.table_type IN (3)   AND d.database_name LIKE '%TPCC%'
AND t.table_name IN ('BMSQL_ITEM')
;

OceanBase 读写分离方案全攻略-24图片

从图中看表bmsql_item的主副本在 221 上,其他节点都是备副本。

确认 SQL 路由节点的方法

OceanBase 里所有的 SQL 都会在sys租户的内部视图gv$sql_audit里记录。这个对排查问题非常方便。

下面语句是根据 SQL 文本查询执行信息

SELECT /*+ read_consistency(weak) ob_querytimeout(100000000) */ substr(usec_to_time(request_time),1,19) request_time_, s.svr_ip, s.client_Ip, s.sid, s.plan_type,  s.query_sql, s.affected_rows, s.return_rows, s.ret_code
FROM gv$sql_audit s
WHERE  s.tenant_id=1001 
 AND user_name LIKE '%TPCC%'AND query_sql LIKE '%TEST_RO%'
ORDER BY request_time DESC
LIMIT 10;

OceanBase 读写分离方案全攻略-25

其中

  • client_ip 是 SQL 在 OceanBase 集群视角的客户端 IP。如果客户端是通过 OBPROXY 访问 OB,那么这个地址通常就是 OBPROXY 的地址。
  • svr_ip 是 SQL 被路由到 OceanBase 集群的节点 IP。通常是 SQL 访问分区的主副本 IP,不过有时候也不是。这个跟 OBPROXY 路由策略有关。这个以后可以独立成篇去介绍。
  • plan_type 是 SQL 的执行类型。1:表示在该节点(指svr_ip)本机执行;2:表示是发送到其他节点远程执行。发送到哪个节点这里看不到(通常是指发送到分区主副本节点);3 表示是这个 SQL 是个分布式执行计划,会涉及到多个分区。有可能这些分区还跨节点了。

所以,上图的解释是这个 SQL 从 55 这个 IP 路由到 55 这个节点。由于访问的表的主副本不在这个节点,所以又再次路由到其他节点(实际是主副本所在节点,即 221 )。

业务读写验证

前面的 TPCC 场景的数据初始化使用的就是第一个 OBProxy 集群,包含读写操作。

首先我们看有一个实时读写的单表 SQL 会被路由到哪个节点。测试 SQL 类似

select /*+ test_rw */ count(*) cnt from bmsql_item\G

注意:/*+ */ 是 SQL 的注释语法,也是 HINT 语法。 test_rw不是标准的 SQL HINT,所以会被 SQL 引擎忽略。写在这里只是为了标记这个 SQL,方面后面从 SQL 审计视图里定位到这个 SQL。

为了简化情况,让下面的测试案例可以复现。请严格按照测试方法做。每次执行 SQL 时都重新连接。不要复用老的连接。

开始测试,通过 observer02 上的 OBPROXY 连接集群看看。然后换 observer01 上的 OBPROXY 连接集群看看。

[root@observer00:/root]# obclient -hobserver02 -utpcc@oboracle01#obdemo -P2883 -p123456 -s -e "select /*+ test_rw_10 */ count(*) cnt from bmsql_item\G "
obclient: [Warning] Using a password on the command line interface can be insecure.
*************************** 1. row ***************************
CNT: 100000

[root@observer00:/root]# obclient -hobserver01 -utpcc@oboracle01#obdemo -P2883 -p123456 -s -e "select /*+ test_rw_10 */ count(*) cnt from bmsql_item\G "
obclient: [Warning] Using a password on the command line interface can be insecure.
*************************** 1. row ***************************
CNT: 100000

看 SQL 审计结果

OceanBase 读写分离方案全攻略-26图片

所以,无论从哪个 OBPROXY 链接 OB 集群,通常单表 SQL 最后都会被路由到该表主副本所在的节点。这种路由规则叫强一致性读

本项验证的目的已经达到。下面演示弱一致性读的路由规则。弱一致性读只允许就近读取备副本。需要指定 HINT (read_consistency(weak) 或者在会话级别设置。

obclient -hobserver01 -utpcc@oboracle01#obdemo -P2883 -p123456  -s -e "set session ob_read_consistency=weak; select /*+ test_ro_41 */ count(*) cnt from bmsql_item\G"
obclient -hobserver01 -utpcc@oboracle01#obdemo -P2883 -p123456  -s -e "set session ob_read_consistency=weak; select /*+ test_ro_41 */ count(*) cnt from bmsql_item\G"
obclient -hobserver02 -utpcc@oboracle01#obdemo -P2883 -p123456  -s -e "set session ob_read_consistency=weak; select /*+ test_ro_41 */ count(*) cnt from bmsql_item\G"
obclient -hobserver02 -utpcc@oboracle01#obdemo -P2883 -p123456  -s -e "set session ob_read_consistency=weak; select /*+ test_ro_41 */ count(*) cnt from bmsql_item\G"

OceanBase 读写分离方案全攻略-27

观察 SQL 路由信息

OceanBase 读写分离方案全攻略-28

注意: SQL 审计视图按时间顺序是从下往上看。

多测试可以看出,如果选择备副本所在节点的 OBPROXY 连接 OB 集群,它就随机转发给备副本的 OBSERVER 节点了,然后 SQL 也是本地执行(plan_type=1)。如果选择主副本所在节点的 OBPROXY 连接 OB 集群,它就随机转发给所有的 的 OBSERVER 节点。

除了用 SQL HINT 外,还有个办法就是通过 SESSION 变量来设置弱一致性读

[root@observer00:/root]# obclient -hobserver01 -utpcc@oboracle01#obdemo -P2883 -p123456  -s -e "set session ob_read_consistency=weak; select /*+ test_rw_14 */ count(*) cnt from bmsql_item\G"
obclient: [Warning] Using a password on the command line interface can be insecure.
*************************** 1. row ***************************
CNT: 100000
[root@observer00:/root]# obclient -hobserver02 -utpcc@oboracle01#obdemo -P2883 -p123456  -s -e "set session ob_read_consistency=weak; select /*+ test_rw_14 */ count(*) cnt from bmsql_item\G"
obclient: [Warning] Using a password on the command line interface can be insecure.
*************************** 1. row ***************************
CNT: 100000
[root@observer00:/root]#

OceanBase 读写分离方案全攻略-29

弱一致性读通常用于少量的读写分离场景。对于大量的读写分离需求,或者为了绝对不影响主副本的读写,那推荐使用只读副本。

只读副本访问验证

只读副本主要用于读写分离场景。对于一些业务上能接受些许延时的查询,可以访问“只读副本”减轻主副本的压力。只读副本的访问也必须使用弱一致性读

下面就验证只读副本的访问是否真的会路由到只读副本的节点。为了便于理解,我加了一些强一致性读进行对比。

obclient -h172.23.152.221 -utpcc@oboracle01#obdemo -P2883 -p123456  -s -e "select /*+ test_ro_28 */ count(*) cnt from bmsql_item\G"

obclient -h172.23.152.221 -utpcc@oboracle01#obdemo -P2883 -p123456  -s -e "set session ob_read_consistency=weak; select /*+ test_ro_28 */ count(*) cnt from bmsql_item\G"

obclient -h172.26.154.55 -utpcc@oboracle01#obdemo -P2883 -p123456  -s -e "select /*+ test_ro_28 */ count(*) cnt from bmsql_item\G"

obclient -h172.26.154.55 -utpcc@oboracle01#obdemo -P2883 -p123456  -s -e "set session ob_read_consistency=weak; select /*+ test_ro_28 */ count(*) cnt from bmsql_item\G"

图片

OceanBase 读写分离方案全攻略-30图片

OceanBase 读写分离方案全攻略-31

注意: SQL 审计视图按时间顺序是从下往上看。

从上图可以看出,发往只读副本所在节点的 OBPROXY(这个 OBPROXY 启动时指定了特别的 IDC 参数,见前面说明)的弱一致性读,会路由到同一个 IDC 下的 OBSERVER 节点(也是本机节点,测试环境受限就这么巧),而不是随机到其他备副本节点。这就是只读副本的目的。

同时也看出,发往只读副本所在节点的 OBPROXY 的强一致性读,还是会被路由到主副本所在的节点。这个就是 OB 的只读副本跟其他分布式数据库主从读写分离方案最大的不同。OB 绝对不会出现错误的写了只读副本(双写)。

然而 OB 更特殊的优势还在只读副本故障时的情形。

只读副本故障后验证

通常模拟故障就是直接登录节点 杀掉 OBSERVER 进程。最近 OCP 增加了停止节点的功能,这里就顺便演示一下。(以前有客户吐槽 OB 不能停机,现在可以了 😆)

OceanBase 读写分离方案全攻略-32

图片

同样的,停 OBSERVER 节点也会生成一个任务,并且拆分为很多原子任务。这个过程会比我直接 KILL 节点要长很多。这是因为 OCP 选择了一种严谨的稳妥的步骤。

OceanBase 读写分离方案全攻略-33

确认节点状态

OceanBase 读写分离方案全攻略-34

select a.zone,concat(a.svr_ip   ,':',a.svr_port) observer, usec_to_time(b.last_offline_time) last_offline_time, usec_to_time(b.start_service_time) start_service_time, b.status, b.with_rootserver 
from __all_virtual_server_stat a     join __all_server b on (a.svr_ip=b.svr_ip and a.svr_port=b.svr_port)
order by a.ZONE, a.svr_ip
;

OceanBase 读写分离方案全攻略-35

再跑弱一致性验证

obclient -h172.23.152.221 -utpcc@oboracle01#obdemo -P2883 -p123456  -s -e "select /*+ test_ro_29 */ count(*) cnt from bmsql_item\G"

obclient -h172.23.152.221 -utpcc@oboracle01#obdemo -P2883 -p123456  -s -e "set session ob_read_consistency=weak; select /*+ test_ro_29 */ count(*) cnt from bmsql_item\G"

obclient -h172.26.154.55 -utpcc@oboracle01#obdemo -P2883 -p123456  -s -e "select /*+ test_ro_29 */ count(*) cnt from bmsql_item\G"

obclient -h172.26.154.55 -utpcc@oboracle01#obdemo -P2883 -p123456  -s -e "set session ob_read_consistency=weak; select /*+ test_ro_29 */ count(*) cnt from bmsql_item\G"

OceanBase 读写分离方案全攻略-36

从图中可以看出,当只读副本不可访问时,原弱一致性读的 SQL 会被路由到同一个 REGION(RG2)的其他 IDC(IDC3) OBSERVER 节点。

也就是说即使只读副本故障了,那些只读查询业务也不会受影响(OBPROXY 会迅速把路由切换到其他候选的备副本所在 OBSERVER 节点)。这点也是 OB 跟其他分布式数据库中间件读写分离最大的不同。尽管后者也可以通过高可用 agent 去判断只读实例故障然后更改各个备实例的读写权重。读写权重那个设置是全局层面的,无法按业务切分。

只读副本跟全功能备副本之间的在线转换

OceanBase 更特别的地方就是只读副本跟全功能副本可以在线转换。

图片

OceanBase 读写分离方案全攻略-37

上图是编辑Zone3 的全功能副本,改为只读副本。也可以改 Zone4 的只读副本为全功能副本。基本上 1 分钟就生效。

任务图如下:

OceanBase 读写分离方案全攻略-38

最终结果如下:

OceanBase 读写分离方案全攻略-39

只读副本和全功能副本的在线转换这个能力,通常用于 OceanBase 集群在线跨机房跨城市搬迁。支付宝每年双11 大促前后常做这种在线搬迁。

备集群的访问

OB 现在也支持主备集群架构(DATAGUARD)。备集群的使用详情以后再介绍,这里只展示一下备集群的访问。

首先备集群的访问跟主集群一样,只是集群名字后面多了一个 :2

OceanBase 读写分离方案全攻略-40

上图: obdemo:1是主集群,obdemo:2是备集群。

备集群访问方式:

obclient -h172.26.154.55 -utpcc@oboracle01#obdemo:2 -P2883 -p123456  -s -e "set session ob_read_consistency=weak; select /*+ test_ro_30 */ count(*) cnt from bmsql_item\G"

obclient -h172.26.154.55 -utpcc@oboracle01#obdemo:2 -P2883 -p123456  -s -e "select /*+ test_ro_30 */ count(*) cnt from bmsql_item\G"

OceanBase 读写分离方案全攻略-41图片

注意:备集群只能读不能写,并且这个读必须是弱一致性读

通常主集群的任意一个 OBPROXY 也可以访问备集群。

下面是上面 SQL 在备集群的 SQL 审计视图里的路由信息。

OceanBase 读写分离方案全攻略-42

总结

综上所述,OB 的读写分离有三种方案:

  • 三副本或者五副本架构下,个别 SQL 通过弱一致性读 HINT 或者会话设置,就近只读备副本。
  • 三副本或五副本架构下,额外增加一个或多个只读副本,为只读副本配置单独的 OBPROXY ,只读业务走这个 OBPROXY 专门访问只读副本。
  • 为 OB 集群搭建一个备集群,可以是单副本或者三副本。只读业务专门访问备集群。

至于要选择哪种方案呢,还是要看“读写分离”的目的。想在什么范围内隔离只读查询对读写业务的影响,决定了选择哪种方案更合适。

OB 读写分离方案的优势有两点:

  • 无论什么状况都不用担心误写了“备副本或只读副本”,因为它不支持写,写操作会被路由到主副本。(当然备集群那个例外,不能跨集群路由)。
  • 无论什么时候都不用担心“备副本或只读副本”故障了,因为 OBPROXY会就近路由到其他备副本。(当然单副本备集群不能,如果要防范这个风险,就搭建三副本备集群就行,自身有高可用)。

用惯了 ORACLE 的 ADG 或者 MySQL 的主从读写分离的,可能会觉得 OB 的读写分离方案复杂。这个就需要转变观念了。读写分离方案严格的说要考虑各种异常情况,OB 把这些异常都做到内部去了,但对用户使用是极其方便的,对运维的工作也是很友好的。当企业的数据库机器规模成百上千后,企业级的自动化运维平台应该长什么样呢?命令行下脚本运维肯定是不行,自动化任务失败率过高时也是不行。

小提示:仅仅通过 OCP 完成只读副本和备集群搭建还不算真正掌握这个能力,其背后具体的操作步骤(尤其是 SQL)才是关键,感兴趣的朋友,可以在任务列表里下载这些任务的日志进行详细研究。 HAVE FUN 😆!

更多文章请搜索个人公众号:OceanBase技术闲谈

相关文章

pt-kill工具的使用
pt-ioprofile工具包的使用
数据库管理-第216期 Oracle的高可用-01(20240703)
DBMS_REPAIR EXAMPLE SCRIPT WITH PARTITION
数据库事务的四大特性: ACID 
使用BBED修复损坏的SYSTEM文件头

发布评论