数仓项目中所遇问题及解决方法

1,582 阅读5分钟

Flink技术选型

​ 分别对主流的流计算框架:Storm,Storm Trident,Spark Streaming,Google Cloud Dataflow,Flink做了对比。基于微批量的Spark Streaming和Storm Trident延迟比较高,从这点就不适合我们的场景。Storm的延迟很低,但是数据一致性是At Least once,容错机制比较复杂,流控会比较抖动,这些方面都是不太适合。其中,Flink的一致性保证(1.4版本还支持了end-to-end一致性),延迟比较低,容错机制的开销是比较小的(基于Chandy-Lamport的分布式快照),流控是比较优雅的(算子之间的数据传输是基于分布式内存阻塞队列),应用逻辑与容错是分离的(算子处理和分布式快照checkpoint),基于以上我们认为flink是比较适合项目场景的。

Hive 分隔符的问题

将数据导入到Hive中该如何采用分隔符:

  • 普通情况'/001' 使用默认分隔符或者其他数据中不影响数据完整性的分隔符

  • 当数据字段中带有一些常见分隔符或者导入后出现条数不一致,字段增加的情况、说明分隔符选择的有问题

    这时候要采用 定长 的方法将数据切割进行导入


Kafka分布式系统的线上部署

线上部署的时候,JVM堆内存大小是越大越好么

  • 是否依赖Java系统自身内存处理数据

Java和Scala编程语言底层都是依赖于JVM,只要是使用JVM,考虑在JVM进程中来放置大量的数据。

  • 一条消息发送到消息中间件之后:
  • 一种处理方式,就是把这条数据先缓冲在自己的JVM内存里,然后过一段时间之后,再从自己的内存刷新到磁
  • 盘上去,这样可以持久化保存这条消息。

如果用类似上述的方式,依赖Java系统自身内存处理数据,比如说设计一个内存缓冲区,来缓冲住高并发写入的大

量消息,那么是有其缺陷的。最大的缺陷,其实就是JVM的GC问题,这个GC就是垃圾回收,JVM垃圾回收的时

候,有一种情况叫做stop the world,就是他会停止你的工作线程,就专门让他进行垃圾回收。

  • 另一种处理方式、依赖OS Cache而不是JVM

    • 类似Kafka、Elasticsearch等分布式中间件系统,虽然也是基于JVM运行的,但是他们都选择了依赖OS

      Cache来管理大量的数据。

    • 具体以kafka为例,其典型的运行流程如下:

+ 写一条数据到kafka、实际上会将数据写入磁盘文件、但是在写入之前会进入到OS Cache,也就是操作系统管理的内存空间,过一段时间之后,操作系统会选择讲数据持久化到磁盘中。

+ 消费数据的时候会优先从Os Cache中读取数据

+ 写数据和读数据都是依托于Os Cache来进行的,完全依托操作系统级别的内存区域来进行,读写性能

  都很高。

解决方法

  • 针对类似Kafka、Elasticsearch这种生产系统部署的时候,应该要给JVM比如6GB或者几个GB的内存就可以了,

    因为他们可能不需要耗费过大的内存空间,不依赖JVM内存管理数据。

  • 给Os Cache分配足够的空间

总结

  • 在线上生产系统引入任何技术的时候,都应该先对这个技术的原理,甚至源码进行深入的理解,知道他具体的

工作流程是什么,然后针对性的合理设计生产环境的部署方案,保证最佳的生产性能。


kafka的副本写入机制和消息一致性

起初为了保证kafka数据的容错和一致性设置消息的副本数为3,在写入大量数据的时候发现效率有些慢

定位问题
  • 定量排查确定为非网络磁盘等硬件问题,查看kafka官网了解到kafka消息的副本写入机制,其通过水位机制保证消息的一致性,有点类似于木桶定理。
  • 假设分区的副本为3,其中副本0是 Leader,副本1和副本2是 follower,并且在 ISR 列表里面。虽然副本0已经写入了 Message4,但是 Consumer 只能读取到 Message2。因为所有的 ISR 都同步了 Message2,只有 High Water Mark 以上的消息才支持 Consumer 读取,而 High Water Mark 取决于 ISR 列表里面偏移量最小的分区,对应于上图的副本2,这个很类似于木桶原理。
  • 这样做的原因是还没有被足够多副本复制的消息被认为是“不安全”的,如果 Leader 发生崩溃,另一个副本成为新 Leader,那么这些消息很可能丢失了。如果我们允许消费者读取这些消息,可能就会破坏一致性。试想,一个消费者从当前 Leader(副本0) 读取并处理了 Message4,这个时候 Leader 挂掉了,选举了副本1为新的 Leader,这时候另一个消费者再去从新的 Leader 读取消息,发现这个消息其实并不存在,这就导致了数据不一致性问题。
分析问题

​ 引入了 High Water Mark 机制,会导致 Broker 间的消息复制因为某些原因变慢,那么消息到达消费者的时间也会随之变长(因为我们会先等待消息复制完毕)。延迟时间可以通过参数 replica.lag.time.max.ms 参数配置,它指定了副本在复制消息时可被允许的最大延迟时间。

问题解决

通过调小副本个数和 replica.lag.time.max.ms 参数从而降低延迟,提高写入速度


Kafka的乱序问题


数据的倾斜问题及解决办法


项目的版本迭代