通过阅读Flask-AppBuilder源码为Superset正确配置LDAP
前言由于公司LDAP奇怪的信息管理,导致superset按照官方文档配置LDAP的时候,遇到一系列问题,不是认证失败,就是认证信息不合理。因此开始漫长的阅读Flask-AppBuilder源码,来正确的配置LDAP。
配置过程
1、在superset的配置文件中,开启Flask-AppBuilder的日志输出。
1234# Whether to bump the logging level to ERROR on the flask_appbuilder package# Set to False if/when debugging FAB related issues like# permission managementSILENCE_FAB = False
2、正确的配置入下
12345678910AUTH_LDAP_SERVER = "ldap://sdsdsds:389"AUTH_LDAP_SEARCH = "DC=xx,DC=cc,DC=com"# see flask_appbuilder.security.manager.Base ...
LSM基本概念与其经典实现Level-DB
前言
LSM 是以牺牲读取性能以及空间利用率为代价而换取顺序写入性能的。因此,对LSM结构的优化目标就是想办法提高读取性能和空间利用率。读取性能的瓶颈在于读写放大以及合并压缩过程的抖动。
LSM经典实现Level-DB:Level引入分层机制
1、将最近最新写入的kv存储在内存数据结构中,如红黑树,跳表等。 那么问题是何时将此数据结构dump到磁盘?最简单的是根据其大小的区别,然而在dump之前我们不能继续向其中写入数据,因此在内存中应该存在一个活跃内存表和一个不变内存表,二者相互交替,周期性的将不变内存表dump到内存中形成一个分段文件。
2、为了优化LSM的读取性能:
LSM结构引入了分层设计的思想。将所有的kv文件分为c0-ck 共k+1层。c0层是直接从不变的内存表中dump下的结果。而c1-ck是发生过合并的文件。由于ci+1 是ci中具有重叠部分的文件合并的产物,因此可以说在同一层内是不存在重叠key的,因为重叠key已经在其上一层被合并了。那么只有c0层是可能存在重叠的文件的。所以当要读取磁盘上的数据时,最坏情况下只需要读取c0的所有文件以及c1-ck每一层中的一 ...
初识paimon && Spark Catalog
前言由于公司的业务场景涉及海量的数据更新和删除,因此一直对擅长处理海量数据更新的数据湖格式Apache paimon感兴趣。虽然Hudi对数据更新支持的也不错,但是经过测试,无论是吞吐量还是资源消耗都不能令人满意。究其根本像hudi、iceberg等数据湖格式在处理数据更新上都是通过简单粗暴的合并文件实现的,存在较大的写放大问题。
在了解到Apache paimon是通过LSM实现海量数据更新后,可以预见的到海量数据更新对paimon不会存在问题,因为像使用LSM技术的kudu、doris、hbase等存储引擎都是非常成熟且久经考验的。经过测试Apache paimon的吞吐量是hudi MOR表的3-5倍,同时资源占用(IO和CPU和内存)也大幅下降。
PR on Paimon
修复Date类型作为分区值的格式化问题,由于可能会造成与老版本(Flink Table Store)的兼容性问题,暂时无法进行合并。但是对于我们来说没有兼容性问题,因此在我们的内部版本中使用。https://github.com/apache/incubator-paimon/pull/853
Spark ...
Spark SQL合并小文件
前言Hive 表中太多的小文件会影响数据的查询性能和效率,同时加大了 HDFS NameNode 的压力。
方法1:Base Spark SQL Partitioning Hints123456789101112131415161718192021222324252627282930313233343536373839404142434445464748SELECT /*+ COALESCE(3) */ * FROM t;SELECT /*+ REPARTITION(3) */ * FROM t;SELECT /*+ REPARTITION(c) */ * FROM t;SELECT /*+ REPARTITION(3, c) */ * FROM t;SELECT /*+ REPARTITION_BY_RANGE(c) */ * FROM t;SELECT /*+ REPARTITION_BY_RANGE(3, c) */ * FROM t;SELECT /*+ REBALANCE */ * FROM t;SELECT /*+ REBALANCE(3) */ * FROM t;SELE ...
Spark事件总线源码分析
前言Spark中很多组件之间是靠事件消息实现通信的,之前分析了一下Spark中RPC机制,RPC和事件消息机制目的都是实现组件之间的通信,前者解决远程通信问题,而后者则是在本地较为高效的方式。Spark中大量采用事件监听这种方式,实现driver端的组件之间的通信。
ListenerBus1234567891011/** * An event bus which posts events to its listeners. */private[spark] trait ListenerBus[L <: AnyRef, E] extends Logging { private[this] val listenersPlusTimers = new CopyOnWriteArrayList[(L, Option[Timer])] // Marked `private[spark]` for access in tests. private[spark] def listeners = listenersPlusTimers.asScala.map(_._1).asJ ...
Scala特殊语法指南
柯里化在Scala中,定义了两组空括号()()的方法称为“柯里化方法”。这意味着该方法采用多个参数列表,每个参数列表都由一组空括号表示。
例如,考虑以下方法定义:
1def add(a: Int)(b: Int): Int = a + b
在这种情况下,add是一个柯里化方法,它以单独的参数列表接受两个整数参数a和b。要调用此方法,您首先需要提供a的值,然后是b。这看起来像:
1val result = add(1)(2) // result是3
柯里化方法在函数式编程中非常有用,可以允许部分函数应用,函数组合和其他高阶编程技术。
123456789101112131415161718192021222324252627282930313233/** * Execute a block of code that evaluates to Unit, stop SparkContext if there is any uncaught * exception * * NOTE: This method is to be called by the driver-side compon ...
理解Spark ESS
spark shuffle大概过程
spark shuffle分为两部分shuffle write和shuffle read。
在map write端,对每个task的数据,不管是按key hash还是在数据结构里先聚合再排序,最终都会将数据写到一个partitionFile里面,在partitionFile里面的数据是partitionId有序的,外加会生成一个索引文件,索引包含每个partition对应偏移量和长度。
而reduce read 端就是从这些partitionFile里面拉取相应partitionId的数据, 然后再进行聚合排序。
现在我们在来看下external shuffle service(ESS),其乍从其名字上看,ESS是spark分布式集群为存储shuffle data而设计的分布式组件。但其实它只是Spark通过Executor获取Shuffle data块的代理。
我们可以理解为ESS负责管理shuffle write端生成的shuffle数据,ESS是和yarn一起使用的, 在yarn集群上的每一个nodemanager上面都运行一个ESS,是一个常 ...
修复Kylin4.0.x不正常的push-down query查询耗时
问题描述
发现kylin4.0.x中的push-down query对于简单的明细查询select * from table limit 10非常慢,本来应该秒级响应,却往往耗时几分钟,并且查询的数据集越大,耗时越长,这非常不正常。BI工具往往会执行明细查询,进行数据展示,不正常的查询时长,往往造成BI工具超时,返回错误信息,这对用户体验非常不友好
通过排查发现,在这类非常简单的明细查询的查询计划中,竟然有shuffle过程,简直离谱。
线上定位问题代码当然离不开Arthas了,然后仔细阅读Kylin源码,找到问题代码所在!!!
修改源码
Kylin执行push-down query的主要逻辑集中在org.apache.kylin.query.pushdown.SparkSqlClient中,代码质量简直不忍直视,出现这个问题的主要原因就是代码质量太低。
在org.apache.kylin.query.pushdown.SparkSqlClient#DFToList中,不必要的Spark DataFrame类型转换transform是这个问题的主要原因。
修改后的代码如下org. ...
Apache Superset添加EXCLUDE函数
前言
因为业务需求,需要一个类似于Tableau中的exclude函数的功能。
例如:
若要查看一段时间内每个国家/地区的平均血压,但不按男性和女性进行划分,请使用 EXCLUDE 详细级别表达式 {EXCLUDE [Sex] : AVG[Average blood pressure]}。
这个函数的功能对于业务来说非常重要,但是Apache Superset中没有此类功能,因此需要修改Apache Superset源码,为其添加上这个功能!这是一个不小的挑战!
新功能实现计划
1、获取由用户拖拽生成的BI图表的SQL语句。
2、拦截SQL语句进行改写,例如{EXCLUDE [Sex] : AVG[blood-pressure]}:
1、去除原SQL语句中的Sex维度信息和针对Sex的过滤条件,得到新的SQL
2、基于新的SQL发出对于blood-pressure度量来说是正确的聚合SQL,得到正确结果集
3、获取正确结果集中排除Sex维度后正确的blood-pressure度量聚合值。
4、利用正确的结果集中正确的部分,对原SQ ...
基于LockSupport进行线程间的同步
描述看到一道有意思的Java多线程面试题:要求两个线程交替打印a和b,且都打印50次,且a必须先打印。
这是一个关于线程同步的问题,显然有比较多的解法,比如利用synchronized、CyclicBarrier等来实现。下面是利用LockSupport的代码。
123456789101112131415161718192021222324252627282930313233343536/** * 要求两个线程交替打印a和b,且都打印50次,且a必须先打印。 * 实现两个线程之间的同步 */public class LockSupportDemo { public static void main(String[] args) throws InterruptedException { Thread[] threads = new Thread[2]; threads[0] = new Thread(() -> { int i = 51; while (i-- > 1 ...