如何获得从单区域到多区域应用的零停机时间扩展

120 阅读5分钟

CockroachDB提供了一系列的功能,旨在让你的应用程序在多个地区都能轻松支持。在CockroachDB 20.1中,我们引入了一个新的功能--在线主键变更,允许你在零停机的情况下将你的应用从单区域升级到多区域。我们最近写了一些关于构建在线主键变化的技术挑战,在这篇博文中,我们将介绍一些使用案例和该功能带来的好处。

一个快速的例子

首先,使用你喜欢的方法下载CockroachDB 20.1,包括Linux、Mac或Windows的二进制文件、Docker镜像,或者直接从源码构建。

这个例子将集中在虚构的共享汽车公司MovR上,我们之前在介绍横向连接的时候已经写过。MovR是一家在全球多个城市运营的共享汽车公司。我们已经在这篇多地区的博文中详细探讨了它的模式。你也可以使用我们最近在博客中提到的新的CockroachDB演示功能,在不到5分钟的时间内尝试一下。

要使用CockroachDB演示(以及带有预填充数据的更复杂的Rides表),请输入以下命令。

./cockroach demo

这个命令将自动加载MovR表和数据。

show tables;

table_name
+----------------------------+
  promo_codes
  rides
  user_promo_codes
  users
  vehicle_location_histories
  vehicles
(6 rows)

你可以看到这个骑行表已经为多区域做了很好的设置,因为它有一个复合主键,把区域放在id前面。

show create table rides;
  table_name |                                                        create_statement
-------------+----------------------------------------------------------------------------------------------------------------------------------
  rides      | CREATE TABLE rides (
             |     id UUID NOT NULL,
             |     city VARCHAR NOT NULL,
             |     vehicle_city VARCHAR NULL,
             |     rider_id UUID NULL,
             |     vehicle_id UUID NULL,
             |     start_address VARCHAR NULL,
             |     end_address VARCHAR NULL,
             |     start_time TIMESTAMP NULL,
             |     end_time TIMESTAMP NULL,
             |     revenue DECIMAL(10,2) NULL,
             |     CONSTRAINT "primary" PRIMARY KEY (city ASC, id ASC),
             |     CONSTRAINT fk_city_ref_users FOREIGN KEY (city, rider_id) REFERENCES users(city, id),
             |     CONSTRAINT fk_vehicle_city_ref_vehicles FOREIGN KEY (vehicle_city, vehicle_id) REFERENCES vehicles(city, id),
             |     INDEX rides_auto_index_fk_city_ref_users (city ASC, rider_id ASC),
             |     INDEX rides_auto_index_fk_vehicle_city_ref_vehicles (vehicle_city ASC, vehicle_id ASC),
             |     FAMILY "primary" (id, city, vehicle_city, rider_id, vehicle_id, start_address, end_address, start_time, end_time, revenue),
             |     CONSTRAINT check_vehicle_city_city CHECK (vehicle_city = city)
             | )
(1 row)

由于我们想展示从单地区到多地区的历程,我已经修改了骑行表,将城市从主键中删除(注意:如果你想使用现有的MovR骑行表,你也可以用ALTER TABLE rides ALTER PRIMARY KEY USING COLUMNS (id ASC); )。为了在家里跟上,我们将创建并使用一个新的数据库,然后创建一个新的骑行表,如下所示。

CREATE DATABASE movr_blog;

USE movr_blog;

CREATE TABLE rides (
	id
		UUID NOT NULL,
	city
		VARCHAR NOT NULL,
	vehicle_city
		VARCHAR NULL,
	rider_id
		UUID NULL,
	vehicle_id
		UUID NULL,
	start_address
		VARCHAR NULL,
	end_address
		VARCHAR NULL,
	start_time
		TIMESTAMP NULL,
	end_time
		TIMESTAMP NULL,
	revenue
		DECIMAL(10,2) NULL
);

现在,我们想改变这个主键,所以我们需要使用下面的 alter table 语句。

ALTER TABLE rides ALTER PRIMARY KEY USING COLUMNS (city ASC, id ASC);

NOTICE: primary key changes are finalized asynchronously; further schema changes on this table may be restricted until the job completes
ALTER TABLE

Time: 189.061ms

现在在这个例子中,我们没有指向集群的负载,也没有大量的数据需要改变,所以这是一个相对快速的操作。正如我们将在下面看到的,在线模式的改变被设计为对前台活动的影响最小,因为它不会锁定表供你的客户使用。

一个比较复杂的MovR例子

让我们展示一个更复杂的例子,考虑到整个MovR数据库。我们在这个GitHub 仓库中提供了整个 MovR 工作负载。

要设置这个例子,请确保你已经安装并运行了docker。

brew install docker

你还需要安装CockroachDB 20.1

brew install cockroachdb

然后,在你的笔记本电脑上启动一个 cockroachdb 节点。

./cockroach start-single-node --insecure --host localhost --background

接下来,创建MovR数据库。

