Apache kylin進階——Slow Query SQL改造篇
一、慢查詢(Slow Query SQL)定性
在Apache kylin中,一旦cube(Apache Kylin)經過build、refresh或merge後,將對外提供基於ODBC、JDBC、RESTful API等介面的亞秒級OLAP功能;儘管如此,在生產環境中,我們仍然需要記錄執行結果很慢的sql語句,並發出告警,以便分析、優化。
在kylin的query engine 端,有一個後台線程BadQueryDetector不斷去發現前端請求的錯誤的sql語句,當然包括slow query sql,核心代碼如下:
public void run() {n while (true) {n try {n Thread.sleep(detectionInterval);n } catch (InterruptedException e) {n // stop detection and exitn return;n }nn try {n detectBadQuery();n } catch (Exception ex) {n logger.error("", ex);n }n }n }n
BadQueryDetector#detectBadQuery 代碼如下:
private void detectBadQuery() {n long now = System.currentTimeMillis();n ArrayList<Entry> entries = new ArrayList<Entry>(runningQueries.values());n Collections.sort(entries);nn // report if query running longn for (Entry e : entries) {n float runningSec = (float) (now - e.startTime) / 1000;n if (runningSec >= alertRunningSec) {n notify("Slow", runningSec, e.startTime, e.sqlRequest.getProject(), e.sqlRequest.getSql(), e.thread);n dumpStackTrace(e.thread);n } else {n break; // entries are sorted by startTimen }n }nn // report if low memoryn if (getSystemAvailMB() < alertMB) {n logger.info("System free memory less than " + alertMB + " MB. " + entries.size() + " queries running.");n }n }n
即當sql的執行時間大於 alertRunningSec,kylin將其定性為 slow query sql,alertRunningSec的獲取如下:
public BadQueryDetector() {n super("BadQueryDetector");n this.setDaemon(true);n this.kylinConfig = KylinConfig.getInstanceFromEnv();n this.detectionInterval = kylinConfig.getBadQueryDefaultDetectIntervalSeconds() * 1000;n this.alertMB = 100;n this.alertRunningSec = kylinConfig.getBadQueryDefaultAlertingSeconds();nn initNotifiers();n }n
public int getBadQueryDefaultAlertingSeconds() {n return Integer.parseInt(getOptional("kylin.query.badquery.alerting.seconds", "90"));n }n
可見當sql的響應時間超過90秒,kylin才會將其視為slow query sql, 顯然,對於一個提供實時查詢的OLAP系統,這個指標的設置是不合理的。在${KYLIN_HOME}/conf/kylin.properties中修改如下:
kylin.query.badquery.alerting.seconds=3
二、告警改造
當前 slow query sql的發現及輸出採用觀察者模式,用戶可以通過實現介面 Notifier 自定義觀察者,然後註冊給BadQueryDetector。
public interface Notifier {n void badQueryFound(String adj, float runningSec, long startTime, String project, String sql, Thread t);n }n
public void registerNotifier(Notifier notifier) {n notifiers.add(notifier);n }n
當前BadQueryDetector有兩個內置觀察者,LoggerNotifier和PersistenceNotifier,其中LoggerNotifier將slow query sql 記錄到日誌;PersistenceNotifier將記錄至元數據(一般是hbase)。
出於運維需要,我們可以自定義觀察者,將slow qeury sql發送到業務負責人的郵箱或者手機。如:
public class EmailNotifier implements Notifier {n void badQueryFound(String adj, float runningSec, long startTime, String project, String sql, Thread t){nn //send a email;n }n }n
三、slow query sql 在元數據中的位置:
當元數據配置採用默認配置時,即:
kylin.metadata.url=kylin_metadata@hbase n
元數據在以下位置:
1)表 : kylin_metadata nn2)rowKey : /bad_query/${project_name}.json // 用UTF-8 編碼nn3) column: f:c // content: slow sql的具體內容,需先用UTF-8解碼,然後用 JsonSerializer 反序列化nn column: f:t //timestamp : 更新該條記錄的 時間戳n
推薦閱讀:
※大數據那些事(30):Presto之坑和蘿蔔傻子和騙子的故事
※Azkaban二次開發3-Hadoop任務提交方式改造
※SparkSQL中的Sort實現(二)
※5分鐘 Hadoop Shuffle 優化
※嫌棄Hadoop?可能是你的打開方式有問題