我必须为事件数据编写一个ETL程序,将事件加载到Kafka中,因此在加载器调用中我得到一系列事件。在内部加载器中,我需要查看每个事件,并根据某些参数,我需要确定其类别,该类别与一些Kafka主题一对一映射,应该在其中编写。他们写的卡夫卡主题不超过20个。
所以我怀疑是否应该缓存地图中看到的主题如下:(假设我已经启动了一个线程来划分它们之间的事件并尝试并行加载到Kafka中)
class Loader {
private static Map<String, String> eventCategoryVsKafkaTopic = new HashMap<String, String>();
ReadWriteLock lock = new ReentrantReadWriteLock();
public static void load(IEvent[] events) {
for(IEvent[] event) {
String eventCategory = getEventCategory(event);
lock.readLock().lock();
if(eventCategoryVsKafkaTopic.get(eventCategory) != null) {
loadToKafka(event, eventCategoryVsKafkaTopic.get(eventCategory));
}
lock.readLock().unlock();
String kafkaTopic = generateKafkaTopicFromEvent(event);
loadToKafka(event, kafkaTopic);
lock.writeLock().lock();
eventCategoryVsKafkaTopic.put(eventCategory, kafkaTopic); // Its fine, if some other thread has written it in between, as the topic will be the same so overwrite is not an issue
lock.writeLock().unlock();
}
}
}
我觉得锁定会有太大的影响并且可能会降低性能,而不是每次只是动态创建主题,如下所示:(再次假设我已经启动了一个线程和分布式事件来加载它们并行)
class Loader {
public static void load(IEvent[] events) {
for(IEvent[] event) {
String kafkaTopic = generateKafkaTopicFromEvent(event);
loadToKafka(event, kafkaTopic);
}
}
}
请建议哪一个是处理主题生成的更好方法,并且在这里涉及锁定。
答案 0 :(得分:1)
简短回答:让所有线程争夺每个已处理事件的一个锁可能会更慢。在不知道更多的情况下,生成主题名称可能非常快。
答案很长: 如果可能,尝试构建并发应用程序,其中线程尽可能少地进行通信。在所有工作线程中共享这样的状态会产生很多争用。
如果生成该主题需要花费大量时间,那么缓存它是一个好主意。但是,如果只有20个主题,则应将其本地缓存到每个线程,以避免每个线程为每个正在处理的事件争用相同的锁。
基本模型是通过某些并发队列来分隔消费者和生产者。让消费者在他们自己的线程中运行但与其他消费者不共享任何状态。消费者可以根据需要在本地缓存映射。