cockroach sql --insecure --host localhost -e "create database movr;"

现在,让我们为MovR数据库生成一些假数据。

docker run -it --rm cockroachdb/movr:movr-20.1-beta.20.4.1 --url "postgres://root@docker.for.mac.localhost:26257/movr?sslmode=disable" load --num-users 100 --num-rides 100 --num-vehicles 10

我们可以打开webui,在浏览器中直接访问localhost,看看发生了什么事。

http://localhost:8080/#/overview/list

我们甚至可以看到现有的表是什么样子的,比如说,骑手表。

http://localhost:8080/#/database/movr/table/rides

现在让我们把负载指向它。

docker run -it --rm cockroachdb/movr:movr-20.1-beta.20.4.2 --app-name "movr-loadgen" --url "postgres://root@docker.for.mac.localhost:26257/movr?sslmode=disable" run --multi-region

我们还可以在webui的metrics标签中看到这个负载。

http://localhost:8080/#/metrics/overview/cluster

现在,让我们把它升级为一个多区域集群。通常情况下,如果你是手工操作,你需要通过Docker运行以下命令。

docker run -it --rm cockroachdb/movr:movr-20.1-beta.20.4.1 --app-name "movr-loadgen" --url "postgres://root@docker.for.mac.localhost:26257/movr?sslmode=disable" configure-multi-region --preview-queries

[INFO] (MainThread) connected to movr database @ postgres://root@docker.for.mac.localhost:26257/movr?sslmode=disable
DDL to convert a single region database to multi-region
===primary key alters===
ALTER TABLE users ALTER PRIMARY KEY USING COLUMNS (city, id);
ALTER TABLE rides ALTER PRIMARY KEY USING COLUMNS (city, id);
ALTER TABLE vehicle_location_histories ALTER PRIMARY KEY USING COLUMNS (city, ride_id, timestamp);
ALTER TABLE vehicles ALTER PRIMARY KEY USING COLUMNS (city, id);
ALTER TABLE user_promo_codes ALTER PRIMARY KEY USING COLUMNS (city, user_id, code);
===foreign key alters===
DROP INDEX users_city_idx;
ALTER TABLE vehicles DROP CONSTRAINT fk_owner_id_ref_users;
CREATE INDEX ON vehicles (city, owner_id);
DROP INDEX vehicles_auto_index_fk_owner_id_ref_users;
DROP INDEX vehicles_city_idx;
ALTER TABLE vehicles ADD CONSTRAINT fk_owner_id_ref_users_mr FOREIGN KEY (city, owner_id) REFERENCES users (city,id);
ALTER TABLE rides DROP CONSTRAINT fk_rider_id_ref_users;
CREATE INDEX ON rides (city, rider_id);
ALTER TABLE rides ADD CONSTRAINT fk_rider_id_ref_users_mr FOREIGN KEY (city, rider_id) REFERENCES users (city,id);
ALTER TABLE rides DROP CONSTRAINT fk_vehicle_id_ref_vehicles;
CREATE INDEX ON rides (city, vehicle_id);
ALTER TABLE rides ADD CONSTRAINT fk_vehicle_id_ref_vehicles_mr FOREIGN KEY (city, vehicle_id) REFERENCES vehicles (city,id);
DROP INDEX rides_auto_index_fk_rider_id_ref_users;
DROP INDEX rides_auto_index_fk_vehicle_id_ref_vehicles;
ALTER TABLE user_promo_codes DROP CONSTRAINT fk_user_id_ref_users;
ALTER TABLE user_promo_codes ADD CONSTRAINT fk_user_id_ref_users_mr FOREIGN KEY (city, user_id) REFERENCES users (city,id);

我们已经编写了脚本,为你完成这些命令,所以你可以去掉--预览--查询来看到这个执行。


docker run -it --rm cockroachdb/movr:movr-20.1-beta.20.4.1 --app-name "movr-loadgen" --url "postgres://root@docker.for.mac.localhost:26257/movr?sslmode=disable" configure-multi-region

你可以在webui的job部分看到这些运行,或者通过运行show jobs

http://localhost:8080/#/jobs

我们也可以在webui中或通过运行show create table rides 来验证这一点的发生。

这对集群有什么影响?

回到指标表中,我们可以看到,当模式变化生效时,p99的延迟只稍微上升了一点,但我们的吞吐量没有下降。

你可以增加集群的规模,增加工作负载,并在其他方面使用MovR来尝试CockroachDB!

为你的应用程序提供未来保障

你还在寻找CockroachDB使多区域部署变得简单的其他方法吗?我们之前报道了如何利用地理分区通过跟随者读取减少多区域延迟,以及最近的《如何在CockroachDB上构建多区域应用》。

CockroachDB为开发者提供了强大的工具来创建多区域应用。但是你的应用不需要从一开始就为多区域而设计,我们也为你提供了工具,让你的应用从单区域发展到多区域。免费试用CockroachCloud 30天。