JAVA-基础语法-多线程基础-CopyOnWrite-3

举报
Photon2 发表于 2020/12/22 12:18:00 2020/12/22
【摘要】 JAVA-基础语法-多线程基础-
CopyOnWrite 思想在Kafka源码中的运用

在Kafka的内核源码中,有这么一个场景,客户端在向Kafka写数据的时候,会把消息先写入客户端本地的内存缓冲,然后在内存缓冲里形成一个Batch之后再一次性发送到Kafka服务器上去,这样有助于提升吞吐量。

话不多说,大家看下图:

img

这个时候Kafka的内存缓冲用的是什么数据结构呢?大家看源码:

private final ConcurrentMap<TopicPartition, Deque<RecordBatch>> batches = 
new CopyOnWriteMap<TopicPartition, Deque<RecordBatch>>();

这个数据结构就是核心的用来存放写入内存缓冲中的消息的数据结构,要看懂这个数据结构需要对很多Kafka内核源码里的概念进行解释,这里先不展开。

但是大家关注一点,他是自己实现了一个CopyOnWriteMap,这个CopyOnWriteMap采用的就是CopyOnWrite思想。

我们来看一下这个CopyOnWriteMap的源码实现:

 // 典型的volatile修饰普通Map
private volatile Map<K, V> map;
@Override
public synchronized V put(K k, V v) {
   // 更新的时候先创建副本,更新副本,然后对volatile变量赋值写回去
   Map<K, V> copy = new HashMap<K, V>(this.map);
   V prev = copy.put(k, v);
   this.map = Collections.unmodifiableMap(copy);
   return prev;
}
@Override
public V get(Object k) {
   // 读取的时候直接读volatile变量引用的map数据结构,无需锁
   return map.get(k);
}

所以Kafka这个核心数据结构在这里之所以采用CopyOnWriteMap思想来实现,就是因为这个Map的key-value对,其实没那么频繁更新。

也就是TopicPartition-Deque这个key-value对,更新频率很低。

但是他的get操作却是高频的读取请求,因为会高频的读取出来一个TopicPartition对应的Deque数据结构,来对这个队列进行入队出队等操作,所以对于这个map而言,高频的是其get操作。

这个时候,Kafka就采用了CopyOnWrite思想来实现这个Map,避免更新key-value的时候阻塞住高频的读操作,实现无锁的效果,优化线程并发的性能。

相信大家看完这个文章,对于CopyOnWrite思想以及适用场景,包括JDK中的实现,以及在Kafka源码中的运用,都有了一个切身的体会了。


如果你能在面试时说清楚这个思想以及他在JDK中的体现,并且还能结合知名的开源项目 Kafka 的底层源码进一步向面试官进行阐述,面试官对你的印象肯定大大的加分。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。