kafkaソース解析4:RecordAccemulatorの関連コンポーネントBufferPool、CopyOWriteMap(下)

1665 ワード

CopyOWriteMap
    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のネットデザインを分析するつもりです.