kafkaソース解析4:RecordAccemulatorの関連コンポーネントBufferPool、CopyOWriteMap(下)
1665 ワード
CopyOWriteMap
締め括りをつける
kafkaのCopyOWriteMapは私達に日常の仕事で同時にデータ構造を設計することに対してとても良い構想を提供して、先にシーンを分析して、更にシーンの特徴(例えば読み書きの周波数)によって、しかも更にいくつかの合理的な設計パターンを利用します.ここまでRecordAcceumulatorの関連部品は解析済みです.今度はkafkaのネットデザインを分析するつもりです.
private final ConcurrentMap> batches;
前の解析RecordAcccmulatorでは、batchは各TopicPartionに対応するロット列を格納するために使用されます.マルチスレッド環境で使用されるので、CocurrentMapとして声明していますが、batchは読み書きが少ないシーンです.だから、kafkaはCopyOWriteMapというデータ構造をCopyOWriteを設計しました.読むのは可変ではないhashMapですが、COWモードは短いデータ遅延があります.kafkaはどう解決しますか? private Deque getOrCreateDeque(TopicPartition tp) {
Deque d = this.batches.get(tp);
if (d != null)
return d;
d = new ArrayDeque<>();
Deque previous = this.batches.putIfAbsent(tp, d);
if (previous == null)
return d;
else
return previous;
}
COW会のデータが一致しない問題の原因はCOWが書き込みロックだけをかけて読みロックをかけないためで、先に分析してみます.読みロックもあり、書き込みロックもあり、読みと書きの操作もあります.つまり同じ時間に読みと書きは一つしか実行できないので、読みを保証する時は最新値です.読みロックを外して書き込みだけすると、読むときに実行して読むと最新値ではないですが、batchのシーンは特殊で、一度だけ挿入されて更新されません.だからTopicPartationがあると、読むときにロックをかける必要がないので、COWのシーンとは完全に一致しています.だから、まずtをゲットして、暇の時にロックなしから書き込みロックなしにアップグレードするだけで、繰り返し挿入しないと保証されています. @Override
public synchronized V putIfAbsent(K k, V v) {
if (!containsKey(k))
return put(k, v);
else
return get(k);
}
このシーンでは、書き込み操作の実行機会が少なく、メッセージ数に関係なく、ロックの回数はTopicParttition数にのみ関連していますが、読んでもHashMapのロックなし操作によって、性能が向上し、データの整合性も回避されます.締め括りをつける
kafkaのCopyOWriteMapは私達に日常の仕事で同時にデータ構造を設計することに対してとても良い構想を提供して、先にシーンを分析して、更にシーンの特徴(例えば読み書きの周波数)によって、しかも更にいくつかの合理的な設計パターンを利用します.ここまでRecordAcceumulatorの関連部品は解析済みです.今度はkafkaのネットデザインを分析するつもりです.