如何创建可从现有更改日志主题恢复的状态存储?

时间:2018-01-11 18:20:07

标签: apache-kafka apache-kafka-streams

我正在使用流DSL来重复删除一个名为users的主题:

topology.addStateStore(Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore("users"), byteStringSerde, userSerde));                                                                                                                                                   

KStream<ByteString, User> users = topology.stream("users", Consumed.with(byteStringSerde, userSerde));                                                                                                                                                                      

users.transform(() -> new Transformer<ByteString, User, KeyValue<ByteString, User>>() {                                                                                                                                                                                     

    private KeyValueStore<ByteString, User> store;                                                                                                                                                                                                                          

    @Override                                                                                                                                                                                                                                                               
    @SuppressWarnings("unchecked")                                                                                                                                                                                                                                          
    public void init(ProcessorContext context) {                                                                                                                                                                                                                            
        store = (KeyValueStore<ByteString, User>) context.getStateStore("users");                                                                                                                                                                                           
    }                                                                                                                                                                                                                                                                       

    @Override                                                                                                                                                                                                                                                               
    public KeyValue<ByteString, User> transform(ByteString key, User value) {                                                                                                                                                                                               
        User user = store.get(key);                                                                                                                                                                                                                                         
        if (user != null) {                                                                                                                                                                                                                                                 
            store.put(key, value);                                                                                                                                                                                                                                          
            return new KeyValue<>(key, value);                                                                                                                                                                                                                              
        }                                                                                                                                                                                                                                                                   
        return null;                                                                                                                                                                                                                                                        
    }                                                                                                                                                                                                                                                                       

    @Override                                                                                                                                                                                                                                                               
    public KeyValue<ByteString, User> punctuate(long timestamp) {                                                                                                                                                                                                           
        return null;                                                                                                                                                                                                                                                        
    }                                                                                                                                                                                                                                                                       

    @Override                                                                                                                                                                                                                                                               
    public void close() {                                                                                                                                                                                                                                                   

    }                                                                                                                                                                                                                                                                       
}, "users"); 

鉴于此代码,Kafka Streams为users商店创建了一个内部更改日志主题。我想知道,是否有某些方法可以使用现有的users主题,而不是创建一个基本相同的更改日志主题?

PS。我看到StreamsBuilder说这是可能的:

  

但是,由于原始输入主题可用于恢复,因此未创建内部更改日志主题

但是按照InternalStreamsBuilder#table()InternalStreamsBuilder#createKTable()的代码,我没有看到它是如何实现这种效果的。

1 个答案:

答案 0 :(得分:1)

并非所有DSL在处理器API级别都可以做到 - 它使用了一些内部构件,这些内部构件不是公共API的一部分,可以实现您所描述的内容。

调用InternalTopologyBuilder#connectSourceStoreAndTopic()可以解决问题(参见InternalStreamsBuilder#table())。

对于关于重复数据删除的用例,您似乎需要两个主题(取决于您应用的重复数据删除逻辑)。通过changelog主题进行恢复可以进行基于密钥的更新,因此不会考虑值(也可能是重复数据删除逻辑的一部分)。