private Deque<RecordBatch> getOrCreateDeque(TopicPartition tp) {
/**
* CopyonWriteMap:
* get
* put
*
*/
//直接从batches里面获取当前分区对应的存储队列
Deque<RecordBatch> d = this.batches.get(tp);
//我们现在用到是场景驱动的方式,代码第一次执行到这儿的死活
//是获取不到队列的,也就是说d 这个变量的值为null
if (d != null)
return d;
//代码继续执行,创建出来一个新的空队列,
d = new ArrayDeque<>();
//把这个空的队列存入batches 这个数据结构里面
Deque<RecordBatch> previous = this.batches.putIfAbsent(tp, d);
if (previous == null)
return d;
else
//直接返回新的结果
return previous;
}
CopyOnWriteMap
/**CopyOnWriteMap的这样的一个数据类型。
//这个数据结构在jdk里面是没有的,是kafka自己设计的。
//这个数据结构设计得很好,因为有了这个数据结构
//整体的提升了封装批次的这个流程的性能!!
//JDK juc包下面:CopyOnWriteArrayList*/
this.batches = new CopyOnWriteMap<>();
/**
* A simple read-optimized map implementation that synchronizes only writes and does a full copy on each modification
*
* 1) 这个数据结构是在高并发的情况下是线程安全的。
* 2) 采用的读写分离的思想设计的数据结构
* 每次插入(写数据)数据的时候都开辟新的内存空间
* 所以会有个小缺点,就是插入数据的时候,会比较耗费内存空间。
* 3)这样的一个数据结构,适合写少读多的场景。
* 读数据的时候性能很高。
*
* batchs这个对象存储数据的时候,就是使用的这个数据结构。
* 对于batches来说,它面对的场景就是读多写少的场景。
*
*batches:
* 读数据:
* 每生产一条消息,都会从batches里面读取数据。
* 假如每秒中生产10万条消息,是不是就意味着每秒要读取10万次。
* 所以绝对是一个高并发的场景。
* 写数据:
* 假设有100个分区,那么就是会插入100次数据。
* 并且队列只需要插入一次就可以了。
* 所以这是一个低频的操作。
*
* 高性能:
*
* 读写分离读设计方案:适合的场景就是读多写少。
* 读多:
* 写少:
*/
public class CopyOnWriteMap<K, V> implements ConcurrentMap<K, V> {
/**
* 核心的变量就是一个map
* 这个map有个特点,它的修饰符是volatile关键字。
* 在多线程的情况下,如果这个map的值发生变化,其他线程也是可见的。
*
* get
* put
*/
private volatile Map<K, V> map;
/**
* 没有加锁,读取数据的时候性能很高(高并发的场景下,肯定性能很高)
* 并且是线程安全的。
* 因为人家采用的读写分离的思想。
* @param k
* @return
*/
@Override
public V get(Object k) {
return map.get(k);
}
/**
* 1):
* 整个方法使用的是synchronized关键字去修饰的,说明这个方法是线程安全。
* 即使加了锁,这段代码的性能依然很好,因为里面都是纯内存的操作。
* 2)
* 这种设计方式,采用的是读写分离的设计思想。
* 读操作和写操作 是相互不影响的。
* 所以我们读数据的操作就是线程安全的。
*3)
* 最后把值赋给了map,map是用volatile关键字修饰的。
* 说明这个map是具有可见性的,这样的话,如果get数据的时候,这儿的值发生了变化,也是能感知到的。
* @param k
* @param v
* @return
*/
@Override
public synchronized V put(K k, V v) {
//新的内存空间
//读写分离
//往新的内存空间里面插入
//读,读数据就老读空间里面去
Map<K, V> copy = new HashMap<K, V>(this.map);
//插入数据
V prev = copy.put(k, v);
//赋值给map
this.map = Collections.unmodifiableMap(copy);
return prev;
}
}