Kafka交付语义的前半段producer:ack=all retries=100 无需关心,关键在于后半段consumer的offset如何选择!
我司是 MySQL–>maxwell–>kafka–>ss+phoenix–>phoenix+hbase架构,那么在设计上 选择kafka的自身维护offset的方式 至少1次消费语义–>【断批还原】;且巧妙的使用【upsert】语法,让批次数据无论是异常中断重复或者业务/maxwell重复发送数据,那么要巧妙的设计PK主键,使已存在的数据做update,不存在的数据做insert。不会让数据变成多条,始终和源端一致/始终重复计算结果保存不重复,从而做到真正的幂等性!
hbase的put–》upsert语法
map mysql1条数据–》Phoenix 1条数据 没有shuffle
但是假如选择【外部存储,精准消费一次语义】,那么代码级别是很难实现 事务性的 。因为这是【两段式】提交,并没有事务回滚机制。比如数据结果更新失败,但是offset已经维护完成,这是很致命的。想要达到事务级别: 数据、offset要不一起保存成功,要不一起失败。
所以一般会巧妙设计 数据+offset结合,一次性输出,以保证数据和offset都被更新或者两者不被更新。
比如主键含有offset的值,就相同主键数据就会存在多条;反之offset不设置为主键字段,仅仅作为数据的补充部分,那么数据不会重复。