YugabyteDBによるトークンバケットレート制限のスケーリング


このシリーズでは、私は私のRateLimitDemo.java 同じ行の更新を伴わないAmazon RDSでのPostgreSQLのプログラム、read commitとserializableの分離.結果は
  • レート:1000トークン/秒(100 %トランザクション成功)id 読取り隔離レベルでs
  • レート:930トークン/秒id シリアル化可能な分離レベル
  • レート:124トークン/秒(100.00 %トランザクション成功)の50スレッドと同じid 読取り隔離レベルでs
  • レート:218トークン/s(83 %トランザクション成功)、10のスレッドと同じですid シリアル化可能な分離レベル

  • yugabytedb雲
    マネージドサービスを使用するのと同じ考えで、Yugabyte dbaasを通してAWS上で3ノードのyugabytedbクラスタを作成しました.


    YugabyteDBは別の約束を読むidインマイRateLimitDemo.java 私は変更id セッションpidを連結するには、次の手順に従います.rate_limiting_request(?||pg_backend_pid(),?) そして、read - commitされた分離レベルを設定します.connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED)
    java RateLimitDemo 50 "jdbc:yugabytedb://47cc8863-9344-4a9c-bc02-0dd9f843dceb.cloudportal.yugabyte.com/yugabyte?user=admin&password=Covid-19" "user2" 1000 20 | awk 'BEGIN{t=systime()}/remaining$/{c=c+1;p=100*$5/$3}NR%100==0{printf "rate: %8.2f/s (last pct: %5.2f) max retry:%3d\n",c/(systime()-t),p,retry}/retry/{sub(/#/,"",$6);if($6>retry)retry=$6}'
    
    read commitはPostgreSQLの互換性のために用意されていますが、推奨されませんので、PostgreSQLと同じレートであることを示します.
    rate:  1063.08/s (last pct: 100.00) max retry:  1
    rate:  1063.32/s (last pct: 100.00) max retry:  1
    rate:  1063.56/s (last pct: 100.00) max retry:  1
    rate:  1063.80/s (last pct: 100.00) max retry:  1
    rate:  1064.05/s (last pct: 100.00) max retry:  1
    rate:  1064.29/s (last pct: 100.00) max retry:  1
    rate:  1064.53/s (last pct: 100.00) max retry:  1
    rate:  1062.20/s (last pct: 100.00) max retry:  1
    rate:  1062.44/s (last pct: 100.00) max retry:  1
    rate:  1062.68/s (last pct: 100.00) max retry:  1
    rate:  1062.92/s (last pct: 100.00) max retry:  1
    rate:  1063.16/s (last pct: 100.00) max retry:  1
    
    PostgreSQLとの違いは、悲観的なロックを使用して再試行していませんでした.YugabyteDBはここで楽観的にロックを使用します.

    YugabyteDBシリアル化可能idインマイRateLimitDemo.java 私は守るid セッションpidを連結します.rate_limiting_request(?||pg_backend_pid(),?) そして、read - commitされた分離レベルを設定します.connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE)スループットは同じです.
    rate:  1079.99/s (last pct: 100.00) max retry:  2
    rate:  1079.38/s (last pct: 100.00) max retry:  2
    rate:  1079.44/s (last pct: 100.00) max retry:  2
    rate:  1079.51/s (last pct: 100.00) max retry:  2
    rate:  1079.57/s (last pct: 100.00) max retry:  2
    rate:  1079.63/s (last pct: 100.00) max retry:  2
    rate:  1079.69/s (last pct: 100.00) max retry:  2
    rate:  1079.75/s (last pct: 100.00) max retry:  2
    rate:  1079.81/s (last pct: 100.00) max retry:  2
    rate:  1079.87/s (last pct: 100.00) max retry:  2
    rate:  1079.94/s (last pct: 100.00) max retry:  2
    rate:  1080.00/s (last pct: 100.00) max retry:  2
    
    シリアル化可能なのは、右の分離レベルです.リトライ量はまだ少ない.
    この実行中の主要なパフォーマンスメトリックです.
  • 1000個のysql ops/sは毎秒トークンの割合にマッチします.なぜなら、それぞれのトークンリクエストは1つのUPDATE文ですid を追加する
  • 1000 OPS/sは、分散ストレージとトランザクション層のdocdbにおける操作の数です.そこでは、操作はRAFTプロトコルで3ノードに複製されます.ここでは、各更新プログラム.返り値はトランザクションのread + writeであり、1つの読み出しと1つの書き込みとして現れる.リターンが1つの操作であるために押し下げられるとき、若干のケースがあります、しかし、それは現在計算された値(YSQL層で計算が行われるので)にされません
  • これらのアップデートの平均で5ミリ秒の待ち時間.テーブルがハッシュされているのでid これらの操作は、右のノード、タブレットリーダーに送られ、他のノードからの書き込みクォートを取得するのを待ちます(ここではマルチZの設定があります).
  • 私は、圧縮がバックグラウンドで起こるとき、5 msから7 msまで潜在性の少しの増加を説明するためにコンパクトを示しました.すべての更新は、列の値とsstファイルのcompactionのための新しいバージョンとして格納されて以前のバージョンを取り除く.
  • 我々は、この平均時間が5ミリ秒であることを確認しているPGRIGHT STATHERNステートメントに関する見解を持っています.

    「ローカルブロック」統計はゼロです.なぜなら、一時テーブルはここに関係していません.yysqlがステートレスであるため、共有ブロックヒットを表示しません.PostgreSQLのコードは、テーブル操作メソッドの上でのみ再利用され、タプル操作をdocdb操作に変換します.
    したがって、これは衝突なしでこのトークンバケットアルゴリズムを実行することについてです.パフォーマンスは、PostgreSQLと同じですが、スケールアウトする追加の可能性があります.負荷はここの3つのノードに分配されます、そして、1つのノードが計画されていない停電の計画されたメンテナンスのために下がるならば、複製因子RF = 3はすべて透過的に続きます.

    PostgreSQL read readと同じです.id今50レースでレース条件を強調するid . インマイRateLimitDemo.java 私は戻ってid ひとりぼっちrate_limiting_request(?,?) そして、read - commitされた分離レベルを設定します.connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED)
    rate:   126.99/s (last pct: 96.69) max retry:  4
    rate:   127.59/s (last pct: 84.78) max retry:  4
    rate:   127.39/s (last pct: 95.62) max retry:  4
    rate:   127.17/s (last pct: 98.37) max retry:  4
    rate:   126.97/s (last pct: 96.71) max retry:  4
    rate:   127.58/s (last pct: 95.68) max retry:  4
    rate:   127.38/s (last pct: 97.62) max retry:  4
    rate:   127.15/s (last pct: 96.68) max retry:  4
    rate:   127.76/s (last pct: 88.00) max retry:  4
    rate:   127.54/s (last pct: 92.53) max retry:  4
    rate:   127.34/s (last pct: 94.48) max retry:  4
    rate:   127.91/s (last pct: 92.85) max retry:  4
    rate:   127.69/s (last pct: 92.68) max retry:  4
    rate:   127.50/s (last pct: 92.87) max retry:  4
    rate:   128.02/s (last pct: 83.57) max retry:  4
    rate:   127.78/s (last pct: 95.61) max retry:  4
    rate:   128.33/s (last pct: 95.61) max retry:  4
    rate:   128.14/s (last pct: 95.66) max retry:  4
    rate:   128.74/s (last pct: 98.04) max retry:  4
    rate:   128.51/s (last pct: 92.40) max retry:  4
    rate:   128.29/s (last pct: 94.63) max retry:  4
    
    ここでは、PostgreSQLのように、すべてのスレッドが同じ行を更新するように競合しているので、この速度は非常に低いです.最初に、1行だけがビジーです.第二に、リードコミットの分離レベルでも再試行があります.
    エラーが発生しました.
    (pid@host [email protected])   3771 calls   3487 tokens      3.8 /sec 60000 remaining
    (pid@host [email protected])   2706 calls   2460 tokens      2.6 /sec 60000 remaining
    (pid@host [email protected])   1513 calls   1422 tokens      1.5 /sec 60000 remaining
    2022-01-05T23:00:26.369987Z SQLSTATE 40001 on retry #0 com.yugabyte.util.PSQLException: ERROR: All transparent retries exhausted. Operation failed. Try again.: Value write after transaction start: { physical: 1641423626346947 } >= { physical: 1641423625848215 }: kConflict
    2022-01-05T23:00:26.371342Z SQLSTATE 40001 on retry #0 com.yugabyte.util.PSQLException: ERROR: Operation expired: Transaction aborted: kAborted
    (pid@host [email protected])   2568 calls   2482 tokens      2.7 /sec 60000 remaining
    (pid@host [email protected])   2272 calls   2186 tokens      2.4 /sec 60000 remaining
    
    これは私のプログラムでキャッチしたもので、数ミリ秒後に再試行するが、データベースで自動的に再試行されたAll transparent retries exhausted ). これは、なぜそれがアプリケーションの再試行の数が少ないと遅いです説明します.

    PostgreSQLシリアル化可能です.id最後のテストRateLimitDemo.java 私は戻ってid ひとりぼっちrate_limiting_request(?,?) そして、read - commitされた分離レベルを設定します.connection.setTransactionIsolation(Connection.SERIALIZABLE)前の結果を考えれば、私はPostgreSQLと同様にスレッド数を10に減らしました.ここでは秒単位で取得したトークンの割合を示します.
    rate:   116.60/s (last pct: 93.95) max retry:  8
    rate:   116.60/s (last pct: 93.25) max retry:  8
    rate:   116.60/s (last pct: 92.66) max retry:  8
    rate:   116.60/s (last pct: 88.60) max retry:  8
    rate:   116.60/s (last pct: 88.48) max retry:  8
    rate:   116.60/s (last pct: 93.95) max retry:  8
    rate:   116.59/s (last pct: 88.60) max retry:  8
    rate:   116.59/s (last pct: 93.92) max retry:  8
    rate:   116.59/s (last pct: 93.92) max retry:  8
    rate:   116.59/s (last pct: 92.66) max retry:  8
    rate:   116.59/s (last pct: 87.81) max retry:  8
    rate:   116.59/s (last pct: 88.73) max retry:  8
    rate:   116.59/s (last pct: 87.81) max retry:  8
    rate:   116.58/s (last pct: 91.75) max retry:  8
    rate:   116.58/s (last pct: 92.66) max retry:  8
    rate:   116.58/s (last pct: 93.25) max retry:  8
    rate:   116.58/s (last pct: 93.95) max retry:  8
    rate:   116.58/s (last pct: 87.81) max retry:  8
    rate:   116.58/s (last pct: 91.75) max retry:  8
    rate:   116.59/s (last pct: 93.95) max retry:  8
    
    同じ行のすべてのスレッドとの更新の競合を考慮した場合、スループットは低くなりますが、レイテンシは良いままです.rate_limiting_request(?,?) 1つ

    もう一つは9869491.81/2149291 = 4.6 msであったid . はい、このレース条件では、スループットが低くなりませんが、RAMやCPUのデータの局所性を考慮して応答時間が高くなります.
    パフォーマンスメトリックは同じです.

    夜の走りは真ん中(私は10本の糸で同じテストを始めた)id そして、より低いCPU使用量で、より現実的である異なるものの上の50の糸.あなたが少数のユーザーまたはテナントIDですべてのトークン要求でこのレース状態にいるならば、より高いスループットを必要として、このトークンバケツはスケーラブルではありません.次のポストに別のアルゴリズムを示します.