CLOVER🍀

That was when it all began.

LocalStackの提供するAWS CLIを使って、LocalStackを操作する

これは、なにをしたくて書いたもの?

LocalStackでAWS CLIを扱う時、--endpoint-url=...と指定する必要があるのが面倒です。

awsコマンドを使う時に、常に--endpoint-url=...となるようにエイリアスでもつけようかなと思っていたのですが、
LocalStackが提供しているAWS CLIを使うと良さそうなので使ってみました。

GitHub - localstack/awscli-local: 💲 "awslocal" - Thin wrapper around the "aws" command line interface for use with LocalStack

環境

今回の環境は、こちら。LocalStackも、LocalStackの提供するAWS CLIも、pipでインストールします。

$ python3 -V
Python 3.8.10


$ pip3 -V
pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8)

LocalStackの提供するAWS CLIは、あくまで本家のAWS CLIのラッパーであるのでAWS CLI本体が必要です。

今回使うのはこちら。

$ aws --version
aws-cli/2.2.35 Python/3.8.8 Linux/5.4.0-81-generic exe/x86_64.ubuntu.20 prompt/off

LocalStackをインストール、起動する

まずはLocalStackがないと始まらないのでインストールします。

$ pip3 install localstack==0.12.17.5

バージョン。

$ localstack --version
0.12.17.5

起動。

$ localstack start

     __                     _______ __             __
    / /   ____  _________ _/ / ___// /_____ ______/ /__
   / /   / __ \/ ___/ __ `/ /\__ \/ __/ __ `/ ___/ //_/
  / /___/ /_/ / /__/ /_/ / /___/ / /_/ /_/ / /__/ ,<
 /_____/\____/\___/\__,_/_//____/\__/\__,_/\___/_/|_|

 💻 LocalStack CLI 0.12.17.5

[16:24:06] starting LocalStack in Docker mode 🐳                                                                                                               localstack.py:103
──────────────────────────────────────────────────────────────── LocalStack Runtime Log (press CTRL-C to quit) ─────────────────────────────────────────────────────────────────
['docker', 'run', '-it', '-e', 'TEST_AWS_ACCOUNT_ID=000000000000', '-e', 'DEFAULT_REGION=us-east-1', '-e', 'LOCALSTACK_HOSTNAME=localhost', '-e', 'DOCKER_HOST=unix:///var/run/docker.sock', '-e', 'HOST_TMP_FOLDER=/tmp/localstack', '--rm', '--privileged', '--name', 'localstack_main', '-p', '127.0.0.1:8080:8080', '-p', '127.0.0.1:4566:4566', '-p', '127.0.0.1:4571:4571', '-v', '/tmp/localstack:/tmp/localstack', '-v', '/var/run/docker.sock:/var/run/docker.sock', 'localstack/localstack']
Waiting for all LocalStack services to be ready
2021-09-04 07:24:07,601 CRIT Supervisor is running as root.  Privileges were not dropped because no user is specified in the config file.  If you intend to run as root, you can set user=root in the config file to avoid this message.
2021-09-04 07:24:07,604 INFO supervisord started with pid 15
2021-09-04 07:24:08,606 INFO spawned: 'infra' with pid 21
(. .venv/bin/activate; exec bin/localstack start --host)

     __                     _______ __             __
    / /   ____  _________ _/ / ___// /_____ ______/ /__
   / /   / __ \/ ___/ __ `/ /\__ \/ __/ __ `/ ___/ //_/
  / /___/ /_/ / /__/ /_/ / /___/ / /_/ /_/ / /__/ ,<
 /_____/\____/\___/\__,_/_//____/\__/\__,_/\___/_/|_|

 💻 LocalStack CLI 0.12.17.5

[07:24:09] starting LocalStack in host mode 💻                 localstack.py:101
──────────────── LocalStack Runtime Log (press CTRL-C to quit) ─────────────────
2021-09-04 07:24:10,539 INFO success: infra entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

LocalStack version: 0.12.17.5
LocalStack Docker container id: efec1972ae42
LocalStack build date: 2021-09-03
LocalStack build git hash: 484d9d20

Waiting for all LocalStack services to be ready
Starting edge router (https port 4566)...
Starting mock ACM service on http port 4566 ...
2021-09-04T07:24:14:INFO:localstack.multiserver: Starting multi API server process on port 57135
[2021-09-04 07:24:14 +0000] [22] [INFO] Running on https://0.0.0.0:4566 (CTRL + C to quit)
2021-09-04T07:24:14:INFO:hypercorn.error: Running on https://0.0.0.0:4566 (CTRL + C to quit)
[2021-09-04 07:24:14 +0000] [22] [INFO] Running on http://0.0.0.0:57135 (CTRL + C to quit)
2021-09-04T07:24:14:INFO:hypercorn.error: Running on http://0.0.0.0:57135 (CTRL + C to quit)
Starting mock API Gateway service on http port 4566 ...
Starting mock CloudFormation service on http port 4566 ...
Starting mock Config Service service on http port 4566 ...
Starting mock CloudWatch service on http port 4566 ...
Starting mock DynamoDB service on http port 4566 ...
Starting mock DynamoDB Streams service on http port 4566 ...
Starting mock EC2 service on http port 4566 ...
Starting mock ES service on http port 4566 ...
Starting mock Firehose service on http port 4566 ...
Starting mock IAM service on http port 4566 ...
Starting mock STS service on http port 4566 ...
Starting mock Kinesis service on http port 4566 ...
Starting mock KMS service on http port 4566 ...
Starting mock Lambda service on http port 4566 ...
Starting mock CloudWatch Logs service on http port 4566 ...
Starting mock Redshift service on http port 4566 ...
Starting mock Route53 service on http port 4566 ...
Starting mock S3 service on http port 4566 ...
Starting mock Secrets Manager service on http port 4566 ...
Starting mock SES service on http port 4566 ...
Starting mock SNS service on http port 4566 ...
Starting mock SQS service on http port 4566 ...
Starting mock SSM service on http port 4566 ...
Starting mock Cloudwatch Events service on http port 4566 ...
Starting mock StepFunctions service on http port 4566 ...
Starting mock SWF service on http port 4566 ...
Starting mock Resource Groups Tagging API service on http port 4566 ...
Starting mock Resource Groups API service on http port 4566 ...
Starting mock Support service on http port 4566 ...
Waiting for all LocalStack services to be ready
Ready.
2021-09-04T07:24:24:INFO:bootstrap.py: Execution of "start_api_services" took 9440.04ms

awscli-localをインストールする

続けて、LocalStackの提供するAWS CLIをインストールします。

$ pip3 install awscli-local==0.15

これで、awslocalというコマンドが使えるようになります。

試しに、S3バケットを操作してみましょう。

バケットの作成。

$ awslocal s3 mb s3://test-bucket
make_bucket: test-bucket

ファイルを作成して

$ echo 'Hello World' > file.txt

アップロード。

$ awslocal s3 cp file.txt s3://test-bucket
upload: ./file.txt to s3://test-bucket/file.txt                   

確認。

$ awslocal s3 ls test-bucket
2021-09-04 16:31:49         12 file.txt


$ awslocal s3 cp s3://test-bucket/file.txt -
Hello World

OKそうですね。

LocalStackの提供するAWS CLIの正体

最初にも書きましたが、LocalStackの提供するAWS CLIは、本家のAWS CLIのラッパーです。

というか、AWS CLIそのものを外部プロセスで起動しようとします。

awscli-local/awslocal at 53876fbb7dcc75868402cc5593ab36db87c4c66d · localstack/awscli-local · GitHub

https://github.com/localstack/awscli-local/blob/53876fbb7dcc75868402cc5593ab36db87c4c66d/bin/awslocal#L63-L65

このため、AWS CLIがインストールされていないとプロセスの起動に失敗します。

Traceback (most recent call last):
  File "/path/to/bin/awslocal", line 93, in main
    raise
