詳しくはダブルバッファー


前言


バッファメカニズムは,データの持続化に対する遅延であり,不要なIOを低減し,データドロップの効率を向上させる.本稿では,デュアルBufferを有するバッファプール(以下,TwinsBufferPoolと総称する)がどのように実現されるかを詳細に検討し,読者はこれに基づいてN−Bufferの実現原理を得ることができる.
この記事では、バッファ(Buffer)とバッファ(BufferPool)は2つの重要な概念であり、両者は、1つのバッファ内で1つ以上のバッファが協働して動作し、バッファ内のすべてのバッファがリングキューに組織され、前後の2つのバッファが互いに役割を置き換えることができることを含む関係を構成していることが明らかになった.
もちろん、プロセス全体にわたって、他の補助ツールも登場し、以下で説明します.

一、設計のポイント


1、拡張性.間違いなく、拡張性は設計の良いソフトウェアに対する基本的な要求であり、1つのソフトウェアの拡張性の場所は通常多くの場所があり、これはプログラミング者の経験にある程度依存し、製品の需要に限られると、ソフトウェアの拡張性を深刻に制限する可能性があります.バッファプールは比較的汎用的なミドルウェアであり、拡張点が比較的多い.例えば、バッファ数の指定、スレッドのセキュリティの有無、バッファしきい値のプロビジョニングなどである.
2、使いやすさ.設計されたミドルウェアはユーザーに友好的であるべきで、使用中に煩雑な配置がなく、奇形怪状のAPIがあり、さらに多くの不要なDependenciesがあり得ず、コードの侵入性がなければ、それは非常に完璧である.この要求に基づいて、TwinsBufferPoolはSpring Boot Starterの形式を作り、プロジェクトのdependenciesに参加すれば使用を開始することができます.
3、安定性.これは中間部品の良し悪しを測る重要なKPIの一つであり、外観から見ると、同じ船であり、穴を開けたことと完璧なことは致命的な違いであり、ユーザーは自分が完全な船に乗って、万里を航行できるようにすることを望んでいる.
4、効率性.安定性といえば、効率的だと言わざるを得ません.ユーザーが問題を迅速に解決するのに役立つなら、間違いなく最も完璧な結果です.TwinsBufferPoolの安定性と効率性の2つの指標について、jemeterの測定結果を添付して説明します.

二、設計案


このセクションでは、TwinsBufferPoolの完全な設計案を示します.まず、構成から説明します.
各パラメータにはデフォルト値が設定されているので、構成を行わなくても許可されます.現在のTwinsBufferPoolで提供できる構成パラメータ(yml)は次のとおりです.
buffer:
  capacity: 2000
  threshold: 0.5
  allow-duplicate: true
  pool:
    enable-temporary-storage: true
    buffer-time-in-seconds: 120

パラメータの説明表を添付します.
以上のパラメータは比較的分かりやすく、ここではenable-temporary-storageとbuffer-time-in-secondsの2つのパラメータを重点的に説明します.
パラメータの説明によれば,この2つのパラメータはバーストを予防し,データ損失を招くためであることが明らかになった.バッファはメモリベースで設計されているため、バッファされたデータがいつでもサービス再起動やサービスダウンのリスクの高い環境にあることを意味します.そのため、この2つのパラメータが誕生します.
TwinsBufferPoolの良好なインタフェース設計のため、以上の2つのパラメータの実現メカニズムも高度に拡張可能である.TwinsBufferPoolのデフォルトはRedisベースの実装であり,ユーザもMongoDB,MySQL,FileSystemなどで実現できる.これによりまた別の問題が発生し,様々な異常により一時記憶層に一定量のデータが残され,次回起動時にこの部分のデータを復元する必要がある.
要するに、データはflush動作によって最終的にディスクに永続化されます.
多くの実際のビジネスシーンはバッファの同時量に一定の要求があるため、デフォルトではスレッドセキュリティの実現戦略を採用し、JDKにおけるThreadPoolに啓発され、バッファも自身の状態管理のメカニズムを備えている.バッファプールが存在する可能性のあるすべてのステータスと、各ステータスのフローを以下に示します.
/**
 *  
 */
private static final int ST_NOT_READY = 1;

/**
 *  , 
 */
private static final int ST_STARTED = 2;

/**
 *  , 
 */
private static final int ST_SHUTTING_DOWN = 3;

/**
 *  
 */
private static final int ST_SHUTDOWN = 4;

/**
 *  
 */
private static final int ST_RECOVERING = 5;

