1件の注文、4つのシステム
お客様が代金を払いました。倉庫は商品を用意し、経理は売上を記録し、メール担当はお礼を送らなければなりません。
ウェブサイトが全部を直接呼ぶと、遅いシステムが1つあるだけで、すべての注文が遅くなります。出来事を記録に書き、各システムが準備できたときに読むほうが、うまくいきます。
このレッスンのゴール
メモ
イベントの記録と、コンシューマーがそれを読む仕組みを説明できます。
キーワード
| ことば | いみ | れい |
|---|---|---|
| イベント | 何かが起きたという記録 | 注文の支払い |
| トピック | 名前のついた、イベントの記録 | |
| パーティション | トピックを順番を保ったまま分けた一片 | |
| オフセット | パーティションの中の番号で、0から数える | |
| プロデューサー | トピックにイベントを書き足すプログラム | |
| コンシューマー | トピックのイベントを読むプログラム |
学生が入力するセルは、このプレビューでは空白です。
トピックは書き足す記録
Kafkaは、イベントをトピックに入れます。レジの記録帳を思い浮かべてください。新しい行は最後に付き、古い行は変わりません。
プロデューサーがイベントを書き足し、各イベントにはオフセットという番号がつきます。番号は0から始まります。イベントは、読まれたかどうかに関係なく、決めた期間だけ残ります。
例: 記録とオフセット
| オフセット | イベント | 書いたもの |
|---|---|---|
| 0 | 注文2001が支払い済み | ウェブサイト |
| 1 | 注文2002が支払い済み | ウェブサイト |
| 2 | 注文2001を準備した | 倉庫 |
| 3 | 注文2003が支払い済み | ウェブサイト |
学生が入力するセルは、このプレビューでは空白です。
2パーティションのトピックを作る
curl -s -X POST -H "Content-Type: application/json" -d '{"name":"register","partitions":2,"replicationFactor":1,"configs":{}}' http://kafka-ui:8080/api/clusters/lab/topics -o /dev/null -w "%{http_code}\n"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
空のトピックのオフセットを見る
curl -s http://kafka-ui:8080/api/clusters/lab/topics/register | grep -o '"partition":[0-9]*\|"offsetMax":[0-9]*'ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
パーティションが仕事を分ける
大きな店のイベントは、1台の機械の1本の記録には収まりません。そこでトピックをパーティションに分けます。それぞれが別の記録で、自分のオフセットを持ちます。
同じパーティションの中では、イベントの順番が守られます。パーティションが違えば、順番は約束されません。
パーティション0にイベントを足す
curl -s -X POST -H "Content-Type: application/json" -d '{"partition":0,"key":"reg1","value":"bread","headers":{},"keySerde":"String","valueSerde":"String"}' http://kafka-ui:8080/api/clusters/lab/topics/register/messages -w "%{http_code}\n"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
パーティション0に2つ目を足す
curl -s -X POST -H "Content-Type: application/json" -d '{"partition":0,"key":"reg1","value":"milk","headers":{},"keySerde":"String","valueSerde":"String"}' http://kafka-ui:8080/api/clusters/lab/topics/register/messages -w "%{http_code}\n"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
パーティション1にイベントを足す
curl -s -X POST -H "Content-Type: application/json" -d '{"partition":1,"key":"web","value":"coffee","headers":{},"keySerde":"String","valueSerde":"String"}' http://kafka-ui:8080/api/clusters/lab/topics/register/messages -w "%{http_code}\n"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
オフセットをもう一度見る
curl -s http://kafka-ui:8080/api/clusters/lab/topics/register | grep -o '"partition":[0-9]*\|"offsetMax":[0-9]*'ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
コンシューマーはオフセットを覚える
コンシューマーは、パーティションのイベントを順番に読み、次に必要なオフセットを覚えます。止まって再開しても、そこから続けられます。
2つのサービスが同じトピックを読めます。それぞれが自分のオフセットを持つので、遅いサービスが速いサービスを止めることはありません。記録の終わりとコンシューマーの位置の差が、遅れです。
コンシューマーが読んで進む
# トピックの1つのパーティションを、リストとして見ます。コンシューマーが覚えるのは数字ひとつです。
partition = ["bread", "milk", "coffee", "rice"]
offset = 2
print("読んだもの:", partition[offset], "オフセット", offset)
offset = offset + 1
print("次のオフセット:", offset)
print("まだ読んでいない数:", len(partition) - offset)
# 最初の offset を 0 に変えると、最初から読めます。
2つのコンシューマー、2つのオフセット
# 2つのサービスが、同じ記録を読みます。それぞれが自分のオフセットを持ちます。
log = ["bread", "milk", "coffee"]
offsets = {"billing": 3, "mailer": 1}
for name in offsets:
left = len(log) - offsets[name]
print(name, "の未読:", left, "件")
# mailer のオフセットを 3 にして、もう一度実行してみましょう。
パーティション0を最初から読み直す
curl -s -N "http://kafka-ui:8080/api/clusters/lab/topics/register/messages/v2?seekType=BEGINNING&partitions=0&limit=10" | grep -o '"partition":[0-9]*,"offset":[0-9]*\|"value":"[a-z]*"'ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
よくある間違い
注意
手紙をポストから取り出すように、読むとイベントが消えると考えがちです。記録では、そうなりません。読むと進むのは、コンシューマーのオフセットだけです。イベントは残るので、別のサービスも読めます。
さらに先へ: 次のオフセットを予想する
パーティション1へ送るコマンドを、値を変えて2回送ってください。送る前に、それぞれのあとでパーティション1の offsetMax がいくつになるか予想します。
そのあと、オフセットを見るコマンドで確かめてください。パーティション0の数字は変わりますか。