RuntimeError: No active exception to reraise

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/path/to/bin/awslocal", line 272, in <module>
    main()
  File "/path/to/bin/awslocal", line 96, in main
    return run_as_separate_process()
  File "/path/to/bin/awslocal", line 169, in run_as_separate_process
    run(cmd_args, env_dict)
  File "/path/to/bin/awslocal", line 63, in run
    process = subprocess.Popen(
  File "/usr/lib/python3.8/subprocess.py", line 858, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/lib/python3.8/subprocess.py", line 1704, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'aws'

Bash Completionを有効にする

これでawslocalコマンドが使えるようになりましたが、このままだとBash Completion(コマンド補完)が効きません。

というわけで、awslocalコマンドでも効くようにしておきます。

$ complete -C `which aws_completer` awslocal

これで、コマンド補完ができるようになりました、と。

$ awslocal s3 
cp       ls       mb       mv       presign  rb       rm       sync     website 

CockroachDBで、データがどのノードに割り当てられているか確認する

これは、なにをしたくて書いたもの?

CockroachDBで保持しているデータが、どのノードに配置されているかって見れるのかな?と思いまして。

確認してみることにしました。

環境

今回の環境は、こちら。

$ cockroach --version
cockroach version details:
Build Tag:        v21.1.8
Build Time:       2021/08/30 13:41:17
Distribution:     CCL
Platform:         linux amd64 (x86_64-unknown-linux-gnu)
Go Version:       go1.15.14
C Compiler:       gcc 6.5.0
Build Commit ID:  57b7968be0e1c8e6cb1523ab01df886afef2a2ea
Build Type:       release
(use 'cockroach version --build-tag' to display only the build tag)

CockroachDBは全部で5ノード用意します。

SSLTLS証明書が格納されたディレクトリは$CERTS_DIR環境変数で指し、admin権限を付与したmyuserという
ユーザーで操作するものとします。

また、APIで操作する時のセッショントークンは$SESSION_TOKENという環境変数に格納されているものとします。

クラスタを構成するノードは、こんな感じです。

$ curl -s -H "X-Cockroach-API-Session: $SESSION_TOKEN" --cacert $CERTS_DIR/ca.crt https://localhost:8080/api/v2/nodes/ | jq '.nodes[] | "node_id: " + (.node_id|tostring) + ", address: " + .address.address_field + ", liveness_status: " + (.liveness_status|tostring)'
"node_id: 1, address: node1:26257, liveness_status: 3"
"node_id: 2, address: node3:26257, liveness_status: 3"
"node_id: 3, address: node4:26257, liveness_status: 3"
"node_id: 4, address: node5:26257, liveness_status: 3"
"node_id: 5, address: node2:26257, liveness_status: 3"

f:id:Kazuhira:20210903223714p:plain

データをロードする

データの配置状況を確認するにも、データがないと始まらないのでcockroach workload initコマンドで用意することにします。

テーブルの構成と数から、movrを使うことにしました。

$ cockroach workload init movr "postgresql://myuser@localhost:26257?sslcert=$CERTS_DIR/client.myuser.crt&sslkey=$CERTS_DIR/client.myuser.key&sslmode=verify-full&sslrootcert=$CERTS_DIR/ca.crt"
I210903 13:37:27.634532 1 workload/workloadsql/dataload.go:146  [-] 1  imported users (0s, 50 rows)
I210903 13:37:27.804760 1 workload/workloadsql/dataload.go:146  [-] 2  imported vehicles (0s, 15 rows)
I210903 13:37:28.047972 1 workload/workloadsql/dataload.go:146  [-] 3  imported rides (0s, 500 rows)
I210903 13:37:28.653149 1 workload/workloadsql/dataload.go:146  [-] 4  imported vehicle_location_histories (1s, 1000 rows)
I210903 13:37:28.970768 1 workload/workloadsql/dataload.go:146  [-] 5  imported promo_codes (0s, 1000 rows)
I210903 13:37:28.976710 1 workload/workloadsql/workloadsql.go:113  [-] 6  starting 8 splits
I210903 13:37:31.854851 1 workload/workloadsql/workloadsql.go:113  [-] 7  starting 8 splits
I210903 13:37:33.376894 1 workload/workloadsql/workloadsql.go:113  [-] 8  starting 8 splits

コマンドが完了したら、ログイン。

$ cockroach sql --certs-dir=$CERTS_DIR --user myuser --database movr
#
# Welcome to the CockroachDB SQL shell.
# All statements must be terminated by a semicolon.
# To exit, type: \q.
#
# Server version: CockroachDB CCL v21.1.8 (x86_64-unknown-linux-gnu, built 2021/08/30 13:41:17, go1.15.14) (same version as client)
# Cluster ID: e167a27b-e94e-4ce5-a312-e120f44ae619
#
# Enter \? for a brief introduction.
#
myuser@:26257/movr> 

少し待っていると、データが統計情報に反映されます。

myuser@:26257/movr> \d
  schema_name |         table_name         | type  | owner  | estimated_row_count | locality
--------------+----------------------------+-------+--------+---------------------+-----------
  public      | promo_codes                | table | myuser |                1000 | NULL
  public      | rides                      | table | myuser |                 500 | NULL
  public      | user_promo_codes           | table | myuser |                   0 | NULL
  public      | users                      | table | myuser |                  50 | NULL
  public      | vehicle_location_histories | table | myuser |                1000 | NULL
  public      | vehicles                   | table | myuser |                  15 | NULL
(6 rows)

Time: 25ms total (execution 25ms / network 0ms)

データが入っているテーブルの定義は、こんな感じです。

myuser@:26257/movr> \d
  schema_name |         table_name         | type  | owner  | estimated_row_count | locality
--------------+----------------------------+-------+--------+---------------------+-----------
  public      | promo_codes                | table | myuser |                1000 | NULL
  public      | rides                      | table | myuser |                 500 | NULL
  public      | user_promo_codes           | table | myuser |                   0 | NULL
  public      | users                      | table | myuser |                  50 | NULL
  public      | vehicle_location_histories | table | myuser |                1000 | NULL
  public      | vehicles                   | table | myuser |                  15 | NULL
(6 rows)

Time: 27ms total (execution 27ms / network 0ms)

myuser@:26257/movr> 
myuser@:26257/movr> 
myuser@:26257/movr> \d
  schema_name |         table_name         | type  | owner  | estimated_row_count | locality
--------------+----------------------------+-------+--------+---------------------+-----------
  public      | promo_codes                | table | myuser |                1000 | NULL
  public      | rides                      | table | myuser |                 500 | NULL
  public      | user_promo_codes           | table | myuser |                   0 | NULL
  public      | users                      | table | myuser |                  50 | NULL
  public      | vehicle_location_histories | table | myuser |                1000 | NULL
  public      | vehicles                   | table | myuser |                  15 | NULL
(6 rows)

Time: 25ms total (execution 25ms / network 0ms)

myuser@:26257/movr> \d promo_codes
    column_name   | data_type | is_nullable | column_default | generation_expression |  indices  | is_hidden
------------------+-----------+-------------+----------------+-----------------------+-----------+------------
  code            | VARCHAR   |    false    | NULL           |                       | {primary} |   false
  description     | VARCHAR   |    true     | NULL           |                       | {}        |   false
  creation_time   | TIMESTAMP |    true     | NULL           |                       | {}        |   false
  expiration_time | TIMESTAMP |    true     | NULL           |                       | {}        |   false
  rules           | JSONB     |    true     | NULL           |                       | {}        |   false
(5 rows)

Time: 39ms total (execution 39ms / network 0ms)

myuser@:26257/movr> \d rides
   column_name  |   data_type   | is_nullable | column_default | generation_expression |                                          indices                                           | is_hidden
----------------+---------------+-------------+----------------+-----------------------+--------------------------------------------------------------------------------------------+------------
  id            | UUID          |    false    | NULL           |                       | {primary,rides_auto_index_fk_city_ref_users,rides_auto_index_fk_vehicle_city_ref_vehicles} |   false
  city          | VARCHAR       |    false    | NULL           |                       | {primary,rides_auto_index_fk_city_ref_users,rides_auto_index_fk_vehicle_city_ref_vehicles} |   false
  vehicle_city  | VARCHAR       |    true     | NULL           |                       | {rides_auto_index_fk_vehicle_city_ref_vehicles}                                            |   false
  rider_id      | UUID          |    true     | NULL           |                       | {rides_auto_index_fk_city_ref_users}                                                       |   false
  vehicle_id    | UUID          |    true     | NULL           |                       | {rides_auto_index_fk_vehicle_city_ref_vehicles}                                            |   false
  start_address | VARCHAR       |    true     | NULL           |                       | {}                                                                                         |   false
  end_address   | VARCHAR       |    true     | NULL           |                       | {}                                                                                         |   false
  start_time    | TIMESTAMP     |    true     | NULL           |                       | {}                                                                                         |   false
  end_time      | TIMESTAMP     |    true     | NULL           |                       | {}                                                                                         |   false
  revenue       | DECIMAL(10,2) |    true     | NULL           |                       | {}                                                                                         |   false
(10 rows)

Time: 51ms total (execution 51ms / network 0ms)

myuser@:26257/movr> \d users
  column_name | data_type | is_nullable | column_default | generation_expression |  indices  | is_hidden
--------------+-----------+-------------+----------------+-----------------------+-----------+------------
  id          | UUID      |    false    | NULL           |                       | {primary} |   false
  city        | VARCHAR   |    false    | NULL           |                       | {primary} |   false
  name        | VARCHAR   |    true     | NULL           |                       | {}        |   false
  address     | VARCHAR   |    true     | NULL           |                       | {}        |   false
  credit_card | VARCHAR   |    true     | NULL           |                       | {}        |   false
(5 rows)

Time: 42ms total (execution 42ms / network 0ms)

myuser@:26257/movr> \d vehicle_location_histories
  column_name | data_type | is_nullable | column_default | generation_expression |  indices  | is_hidden
--------------+-----------+-------------+----------------+-----------------------+-----------+------------
  city        | VARCHAR   |    false    | NULL           |                       | {primary} |   false
  ride_id     | UUID      |    false    | NULL           |                       | {primary} |   false
  timestamp   | TIMESTAMP |    false    | NULL           |                       | {primary} |   false
  lat         | FLOAT8    |    true     | NULL           |                       | {}        |   false
  long        | FLOAT8    |    true     | NULL           |                       | {}        |   false
(5 rows)

Time: 50ms total (execution 50ms / network 0ms)

myuser@:26257/movr> \d vehicles
    column_name    | data_type | is_nullable | column_default | generation_expression |                     indices                     | is_hidden
-------------------+-----------+-------------+----------------+-----------------------+-------------------------------------------------+------------
  id               | UUID      |    false    | NULL           |                       | {primary,vehicles_auto_index_fk_city_ref_users} |   false
  city             | VARCHAR   |    false    | NULL           |                       | {primary,vehicles_auto_index_fk_city_ref_users} |   false
  type             | VARCHAR   |    true     | NULL           |                       | {}                                              |   false
  owner_id         | UUID      |    true     | NULL           |                       | {vehicles_auto_index_fk_city_ref_users}         |   false
  creation_time    | TIMESTAMP |    true     | NULL           |                       | {}                                              |   false
  status           | VARCHAR   |    true     | NULL           |                       | {}                                              |   false
  current_location | VARCHAR   |    true     | NULL           |                       | {}                                              |   false
  ext              | JSONB     |    true     | NULL           |                       | {}                                              |   false
(8 rows)

Time: 43ms total (execution 43ms / network 0ms)

データを入れた後のDB Consoleの様子。

f:id:Kazuhira:20210903224250p:plain

データがどのノードに割り当てられているか確認する

それでは、データが各ノードにどのように割り当てられているか確認してみましょう。

テーブル単位で確認するには、show ranges文を使います。

SHOW RANGES | CockroachDB Docs

こんな感じで、テーブル名を指定して実行。

myuser@:26257/movr> show ranges from table vehicle_location_histories;
  start_key | end_key | range_id | range_size_mb | lease_holder | lease_holder_locality | replicas | replica_localities
------------+---------+----------+---------------+--------------+-----------------------+----------+---------------------
  NULL      | NULL    |       40 |      0.086918 |            2 |                       | {1,2,4}  | {,,}
(1 row)

Time: 23ms total (execution 23ms / network 0ms)

replicasというのはデータを保持しているノードのIDで、レプリカを保持しているノードを含みます。3つのノードの
IDが確認できますね。

lease_holderというのは、Lease Holderを含むノードです。

用語がいくつか出てきました。こちらに記載があります。

Architecture Overview / Glossary

CockroachDBはユーザーの全データ(テーブル、インデックスなど)とシステムデータを、大きなSorted Mapに格納します。
このキースペースのことを"Range"と呼び、連続するチャンクとして扱われます。

テーブルとセカンダリインデックスが最初に単一のRangeにマップされ、Range内の各キーと値は単一の行を表すことに
なります。そして、テーブルは主キーでソートされます。

Rangeはデフォルトで512MiBに達すると分割されます。

Replicaは、このRangeを複製して異なるノードに保存したものです。

Lease Holderは、Rangeの読み書きの要求を受信して調整するReplicaで、Replicaの中にひとつ存在します。
クライアントは、Lease Holderと対話して読み書きを行います。

Replicaに関しては、以降「レプリカ」と書きますね…。

余談ですが、CockroachDBにはパーティショニングもあるようですが、だいぶスケールの大きな話のようです。
※そして、Enterprise版の機能です

Define Table Partitions | CockroachDB Docs

他のテーブルも見てみましょう。

myuser@:26257/movr> show ranges from table vehicles;
                                    start_key                                    |                                    end_key                                     | range_id | range_size_mb | lease_holder | lease_holder_locality | replicas | replica_localities
---------------------------------------------------------------------------------+--------------------------------------------------------------------------------+----------+---------------+--------------+-----------------------+----------+---------------------
  NULL                                                                           | /"boston"/"\"\"\"\"\"\"B\x00\x80\x00\x00\x00\x00\x00\x00\x02"                  |       38 |      0.000305 |            5 |                       | {1,2,5}  | {,,}
  /"boston"/"\"\"\"\"\"\"B\x00\x80\x00\x00\x00\x00\x00\x00\x02"                  | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\x03"                        |       70 |      0.000144 |            1 |                       | {1,2,5}  | {,,}
  /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\x03"                        | /"new york"/"\x11\x11\x11\x11\x11\x11A\x00\x80\x00\x00\x00\x00\x00\x00\x01"    |       69 |      0.000458 |            5 |                       | {1,2,5}  | {,,}
  /"new york"/"\x11\x11\x11\x11\x11\x11A\x00\x80\x00\x00\x00\x00\x00\x00\x01"    | /"san francisco"/"wwwwwwH\x00\x80\x00\x00\x00\x00\x00\x00\a"                   |       68 |      0.000613 |            1 |                       | {1,2,5}  | {,,}
  /"san francisco"/"wwwwwwH\x00\x80\x00\x00\x00\x00\x00\x00\a"                   | /"san francisco"/"\x88\x88\x88\x88\x88\x88H\x00\x80\x00\x00\x00\x00\x00\x00\b" |       78 |       0.00016 |            5 |                       | {1,2,5}  | {,,}
  /"san francisco"/"\x88\x88\x88\x88\x88\x88H\x00\x80\x00\x00\x00\x00\x00\x00\b" | /"seattle"/"UUUUUUD\x00\x80\x00\x00\x00\x00\x00\x00\x05"                       |       67 |      0.000149 |            1 |                       | {1,2,5}  | {,,}
  /"seattle"/"UUUUUUD\x00\x80\x00\x00\x00\x00\x00\x00\x05"                       | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x06"                       |       79 |      0.000153 |            5 |                       | {1,2,5}  | {,,}
  /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x06"                       | /"washington dc"/"DDDDDDD\x00\x80\x00\x00\x00\x00\x00\x00\x04"                 |       77 |      0.000142 |            2 |                       | {1,2,5}  | {,,}
  /"washington dc"/"DDDDDDD\x00\x80\x00\x00\x00\x00\x00\x00\x04"                 | NULL                                                                           |       87 |      0.001448 |            5 |                       | {1,2,5}  | {,,}
(9 rows)

Time: 21ms total (execution 21ms / network 0ms)

show rangesは、データベース全体に対して実行することもできます。
※インデックスに対しても実行可能なようです

myuser@:26257/movr> show ranges from database movr;
          table_name         |                                    start_key                                     |                                     end_key                                      | range_id | range_size_mb | lease_holder | lease_holder_locality | replicas | replica_localities
-----------------------------+----------------------------------------------------------------------------------+----------------------------------------------------------------------------------+----------+---------------+--------------+-----------------------+----------+---------------------
  promo_codes                | NULL                                                                             | NULL                                                                             |       41 |      0.232973 |            2 |                       | {1,2,5}  | {,,}
  rides                      | NULL                                                                             | /"amsterdam"/"\xc5\x1e\xb8Q\xeb\x85@\x00\x80\x00\x00\x00\x00\x00\x01\x81"        |       39 |       0.00876 |            3 |                       | {3,4,5}  | {,,}
  rides                      | /"amsterdam"/"\xc5\x1e\xb8Q\xeb\x85@\x00\x80\x00\x00\x00\x00\x00\x01\x81"        | /"boston"/"8Q\xeb\x85\x1e\xb8B\x00\x80\x00\x00\x00\x00\x00\x00n"                 |       51 |      0.009648 |            4 |                       | {3,4,5}  | {,,}
  rides                      | /"boston"/"8Q\xeb\x85\x1e\xb8B\x00\x80\x00\x00\x00\x00\x00\x00n"                 | /"los angeles"/"\xa8\xf5\u008f\\(H\x00\x80\x00\x00\x00\x00\x00\x01J"             |       49 |       0.00953 |            5 |                       | {3,4,5}  | {,,}
  rides                      | /"los angeles"/"\xa8\xf5\u008f\\(H\x00\x80\x00\x00\x00\x00\x00\x01J"             | /"new york"/"\x1c(\xf5\u008f\\I\x00\x80\x00\x00\x00\x00\x00\x007"                |       81 |      0.010206 |            2 |                       | {2,3,4}  | {,,}
  rides                      | /"new york"/"\x1c(\xf5\u008f\\I\x00\x80\x00\x00\x00\x00\x00\x007"                | /"paris"/"\xe1G\xae\x14z\xe1H\x00\x80\x00\x00\x00\x00\x00\x01\xb8"               |       93 |      0.008629 |            3 |                       | {2,3,4}  | {,,}
  rides                      | /"paris"/"\xe1G\xae\x14z\xe1H\x00\x80\x00\x00\x00\x00\x00\x01\xb8"               | /"san francisco"/"\x8c\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x01\x13" |       80 |      0.019204 |            2 |                       | {1,2,5}  | {,,}
  rides                      | /"san francisco"/"\x8c\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x01\x13" | /"seattle"/"p\xa3\xd7\n=pD\x00\x80\x00\x00\x00\x00\x00\x00\xdc"                  |       91 |      0.009546 |            3 |                       | {1,2,3}  | {,,}
  rides                      | /"seattle"/"p\xa3\xd7\n=pD\x00\x80\x00\x00\x00\x00\x00\x00\xdc"                  | /"washington dc"/"Tz\xe1G\xae\x14L\x00\x80\x00\x00\x00\x00\x00\x00\xa5"          |       88 |      0.010118 |            3 |                       | {2,3,4}  | {,,}
  rides                      | /"washington dc"/"Tz\xe1G\xae\x14L\x00\x80\x00\x00\x00\x00\x00\x00\xa5"          | NULL                                                                             |       50 |      0.090246 |            4 |                       | {2,3,4}  | {,,}
  user_promo_codes           | NULL                                                                             | NULL                                                                             |       42 |             0 |            4 |                       | {1,2,4}  | {,,}
  users                      | NULL                                                                             | /"amsterdam"/"\xb333333@\x00\x80\x00\x00\x00\x00\x00\x00#"                       |       37 |      0.000116 |            3 |                       | {3,4,5}  | {,,}
  users                      | /"amsterdam"/"\xb333333@\x00\x80\x00\x00\x00\x00\x00\x00#"                       | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\n"                            |       48 |      0.000886 |            4 |                       | {3,4,5}  | {,,}
  users                      | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\n"                            | /"los angeles"/"\x99\x99\x99\x99\x99\x99H\x00\x80\x00\x00\x00\x00\x00\x00\x1e"   |       46 |       0.00046 |            1 |                       | {1,3,4}  | {,,}
  users                      | /"los angeles"/"\x99\x99\x99\x99\x99\x99H\x00\x80\x00\x00\x00\x00\x00\x00\x1e"   | /"new york"/"\x19\x99\x99\x99\x99\x99J\x00\x80\x00\x00\x00\x00\x00\x00\x05"      |       44 |      0.001015 |            3 |                       | {3,4,5}  | {,,}
  users                      | /"new york"/"\x19\x99\x99\x99\x99\x99J\x00\x80\x00\x00\x00\x00\x00\x00\x05"      | /"paris"/"\xcc\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x00("            |       45 |      0.000214 |            1 |                       | {1,3,4}  | {,,}
  users                      | /"paris"/"\xcc\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x00("            | /"san francisco"/"\x80\x00\x00\x00\x00\x00@\x00\x80\x00\x00\x00\x00\x00\x00\x19" |       43 |      0.001299 |            4 |                       | {2,3,4}  | {,,}
  users                      | /"san francisco"/"\x80\x00\x00\x00\x00\x00@\x00\x80\x00\x00\x00\x00\x00\x00\x19" | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x14"                         |       58 |      0.000669 |            3 |                       | {2,3,4}  | {,,}
  users                      | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x14"                         | /"washington dc"/"L\xcc\xcc\xcc\xcc\xccL\x00\x80\x00\x00\x00\x00\x00\x00\x0f"    |       57 |      0.000671 |            3 |                       | {3,4,5}  | {,,}
  users                      | /"washington dc"/"L\xcc\xcc\xcc\xcc\xccL\x00\x80\x00\x00\x00\x00\x00\x00\x0f"    | NULL                                                                             |       47 |      0.000231 |            5 |                       | {3,4,5}  | {,,}
  vehicle_location_histories | NULL                                                                             | NULL                                                                             |       40 |      0.086918 |            2 |                       | {1,2,4}  | {,,}
  vehicles                   | NULL                                                                             | /"boston"/"\"\"\"\"\"\"B\x00\x80\x00\x00\x00\x00\x00\x00\x02"                    |       38 |      0.000305 |            5 |                       | {1,2,5}  | {,,}
  vehicles                   | /"boston"/"\"\"\"\"\"\"B\x00\x80\x00\x00\x00\x00\x00\x00\x02"                    | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\x03"                          |       70 |      0.000144 |            1 |                       | {1,2,5}  | {,,}
  vehicles                   | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\x03"                          | /"new york"/"\x11\x11\x11\x11\x11\x11A\x00\x80\x00\x00\x00\x00\x00\x00\x01"      |       69 |      0.000458 |            5 |                       | {1,2,5}  | {,,}
  vehicles                   | /"new york"/"\x11\x11\x11\x11\x11\x11A\x00\x80\x00\x00\x00\x00\x00\x00\x01"      | /"san francisco"/"wwwwwwH\x00\x80\x00\x00\x00\x00\x00\x00\a"                     |       68 |      0.000613 |            1 |                       | {1,2,5}  | {,,}
  vehicles                   | /"san francisco"/"wwwwwwH\x00\x80\x00\x00\x00\x00\x00\x00\a"                     | /"san francisco"/"\x88\x88\x88\x88\x88\x88H\x00\x80\x00\x00\x00\x00\x00\x00\b"   |       78 |       0.00016 |            5 |                       | {1,2,5}  | {,,}
  vehicles                   | /"san francisco"/"\x88\x88\x88\x88\x88\x88H\x00\x80\x00\x00\x00\x00\x00\x00\b"   | /"seattle"/"UUUUUUD\x00\x80\x00\x00\x00\x00\x00\x00\x05"                         |       67 |      0.000149 |            1 |                       | {1,2,5}  | {,,}
  vehicles                   | /"seattle"/"UUUUUUD\x00\x80\x00\x00\x00\x00\x00\x00\x05"                         | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x06"                         |       79 |      0.000153 |            5 |                       | {1,2,5}  | {,,}
  vehicles                   | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x06"                         | /"washington dc"/"DDDDDDD\x00\x80\x00\x00\x00\x00\x00\x00\x04"                   |       77 |      0.000142 |            2 |                       | {1,2,5}  | {,,}
  vehicles                   | /"washington dc"/"DDDDDDD\x00\x80\x00\x00\x00\x00\x00\x00\x04"                   | NULL                                                                             |       87 |      0.001448 |            5 |                       | {1,2,5}  | {,,}
(30 rows)

Time: 43ms total (execution 42ms / network 1ms)

また、実験的機能ではありますが、show range for rowを使うと行単位でデータの配置状況を確認できます。

SHOW RANGE FOR ROW | CockroachDB Docs

show range for rowは、主キーまたはセカンダリインデックスを指定して実行します。今回は主キーで使いましょう。

単一主キーのテーブルの場合。

myuser@:26257/movr> show range from table promo_codes for row('0_explain_theory_something');
  start_key | end_key | range_id | lease_holder | lease_holder_locality | replicas | replica_localities
------------+---------+----------+--------------+-----------------------+----------+---------------------
  NULL      | NULL    |       41 |            2 |                       | {1,2,5}  | {,,}
(1 row)

Time: 57ms total (execution 57ms / network 0ms)

複合主キーの場合は、キーの指定が足りないとエラーになります。

myuser@:26257/movr> show range from table vehicle_location_histories for row('amsterdam');
ERROR: crdb_internal.encode_key(): number of values must equal number of columns in index "primary"

こんな感じで、すべてのキーのカラムを指定しましょう。

myuser@:26257/movr> show range from table vehicle_location_histories for row('amsterdam', 'ab020c49-ba5e-4800-8000-00000000014e', '2019-01-02 03:04:05.713');
  start_key | end_key | range_id | lease_holder | lease_holder_locality | replicas | replica_localities
------------+---------+----------+--------------+-----------------------+----------+---------------------
  NULL      | NULL    |       40 |            2 |                       | {1,2,4}  | {,,}
(1 row)

Time: 15ms total (execution 15ms / network 0ms)

これで、各ノードに対するデータの配置状況を確認できました。

レプリケーション数を変更する

先ほどのshow rangesなどのreplicasを見ると、3ノードがデータを保持していました。

これは、レプリケーションの係数を決めるnum_replicasのデフォルト値が3だからですね。

SHOW ZONE CONFIGURATIONS | CockroachDB Docs

確認。

myuser@:26257/movr> show zone configuration from range default;
     target     |              raw_config_sql
----------------+-------------------------------------------
  RANGE default | ALTER RANGE default CONFIGURE ZONE USING
                |     range_min_bytes = 134217728,
                |     range_max_bytes = 536870912,
                |     gc.ttlseconds = 90000,
                |     num_replicas = 3,
                |     constraints = '[]',
                |     lease_preferences = '[]'
(1 row)

Time: 2ms total (execution 1ms / network 0ms)

データベース単位にも見ることができます。現時点ではデフォルトの値を引き継いでいますが。

myuser@:26257/movr> show zone configuration from database movr;
     target     |              raw_config_sql
----------------+-------------------------------------------
  RANGE default | ALTER RANGE default CONFIGURE ZONE USING
                |     range_min_bytes = 134217728,
                |     range_max_bytes = 536870912,
                |     gc.ttlseconds = 90000,
                |     num_replicas = 3,
                |     constraints = '[]',
                |     lease_preferences = '[]'
(1 row)

Time: 3ms total (execution 3ms / network 0ms)

num_replicasの値は、alter databaseで変更することできます。

CONFIGURE ZONE | CockroachDB Docs

今回はmovrデータベースのみ、num_replicasを1に変更してみましょう。

myuser@:26257/movr> alter database movr configure zone using num_replicas = 1;
CONFIGURE ZONE 1

Time: 177ms total (execution 176ms / network 0ms)

確認すると、targetRANGE defaultからDATABASE movrに変わっています。

myuser@:26257/movr> show zone configuration from database movr;
     target     |              raw_config_sql
----------------+-------------------------------------------
  DATABASE movr | ALTER DATABASE movr CONFIGURE ZONE USING
                |     range_min_bytes = 134217728,
                |     range_max_bytes = 536870912,
                |     gc.ttlseconds = 90000,
                |     num_replicas = 1,
                |     constraints = '[]',
                |     lease_preferences = '[]'
(1 row)

Time: 3ms total (execution 3ms / network 0ms)

これで、しばらく待っているとreplicasがひとつのノードになっていきます。

myuser@:26257/movr> show ranges from database movr;
          table_name         |                                    start_key                                     |                                     end_key                                      | range_id | range_size_mb | lease_holder | lease_holder_locality | replicas | replica_localities
-----------------------------+----------------------------------------------------------------------------------+----------------------------------------------------------------------------------+----------+---------------+--------------+-----------------------+----------+---------------------
  promo_codes                | NULL                                                                             | NULL                                                                             |       41 |      0.232973 |            2 |                       | {2}      | {}
  rides                      | NULL                                                                             | /"amsterdam"/"\xc5\x1e\xb8Q\xeb\x85@\x00\x80\x00\x00\x00\x00\x00\x01\x81"        |       39 |       0.00876 |            4 |                       | {4}      | {}
  rides                      | /"amsterdam"/"\xc5\x1e\xb8Q\xeb\x85@\x00\x80\x00\x00\x00\x00\x00\x01\x81"        | /"boston"/"8Q\xeb\x85\x1e\xb8B\x00\x80\x00\x00\x00\x00\x00\x00n"                 |       51 |      0.009648 |            4 |                       | {4}      | {}
  rides                      | /"boston"/"8Q\xeb\x85\x1e\xb8B\x00\x80\x00\x00\x00\x00\x00\x00n"                 | /"los angeles"/"\xa8\xf5\u008f\\(H\x00\x80\x00\x00\x00\x00\x00\x01J"             |       49 |       0.00953 |            3 |                       | {3}      | {}
  rides                      | /"los angeles"/"\xa8\xf5\u008f\\(H\x00\x80\x00\x00\x00\x00\x00\x01J"             | /"new york"/"\x1c(\xf5\u008f\\I\x00\x80\x00\x00\x00\x00\x00\x007"                |       81 |      0.010206 |            3 |                       | {3}      | {}
  rides                      | /"new york"/"\x1c(\xf5\u008f\\I\x00\x80\x00\x00\x00\x00\x00\x007"                | /"paris"/"\xe1G\xae\x14z\xe1H\x00\x80\x00\x00\x00\x00\x00\x01\xb8"               |       93 |      0.008629 |            4 |                       | {2,4}    | {,}
  rides                      | /"paris"/"\xe1G\xae\x14z\xe1H\x00\x80\x00\x00\x00\x00\x00\x01\xb8"               | /"san francisco"/"\x8c\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x01\x13" |       80 |      0.019204 |            5 |                       | {5}      | {}
  rides                      | /"san francisco"/"\x8c\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x01\x13" | /"seattle"/"p\xa3\xd7\n=pD\x00\x80\x00\x00\x00\x00\x00\x00\xdc"                  |       91 |      0.009546 |            3 |                       | {3}      | {}
  rides                      | /"seattle"/"p\xa3\xd7\n=pD\x00\x80\x00\x00\x00\x00\x00\x00\xdc"                  | /"washington dc"/"Tz\xe1G\xae\x14L\x00\x80\x00\x00\x00\x00\x00\x00\xa5"          |       88 |      0.010118 |            4 |                       | {4}      | {}
  rides                      | /"washington dc"/"Tz\xe1G\xae\x14L\x00\x80\x00\x00\x00\x00\x00\x00\xa5"          | NULL                                                                             |       50 |      0.090246 |            4 |                       | {4}      | {}
  user_promo_codes           | NULL                                                                             | NULL                                                                             |       42 |             0 |            1 |                       | {1}      | {}
  users                      | NULL                                                                             | /"amsterdam"/"\xb333333@\x00\x80\x00\x00\x00\x00\x00\x00#"                       |       37 |      0.000116 |            5 |                       | {5}      | {}
  users                      | /"amsterdam"/"\xb333333@\x00\x80\x00\x00\x00\x00\x00\x00#"                       | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\n"                            |       48 |      0.000886 |            3 |                       | {3}      | {}
  users                      | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\n"                            | /"los angeles"/"\x99\x99\x99\x99\x99\x99H\x00\x80\x00\x00\x00\x00\x00\x00\x1e"   |       46 |       0.00046 |            1 |                       | {1}      | {}
  users                      | /"los angeles"/"\x99\x99\x99\x99\x99\x99H\x00\x80\x00\x00\x00\x00\x00\x00\x1e"   | /"new york"/"\x19\x99\x99\x99\x99\x99J\x00\x80\x00\x00\x00\x00\x00\x00\x05"      |       44 |      0.001015 |            3 |                       | {3}      | {}
  users                      | /"new york"/"\x19\x99\x99\x99\x99\x99J\x00\x80\x00\x00\x00\x00\x00\x00\x05"      | /"paris"/"\xcc\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x00("            |       45 |      0.000214 |            4 |                       | {4}      | {}
  users                      | /"paris"/"\xcc\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x00("            | /"san francisco"/"\x80\x00\x00\x00\x00\x00@\x00\x80\x00\x00\x00\x00\x00\x00\x19" |       43 |      0.001299 |            2 |                       | {2}      | {}
  users                      | /"san francisco"/"\x80\x00\x00\x00\x00\x00@\x00\x80\x00\x00\x00\x00\x00\x00\x19" | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x14"                         |       58 |      0.000669 |            4 |                       | {4}      | {}
  users                      | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x14"                         | /"washington dc"/"L\xcc\xcc\xcc\xcc\xccL\x00\x80\x00\x00\x00\x00\x00\x00\x0f"    |       57 |      0.000671 |            3 |                       | {3}      | {}
  users                      | /"washington dc"/"L\xcc\xcc\xcc\xcc\xccL\x00\x80\x00\x00\x00\x00\x00\x00\x0f"    | NULL                                                                             |       47 |      0.000231 |            5 |                       | {5}      | {}
  vehicle_location_histories | NULL                                                                             | NULL                                                                             |       40 |      0.086918 |            2 |                       | {2}      | {}
  vehicles                   | NULL                                                                             | /"boston"/"\"\"\"\"\"\"B\x00\x80\x00\x00\x00\x00\x00\x00\x02"                    |       38 |      0.000305 |            1 |                       | {1}      | {}
  vehicles                   | /"boston"/"\"\"\"\"\"\"B\x00\x80\x00\x00\x00\x00\x00\x00\x02"                    | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\x03"                          |       70 |      0.000144 |            5 |                       | {5}      | {}
  vehicles                   | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\x03"                          | /"new york"/"\x11\x11\x11\x11\x11\x11A\x00\x80\x00\x00\x00\x00\x00\x00\x01"      |       69 |      0.000458 |            5 |                       | {5}      | {}
  vehicles                   | /"new york"/"\x11\x11\x11\x11\x11\x11A\x00\x80\x00\x00\x00\x00\x00\x00\x01"      | /"san francisco"/"wwwwwwH\x00\x80\x00\x00\x00\x00\x00\x00\a"                     |       68 |      0.000613 |            2 |                       | {2}      | {}
  vehicles                   | /"san francisco"/"wwwwwwH\x00\x80\x00\x00\x00\x00\x00\x00\a"                     | /"san francisco"/"\x88\x88\x88\x88\x88\x88H\x00\x80\x00\x00\x00\x00\x00\x00\b"   |       78 |       0.00016 |            1 |                       | {1}      | {}
  vehicles                   | /"san francisco"/"\x88\x88\x88\x88\x88\x88H\x00\x80\x00\x00\x00\x00\x00\x00\b"   | /"seattle"/"UUUUUUD\x00\x80\x00\x00\x00\x00\x00\x00\x05"                         |       67 |      0.000149 |            2 |                       | {2}      | {}
  vehicles                   | /"seattle"/"UUUUUUD\x00\x80\x00\x00\x00\x00\x00\x00\x05"                         | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x06"                         |       79 |      0.000153 |            5 |                       | {5}      | {}
  vehicles                   | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x06"                         | /"washington dc"/"DDDDDDD\x00\x80\x00\x00\x00\x00\x00\x00\x04"                   |       77 |      0.000142 |            5 |                       | {5}      | {}
  vehicles                   | /"washington dc"/"DDDDDDD\x00\x80\x00\x00\x00\x00\x00\x00\x04"                   | NULL                                                                             |       87 |      0.001448 |            1 |                       | {1}      | {}
(30 rows)

Time: 53ms total (execution 52ms / network 1ms)

3に戻してみましょう。

myuser@:26257/movr> alter database movr configure zone using num_replicas = 3;
CONFIGURE ZONE 1

Time: 106ms total (execution 103ms / network 2ms)

しばらく待っていると、replicasが3ノードに戻ります。

myuser@:26257/movr> show ranges from database movr;
          table_name         |                                    start_key                                     |                                     end_key                                      | range_id | range_size_mb | lease_holder | lease_holder_locality | replicas | replica_localities
-----------------------------+----------------------------------------------------------------------------------+----------------------------------------------------------------------------------+----------+---------------+--------------+-----------------------+----------+---------------------
  promo_codes                | NULL                                                                             | NULL                                                                             |       41 |      0.232973 |            2 |                       | {2,3,4}  | {,,}
  rides                      | NULL                                                                             | /"amsterdam"/"\xc5\x1e\xb8Q\xeb\x85@\x00\x80\x00\x00\x00\x00\x00\x01\x81"        |       39 |       0.00876 |            4 |                       | {1,4,5}  | {,,}
  rides                      | /"amsterdam"/"\xc5\x1e\xb8Q\xeb\x85@\x00\x80\x00\x00\x00\x00\x00\x01\x81"        | /"boston"/"8Q\xeb\x85\x1e\xb8B\x00\x80\x00\x00\x00\x00\x00\x00n"                 |       51 |      0.009648 |            4 |                       | {1,3,4}  | {,,}
  rides                      | /"boston"/"8Q\xeb\x85\x1e\xb8B\x00\x80\x00\x00\x00\x00\x00\x00n"                 | /"los angeles"/"\xa8\xf5\u008f\\(H\x00\x80\x00\x00\x00\x00\x00\x01J"             |       49 |       0.00953 |            3 |                       | {2,3,4}  | {,,}
  rides                      | /"los angeles"/"\xa8\xf5\u008f\\(H\x00\x80\x00\x00\x00\x00\x00\x01J"             | /"new york"/"\x1c(\xf5\u008f\\I\x00\x80\x00\x00\x00\x00\x00\x007"                |       81 |      0.010206 |            3 |                       | {3,4,5}  | {,,}
  rides                      | /"new york"/"\x1c(\xf5\u008f\\I\x00\x80\x00\x00\x00\x00\x00\x007"                | /"paris"/"\xe1G\xae\x14z\xe1H\x00\x80\x00\x00\x00\x00\x00\x01\xb8"               |       93 |      0.008629 |            2 |                       | {1,2,4}  | {,,}
  rides                      | /"paris"/"\xe1G\xae\x14z\xe1H\x00\x80\x00\x00\x00\x00\x00\x01\xb8"               | /"san francisco"/"\x8c\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x01\x13" |       80 |      0.019204 |            5 |                       | {1,2,5}  | {,,}
  rides                      | /"san francisco"/"\x8c\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x01\x13" | /"seattle"/"p\xa3\xd7\n=pD\x00\x80\x00\x00\x00\x00\x00\x00\xdc"                  |       91 |      0.009546 |            3 |                       | {3,4,5}  | {,,}
  rides                      | /"seattle"/"p\xa3\xd7\n=pD\x00\x80\x00\x00\x00\x00\x00\x00\xdc"                  | /"washington dc"/"Tz\xe1G\xae\x14L\x00\x80\x00\x00\x00\x00\x00\x00\xa5"          |       88 |      0.010118 |            4 |                       | {1,4,5}  | {,,}
  rides                      | /"washington dc"/"Tz\xe1G\xae\x14L\x00\x80\x00\x00\x00\x00\x00\x00\xa5"          | NULL                                                                             |       50 |      0.090246 |            4 |                       | {1,4,5}  | {,,}
  user_promo_codes           | NULL                                                                             | NULL                                                                             |       42 |             0 |            1 |                       | {1,2,5}  | {,,}
  users                      | NULL                                                                             | /"amsterdam"/"\xb333333@\x00\x80\x00\x00\x00\x00\x00\x00#"                       |       37 |      0.000116 |            5 |                       | {1,4,5}  | {,,}
  users                      | /"amsterdam"/"\xb333333@\x00\x80\x00\x00\x00\x00\x00\x00#"                       | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\n"                            |       48 |      0.000886 |            3 |                       | {1,3,5}  | {,,}
  users                      | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\n"                            | /"los angeles"/"\x99\x99\x99\x99\x99\x99H\x00\x80\x00\x00\x00\x00\x00\x00\x1e"   |       46 |       0.00046 |            1 |                       | {1,2,4}  | {,,}
  users                      | /"los angeles"/"\x99\x99\x99\x99\x99\x99H\x00\x80\x00\x00\x00\x00\x00\x00\x1e"   | /"new york"/"\x19\x99\x99\x99\x99\x99J\x00\x80\x00\x00\x00\x00\x00\x00\x05"      |       44 |      0.001015 |            3 |                       | {1,2,3}  | {,,}
  users                      | /"new york"/"\x19\x99\x99\x99\x99\x99J\x00\x80\x00\x00\x00\x00\x00\x00\x05"      | /"paris"/"\xcc\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x00("            |       45 |      0.000214 |            4 |                       | {1,4,5}  | {,,}
  users                      | /"paris"/"\xcc\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x00("            | /"san francisco"/"\x80\x00\x00\x00\x00\x00@\x00\x80\x00\x00\x00\x00\x00\x00\x19" |       43 |      0.001299 |            2 |                       | {2,3,4}  | {,,}
  users                      | /"san francisco"/"\x80\x00\x00\x00\x00\x00@\x00\x80\x00\x00\x00\x00\x00\x00\x19" | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x14"                         |       58 |      0.000669 |            4 |                       | {2,3,4}  | {,,}
  users                      | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x14"                         | /"washington dc"/"L\xcc\xcc\xcc\xcc\xccL\x00\x80\x00\x00\x00\x00\x00\x00\x0f"    |       57 |      0.000671 |            3 |                       | {1,2,3}  | {,,}
  users                      | /"washington dc"/"L\xcc\xcc\xcc\xcc\xccL\x00\x80\x00\x00\x00\x00\x00\x00\x0f"    | NULL                                                                             |       47 |      0.000231 |            5 |                       | {2,3,5}  | {,,}
  vehicle_location_histories | NULL                                                                             | NULL                                                                             |       40 |      0.086918 |            2 |                       | {1,2,4}  | {,,}
  vehicles                   | NULL                                                                             | /"boston"/"\"\"\"\"\"\"B\x00\x80\x00\x00\x00\x00\x00\x00\x02"                    |       38 |      0.000305 |            1 |                       | {1,4,5}  | {,,}
  vehicles                   | /"boston"/"\"\"\"\"\"\"B\x00\x80\x00\x00\x00\x00\x00\x00\x02"                    | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\x03"                          |       70 |      0.000144 |            5 |                       | {3,4,5}  | {,,}
  vehicles                   | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\x03"                          | /"new york"/"\x11\x11\x11\x11\x11\x11A\x00\x80\x00\x00\x00\x00\x00\x00\x01"      |       69 |      0.000458 |            5 |                       | {2,3,5}  | {,,}
  vehicles                   | /"new york"/"\x11\x11\x11\x11\x11\x11A\x00\x80\x00\x00\x00\x00\x00\x00\x01"      | /"san francisco"/"wwwwwwH\x00\x80\x00\x00\x00\x00\x00\x00\a"                     |       68 |      0.000613 |            2 |                       | {2,3,5}  | {,,}
  vehicles                   | /"san francisco"/"wwwwwwH\x00\x80\x00\x00\x00\x00\x00\x00\a"                     | /"san francisco"/"\x88\x88\x88\x88\x88\x88H\x00\x80\x00\x00\x00\x00\x00\x00\b"   |       78 |       0.00016 |            1 |                       | {1,3,4}  | {,,}
  vehicles                   | /"san francisco"/"\x88\x88\x88\x88\x88\x88H\x00\x80\x00\x00\x00\x00\x00\x00\b"   | /"seattle"/"UUUUUUD\x00\x80\x00\x00\x00\x00\x00\x00\x05"                         |       67 |      0.000149 |            2 |                       | {2,3,5}  | {,,}
  vehicles                   | /"seattle"/"UUUUUUD\x00\x80\x00\x00\x00\x00\x00\x00\x05"                         | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x06"                         |       79 |      0.000153 |            5 |                       | {2,3,5}  | {,,}
  vehicles                   | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x06"                         | /"washington dc"/"DDDDDDD\x00\x80\x00\x00\x00\x00\x00\x00\x04"                   |       77 |      0.000142 |            5 |                       | {3,4,5}  | {,,}
  vehicles                   | /"washington dc"/"DDDDDDD\x00\x80\x00\x00\x00\x00\x00\x00\x04"                   | NULL                                                                             |       87 |      0.001448 |            1 |                       | {1,2,3}  | {,,}
(30 rows)

Time: 53ms total (execution 52ms / network 1ms)

num_replicasの値を変更すると、クラスタ内のレプリカ数を動的に変更できることがわかりました。

ノードを落としてみる

最後に、ノードを落としてみましょう。

クラスタを構成しているノードを確認します。

$ curl -s -H "X-Cockroach-API-Session: $SESSION_TOKEN" --cacert $CERTS_DIR/ca.crt https://localhost:8080/api/v2/nodes/ | jq '.nodes[] | "node_id: " + (.node_id|tostring) + ", address: " + .address.address_field + ", liveness_status: " + (.liveness_status|tostring)'
"node_id: 1, address: node1:26257, liveness_status: 3"
"node_id: 2, address: node3:26257, liveness_status: 3"
"node_id: 3, address: node4:26257, liveness_status: 3"
"node_id: 4, address: node5:26257, liveness_status: 3"
"node_id: 5, address: node2:26257, liveness_status: 3"

今回、ノードIDが3のもの(ノード名はnode4)をkillしてみました。

すると、liveness_statusが変化します。

$ curl -s -H "X-Cockroach-API-Session: $SESSION_TOKEN" --cacert $CERTS_DIR/ca.crt https://localhost:8080/api/v2/nodes/ | jq '.nodes[] | "node_id: " + (.node_id|tostring) + ", address: " + .address.address_field + ", liveness_status: " + (.liveness_status|tostring)'
"node_id: 1, address: node1:26257, liveness_status: 3"
"node_id: 2, address: node3:26257, liveness_status: 3"
"node_id: 3, address: node4:26257, liveness_status: 6"
"node_id: 4, address: node5:26257, liveness_status: 3"
"node_id: 5, address: node2:26257, liveness_status: 3"

DB Consoleで見ると、DRAININGという状態のようです。

f:id:Kazuhira:20210903225150p:plain

やや時間がかかりますが、それなりに待っているとDEADに変化します。

f:id:Kazuhira:20210903225651p:plain

こうなると、Lease HolderおよびReplicaからノードIDが3のものがなくなります。
Lease Nodeに関しては、DRAININGの時から移っていったようですが。

myuser@:26257/movr> show ranges from database movr;
          table_name         |                                    start_key                                     |                                     end_key                                      | range_id | range_size_mb | lease_holder | lease_holder_locality | replicas | replica_localities
-----------------------------+----------------------------------------------------------------------------------+----------------------------------------------------------------------------------+----------+---------------+--------------+-----------------------+----------+---------------------
  promo_codes                | NULL                                                                             | NULL                                                                             |       41 |      0.232973 |            2 |                       | {2,4,5}  | {,,}
  rides                      | NULL                                                                             | /"amsterdam"/"\xc5\x1e\xb8Q\xeb\x85@\x00\x80\x00\x00\x00\x00\x00\x01\x81"        |       39 |       0.00876 |            4 |                       | {1,4,5}  | {,,}
  rides                      | /"amsterdam"/"\xc5\x1e\xb8Q\xeb\x85@\x00\x80\x00\x00\x00\x00\x00\x01\x81"        | /"boston"/"8Q\xeb\x85\x1e\xb8B\x00\x80\x00\x00\x00\x00\x00\x00n"                 |       51 |      0.009648 |            4 |                       | {1,2,4}  | {,,}
  rides                      | /"boston"/"8Q\xeb\x85\x1e\xb8B\x00\x80\x00\x00\x00\x00\x00\x00n"                 | /"los angeles"/"\xa8\xf5\u008f\\(H\x00\x80\x00\x00\x00\x00\x00\x01J"             |       49 |       0.00953 |            4 |                       | {2,4,5}  | {,,}
  rides                      | /"los angeles"/"\xa8\xf5\u008f\\(H\x00\x80\x00\x00\x00\x00\x00\x01J"             | /"new york"/"\x1c(\xf5\u008f\\I\x00\x80\x00\x00\x00\x00\x00\x007"                |       81 |      0.010206 |            5 |                       | {2,4,5}  | {,,}
  rides                      | /"new york"/"\x1c(\xf5\u008f\\I\x00\x80\x00\x00\x00\x00\x00\x007"                | /"paris"/"\xe1G\xae\x14z\xe1H\x00\x80\x00\x00\x00\x00\x00\x01\xb8"               |       93 |      0.008629 |            2 |                       | {1,2,4}  | {,,}
  rides                      | /"paris"/"\xe1G\xae\x14z\xe1H\x00\x80\x00\x00\x00\x00\x00\x01\xb8"               | /"san francisco"/"\x8c\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x01\x13" |       80 |      0.019204 |            5 |                       | {1,2,5}  | {,,}
  rides                      | /"san francisco"/"\x8c\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x01\x13" | /"seattle"/"p\xa3\xd7\n=pD\x00\x80\x00\x00\x00\x00\x00\x00\xdc"                  |       91 |      0.009546 |            4 |                       | {2,4,5}  | {,,}
  rides                      | /"seattle"/"p\xa3\xd7\n=pD\x00\x80\x00\x00\x00\x00\x00\x00\xdc"                  | /"washington dc"/"Tz\xe1G\xae\x14L\x00\x80\x00\x00\x00\x00\x00\x00\xa5"          |       88 |      0.010118 |            4 |                       | {1,4,5}  | {,,}
  rides                      | /"washington dc"/"Tz\xe1G\xae\x14L\x00\x80\x00\x00\x00\x00\x00\x00\xa5"          | NULL                                                                             |       50 |      0.090246 |            4 |                       | {1,4,5}  | {,,}
  user_promo_codes           | NULL                                                                             | NULL                                                                             |       42 |             0 |            1 |                       | {1,2,5}  | {,,}
  users                      | NULL                                                                             | /"amsterdam"/"\xb333333@\x00\x80\x00\x00\x00\x00\x00\x00#"                       |       37 |      0.000116 |            5 |                       | {1,4,5}  | {,,}
  users                      | /"amsterdam"/"\xb333333@\x00\x80\x00\x00\x00\x00\x00\x00#"                       | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\n"                            |       48 |      0.000886 |            1 |                       | {1,4,5}  | {,,}
  users                      | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\n"                            | /"los angeles"/"\x99\x99\x99\x99\x99\x99H\x00\x80\x00\x00\x00\x00\x00\x00\x1e"   |       46 |       0.00046 |            1 |                       | {1,2,4}  | {,,}
  users                      | /"los angeles"/"\x99\x99\x99\x99\x99\x99H\x00\x80\x00\x00\x00\x00\x00\x00\x1e"   | /"new york"/"\x19\x99\x99\x99\x99\x99J\x00\x80\x00\x00\x00\x00\x00\x00\x05"      |       44 |      0.001015 |            2 |                       | {1,2,5}  | {,,}
  users                      | /"new york"/"\x19\x99\x99\x99\x99\x99J\x00\x80\x00\x00\x00\x00\x00\x00\x05"      | /"paris"/"\xcc\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x00("            |       45 |      0.000214 |            4 |                       | {1,4,5}  | {,,}
  users                      | /"paris"/"\xcc\xcc\xcc\xcc\xcc\xcc@\x00\x80\x00\x00\x00\x00\x00\x00("            | /"san francisco"/"\x80\x00\x00\x00\x00\x00@\x00\x80\x00\x00\x00\x00\x00\x00\x19" |       43 |      0.001299 |            2 |                       | {2,4,5}  | {,,}
  users                      | /"san francisco"/"\x80\x00\x00\x00\x00\x00@\x00\x80\x00\x00\x00\x00\x00\x00\x19" | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x14"                         |       58 |      0.000669 |            4 |                       | {1,2,4}  | {,,}
  users                      | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x14"                         | /"washington dc"/"L\xcc\xcc\xcc\xcc\xccL\x00\x80\x00\x00\x00\x00\x00\x00\x0f"    |       57 |      0.000671 |            1 |                       | {1,2,4}  | {,,}
  users                      | /"washington dc"/"L\xcc\xcc\xcc\xcc\xccL\x00\x80\x00\x00\x00\x00\x00\x00\x0f"    | NULL                                                                             |       47 |      0.000231 |            5 |                       | {2,4,5}  | {,,}
  vehicle_location_histories | NULL                                                                             | NULL                                                                             |       40 |      0.086918 |            2 |                       | {1,2,4}  | {,,}
  vehicles                   | NULL                                                                             | /"boston"/"\"\"\"\"\"\"B\x00\x80\x00\x00\x00\x00\x00\x00\x02"                    |       38 |      0.000305 |            1 |                       | {1,4,5}  | {,,}
  vehicles                   | /"boston"/"\"\"\"\"\"\"B\x00\x80\x00\x00\x00\x00\x00\x00\x02"                    | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\x03"                          |       70 |      0.000144 |            5 |                       | {1,4,5}  | {,,}
  vehicles                   | /"boston"/"333333D\x00\x80\x00\x00\x00\x00\x00\x00\x03"                          | /"new york"/"\x11\x11\x11\x11\x11\x11A\x00\x80\x00\x00\x00\x00\x00\x00\x01"      |       69 |      0.000458 |            5 |                       | {1,2,5}  | {,,}
  vehicles                   | /"new york"/"\x11\x11\x11\x11\x11\x11A\x00\x80\x00\x00\x00\x00\x00\x00\x01"      | /"san francisco"/"wwwwwwH\x00\x80\x00\x00\x00\x00\x00\x00\a"                     |       68 |      0.000613 |            2 |                       | {1,2,5}  | {,,}
  vehicles                   | /"san francisco"/"wwwwwwH\x00\x80\x00\x00\x00\x00\x00\x00\a"                     | /"san francisco"/"\x88\x88\x88\x88\x88\x88H\x00\x80\x00\x00\x00\x00\x00\x00\b"   |       78 |       0.00016 |            1 |                       | {1,4,5}  | {,,}
  vehicles                   | /"san francisco"/"\x88\x88\x88\x88\x88\x88H\x00\x80\x00\x00\x00\x00\x00\x00\b"   | /"seattle"/"UUUUUUD\x00\x80\x00\x00\x00\x00\x00\x00\x05"                         |       67 |      0.000149 |            2 |                       | {2,4,5}  | {,,}
  vehicles                   | /"seattle"/"UUUUUUD\x00\x80\x00\x00\x00\x00\x00\x00\x05"                         | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x06"                         |       79 |      0.000153 |            5 |                       | {1,2,5}  | {,,}
  vehicles                   | /"seattle"/"ffffffH\x00\x80\x00\x00\x00\x00\x00\x00\x06"                         | /"washington dc"/"DDDDDDD\x00\x80\x00\x00\x00\x00\x00\x00\x04"                   |       77 |      0.000142 |            5 |                       | {1,4,5}  | {,,}
  vehicles                   | /"washington dc"/"DDDDDDD\x00\x80\x00\x00\x00\x00\x00\x00\x04"                   | NULL                                                                             |       87 |      0.001448 |            1 |                       | {1,2,4}  | {,,}
(30 rows)

Time: 60ms total (execution 58ms / network 1ms)

APIでノードのステータスを見ると、こんな感じになっています。

$ curl -s -H "X-Cockroach-API-Session: $SESSION_TOKEN" --cacert $CERTS_DIR/ca.crt https://localhost:8080/api/v2/nodes/ | jq '.nodes[] | "node_id: " + (.node_id|tostring) + ", address: " + .address.address_field + ", liveness_status: " + (.liveness_status|tostring)'
"node_id: 1, address: node1:26257, liveness_status: 3"
"node_id: 2, address: node3:26257, liveness_status: 3"
"node_id: 3, address: node4:26257, liveness_status: 1"
"node_id: 4, address: node5:26257, liveness_status: 3"
"node_id: 5, address: node2:26257, liveness_status: 3"

まとめ

CockroachDBで、データがどのノードに割り当てられているか確認してみました。
また、レプリケーションの係数を変更して、クラスタ内のレプリカを動的に変えられるところも確認してみました。

直感的な挙動で、理解しやすかったですね。

一方で、ノードの離脱、復帰についてはいろいろあるようなので、また別の機会に詳しくみてみようかなと思います。

Decommission Nodes | CockroachDB Docs