上記の分析により,設計のスキームも呼び出され,以下では主なインタフェースの設計と実現を示す.
以上の説明でBufferPool定義のインタフェースもわかりやすくなりました.バッファプールのライフサイクル全体、および内部のいくつかの動作メカニズムが体現されています.設計上、バッファプールとストレージレイヤを論理的に分離し、拡張性をさらに向上させることに注目すべきである.
ストレージ関連インタフェースにはいくつかの簡単なCURDが含まれており、現在のデフォルトではRedisを一時ストレージ層、MongoDBを永久ストレージ層として使用しており、ユーザーは必要に応じて他のストレージ方式を実現することができる.
次の図は、TwinsBufferPoolの実装方法を示しています.DataBufferはバッファであり、依存しなければならない基礎要素です.設計されたのはリングキューなのでCycleQueueに依存し,このリングキューのinterfaceもカスタマイズされており,JDKでは比較的適切な実装は見つからなかった.
注意すべきは、BufferPoolインタフェースの定義は柔軟で拡張性があり、TwinsBufferPoolはリングキューベースの実装方式を提供しているだけで、ユーザーも自分で設計し、別のデータ構造を使用してバッファプールの動作をサポートすることができます.

三、圧力測定報告


使用しているのは個人のPCパソコンで、機械の配置は以下の通りです.
プロセッサー:i 5-7400 CPU 3.00 GHZクアッドコア
メモリ:8.00 GB
OS:Windows 10 64ビットx 64ベースプロセッサ
実行環境は次のとおりです.
jdk 1.8.0_144
SpringBoot_2.1.0、Tomcat 9を内蔵.0
Redis_v4.0.1
MongoDB_v3.4.7
テストツール:
jemeter_v5.1
合計4組のパラメータを試験し,各パラメータは主に最大容量,しきい値,最大バッファ時間の3つのパラメータに対して調整した.
第1グループ:
buffer:
  capacity: 1000
  threshold: 0.8
  pool:
    buffer-time-in-seconds: 60

2番目のグループ:
buffer:
  capacity: 5000
  threshold: 0.8
  pool:
    buffer-time-in-seconds: 60

第3グループ
buffer:
  capacity: 5000
  threshold: 0.8
  pool:
    buffer-time-in-seconds: 300

第4グループ
buffer:
  capacity: 10000
  threshold: 0.8
  pool:
    buffer-time-in-seconds: 300

全部で9つの指標を採集した:CPU占有率、スタックメモリ/M、スレッド数、エラー率、スループット/sec、最長応答時間/ms、最短応答時間/ms、平均応答時間/ms、データ損失量.
紙面に限られ,スタックメモリ,データ損失量,平均応答時間,スループットの4つの指標のみを示した.
全体的に見ると、毎秒の合併量の増加に伴い、各指標はあまり楽観的ではない傾向を示しており、その中で最も不安定なのは第4グループのパラメータであり、変動が明らかであり、総合的に最適なのは第2グループのパラメータであり、次いで第3グループである.
データ損失量は比較的関心のある指標であり、図から分かるように、同時量が4000に達すると、データ損失が発生し始める.この現象の原因はTwinsBufferPool実装コードのBugではなく、要求タイムアウトによる「Connection refused」であり、各サーブレット運転容器にタイムアウトメカニズムがあるため、キュー要求時間が長すぎると、直接拒否される.したがって,データ損失量と誤り率曲線を見ると,両者は一致する.タイムアウトしないように設定すると、損失量がゼロになり、エラー率がゼロになり、平均応答時間が長くなります.
個人のテスト環境に制限されているため、テストプロセス全体が厳密ではなく、得られたデータも完璧ではありませんが、ここでは最適化調整のアドバイスを提供しています.
1、ハードウェア環境.「巧婦は米なしの炊事が難しい」というだけに、提供されるハードウェアの性能自体が限られていると、上で実行されるソフトウェアも正常に発揮されにくい.
2、ソフトウェアアーキテクチャ.この想像の空間はとても大きくて、その中の1つの方案は私が将来RoadMapの中に組み入れることができると思っています:マルチバッファの負荷の均衡.1つのアプリケーションで複数のバッファを有効にすることを試み、スケジューリングアルゴリズムにより、バッファデータを各バッファに均一に割り当て、1つのバッファだけが「奔走に疲れている」状況になることなく、少なくともシステムのスループットが向上します.
3、その他のミドルウェアまたはツールの補助、例えばメッセージミドルウェアがピークを削る役割を果たすことができ、各指標も改善される.
4、パラメータチューニング.ここでのパラメータとは,バッファプールのパラメータだけでなく,最大接続数,最大スレッド数,タイムアウト時間など多くの外部パラメータを指す.

四、まとめ


本論文では,二重Bufferバッファの設計原理と実現方式を詳細に述べ,TwinsBufferPoolに対して圧力測定を実施し,試験結果も分析した.
私の微信購読番号:技術送金に注目してください.
完全なテストレポートを表示したい場合は、サブスクリプション番号でキーワード:テストレポートに返信し、ダウンロードリンクを取得できます.
TwinsBufferPoolのソースコードを深く研究したい方は、購読番号でキーワード:バッファプールに返信してください.