CDH是Cloudera早期推出的一個開源平臺版本,它實質上成為了Apache Hadoop生態系統內公認的安裝與管理平臺,專為企業級需求量身打造。CDH為用戶提供了即裝即用的企業級解決方案。通過整合Hadoop與另外十多項關鍵開源項目,Cloudera構建了一個功能強大的系統,能夠支持從端到端的大數據工作流處理。CDH的免費版本在6.3.2版本后停止了更新,轉而專注于商業版本的發布。盡管如此,許多企業仍選擇利用該免費版本的CDH成功部署了Hadoop大數據平臺。
簡單來說:CDH 是一個擁有集群自動化安裝、中心化管理、集群監控、報警功能的一個工具(軟件),使得集群的安裝可以從幾天的時間縮短為幾個小時,運維人數也會從數十人降低到幾個人,極大的提高了集群管理的效率。
1、前言
CDH的配置庫支持Mysql,Oracle及postgresql數據庫,大部分公司使用的是Mysql作為CDH的配置庫,在高可用場景中,Mysql容易成為單點故障的關鍵點,而OceanBase天然具備高可用特性,有必要研究切換CDH的配置庫為OceanBase,如此就有了這篇文章。
2、遇到的問題
問題一:在安裝啟動CM啟動過程中,第一步將初始化配置數據庫SQL的時候,有檢查數據庫的引擎,必須是InnoDB,如圖1,原因是OB執行show engines返回的是OceanBase,如圖2。(OB數據庫可定制show engines輸出來支持就好了)
圖1-CM啟動報錯圖
圖2-OB執行show engines
問題2:通過重新編譯源碼,繞過CM對數據庫引擎檢查后,報不支持連續修改的錯誤,報錯見圖3-1及圖3-2,原因是OB作為分布式數據庫,為分布式一致性不支持連續執行ddl修改操作,需分步驟執行才能成功,如圖4。(OB數據庫能社加個開關支持連續修改就好了)
圖3-1,通過逗號連接,連續修改數據庫表報錯-1
圖3-2連續修改數據庫表,上條未執行完執行下一條報錯
圖4-需改造CM的ddl語句
應對以上兩個問題,經和社區大佬分析、評估及指導后,做出以下兩個解決方案:
- 修改OB源碼,編譯并安裝修改后的Observer,繞過CM的show engines的檢查;
- 修改CM的ddl,繞過OB不支持連續執行的ddl;
下面以此操作步驟為線,記錄這個過程。
3、編譯OceanBase、安裝和租戶創建
1. 下載源碼
git clone https://github.com/oceanbase/oceanbase.git
2. 修改源碼
vim src/observer/virtual_table/ob_all_virtual_engine_table.cpp
第58行OceanBase改為InnoDB,如圖5
圖5-OceanBase改為InnoDB
3. 編譯源碼
編譯流程見?編譯方法?,編譯后新的RPM包在oceanbase/build_rpm目錄下,RPM包見圖6
圖6-編譯后的RPM包
4. 安裝及啟動
安裝oceanbase-ce-4.1.0.0-1.el7.x86_64.rpm
rpm -ivh oceanbase-ce-4.1.0.0-1.el7.x86_64.rpm
拷貝安裝目錄bin下observer文件,使用OBD部署一個4.0環境,替換bin下observer文件為新文件,并啟動,如圖7;修改后的show engines如圖8
圖7-啟動OB
圖8-show engine
5. 準備用于安裝CDH的租戶及用戶
登錄系統root,并創建租戶
CREATE RESOURCE UNIT unit001 MAX_CPU 8,MEMORY_SIZE '10G';
CREATE RESOURCE POOL pool001 UNIT='unit001',UNIT_NUM=1,ZONE_LIST=('zone1');
CREATE TENANT IF NOT EXISTS cdhCHARSET='utf8mb4',PRIMARY_ZONE='zone1',RESOURCE_POOL_LIST=('pool001')SET ob_tcp_invited_nodes='%';
登錄租戶root,并準備用戶 bigdata 密碼 Bigdata@cdh_test,并創建cmdb數據庫和hive數據庫
alter user root identified by 'Root@cdh_test' ;
CREATE USER 'bigdata' IDENTIFIED BY 'Bigdata@cdh_test';
CREATE DATABASE cmdbDEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
CREATE DATABASE hive DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
GRANT ALL PRIVILEGES ON *.* TO bigdata WITH GRANT OPTION;
4、安裝CDH并配置CM
(省略1千字的安裝過程)
tar -zxvf cm6.3.1-redhat7.tar.gz
cd /home/shaqf/cm6.3.1/RPMS/x86_64
rpm -ivh cloudera-manager-daemons-6.3.1-1466458.el7.x86_64.rpm
yum install cloudera-manager-server-6.3.1-1466458.el7.x86_64.rpm
1. 修改數據庫配置文件
vim /etc/cloudera-scm-server/db.properties
內容
com.cloudera.cmf.db.type=mysql
com.cloudera.cmf.db.host=192.168.21.17:2881
com.cloudera.cmf.db.name=cmdb
com.cloudera.cmf.db.user=bigdata@cdh
com.cloudera.cmf.db.setupType=EXTERNAL
com.cloudera.cmf.db.password=Bigdata@cdh_test
啟動CM
service cloudera-scm-server restart
查看日志:more ?/var/log/cloudera-scm-server/cloudera-scm-server.log,報錯如圖9
圖9-執行ddl報錯
2. 修改ddl
修改/opt/cloudera/cm/schema/mysql下的所有ddl文件,修改如圖4;
這里使用java進行批量修改,代碼如下:
import java.io.*;
import java.util.HashSet;
import java.util.Set;public class StartMain {public static void main(String[] args) throws Exception {File pathFile = new File("C:\\Users\\sha\\Desktop\\mysql\\");Set<File> fileSet = new HashSet<>();findFiles(pathFile, fileSet);for (File file:fileSet) {RandomAccessFile raf = new RandomAccessFile(file,"r");String line = null;String preLine = null;StringBuffer sbfDDL = new StringBuffer();while ((line = raf.readLine()) != null){if(line.trim().startsWith("alter table ")){preLine = line;sbfDDL.append(line);sbfDDL.append("\n");} else if (line.trim().startsWith("add index ") && line.trim().endsWith(",")){line = line.replaceAll(",",";");sbfDDL.append(line);sbfDDL.append("\n");sbfDDL.append(preLine);sbfDDL.append("\n");} else {sbfDDL.append(line);sbfDDL.append("\n");}}BufferedWriter bufWriter = null;try {bufWriter = new BufferedWriter(new FileWriter(file, false));// 覆蓋bufWriter.write(sbfDDL.toString());bufWriter.flush();} catch (Exception e) {e.printStackTrace();} finally {if (bufWriter != null) {try {bufWriter.close();} catch (IOException e) {e.printStackTrace();}}}}}private static void findFiles(File file, Set<File> files) {if (file.isDirectory()) {File[] fileArray = file.listFiles();if (fileArray != null) {for (int i = 0; i < fileArray.length; i++) {findFiles(fileArray[i], files);}}} else {files.add(file);}}
}
上傳修改后的ddl,清空cmdb數據庫,再次執行重啟任務,有關命令如下
drop database cmdb;
CREATE DATABASE cmdb
DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
service cloudera-scm-server restart
查看日志:more ?/var/log/cloudera-scm-server/cloudera-scm-server.log,報錯如圖9
圖9-ddl報錯
3. 繼續修改ddl
繼續修改/opt/cloudera/cm/schema/mysql下的所有ddl文件,修改如圖4;
這里使用java到Linux上進行批量修改,代碼如下:
import java.io.*;
import java.util.HashSet;
import java.util.Set;public class StartMain {public static void main(String[] args) throws Exception {File pathFile = new File("/opt/cloudera/cm/schema/mysql");Set<File> fileSet = new HashSet<>();findFiles(pathFile, fileSet);for (File file:fileSet) {RandomAccessFile raf = new RandomAccessFile(file,"r");String line = null;String preLine = null;StringBuffer sbfDDL = new StringBuffer();boolean isAlterLine = false;while ((line = raf.readLine()) != null){if(line.trim().startsWith("alter table ")){preLine = line;sbfDDL.append(line);sbfDDL.append("\n");isAlterLine = true;} else if (line.trim().startsWith("add ") && line.trim().endsWith(",")){line = line.replaceAll(",","; select sleep(1); ");sbfDDL.append(line);sbfDDL.append("\n");sbfDDL.append(preLine);sbfDDL.append("\n");} else if (line.trim().startsWith("modify ") && line.trim().endsWith(",")){line = line.replaceAll(",","; select sleep(1); ");sbfDDL.append(line);sbfDDL.append("\n");sbfDDL.append(preLine);sbfDDL.append("\n");} else if (line.trim().startsWith("drop ") && line.trim().endsWith(",")){line = line.replaceAll(",","; select sleep(1); ");sbfDDL.append(line);sbfDDL.append("\n");sbfDDL.append(preLine);sbfDDL.append("\n");} else {if(isAlterLine && line.trim().endsWith(";")){line = line.replaceAll(";","; select sleep(1); ");}sbfDDL.append(line);sbfDDL.append("\n");}}BufferedWriter bufWriter = null;try {bufWriter = new BufferedWriter(new FileWriter(file, false));// 覆蓋bufWriter.write(sbfDDL.toString());bufWriter.flush();} catch (Exception e) {e.printStackTrace();} finally {if (bufWriter != null) {try {bufWriter.close();} catch (IOException e) {e.printStackTrace();}}}}}private static void findFiles(File file, Set<File> files) {if (file.isDirectory()) {File[] fileArray = file.listFiles();if (fileArray != null) {for (int i = 0; i < fileArray.length; i++) {findFiles(fileArray[i], files);}}} else {files.add(file);}}}
修改ddl文件:
vim 05021_cmf_schema.mysql.ddl
vim 05300_cmf_schema.mysql.ddl
分別注釋掉下面兩行(05021_cmf_schema.mysql.ddl新增IDX_CLIENT_CONFIG_HOST索引,05300_cmf_schema.mysql.ddl又刪除IDX_CLIENT_CONFIG_HOST索引,而05300_cmf_schema.mysql.ddl刪除索引會報錯)
--alter table CLIENT_CONFIGS
-- add index IDX_CLIENT_CONFIG_HOST (HOST_ID); select sleep(1);-- alter table CLIENT_CONFIGS
-- drop index IDX_CLIENT_CONFIG_HOST; select sleep(1);
如圖-10修復所有即建索引又指定主鍵的ddl
圖-10?在建表時不能即建索引又指定主鍵(修復方法:索引單獨創建)
確保ddl修改完成后,清空cmdb數據庫,再次執行重啟任務,有關命令如下
drop database cmdb;
CREATE DATABASE cmdb DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
service cloudera-scm-server restart
查看日志:more /var/log/cloudera-scm-server/cloudera-scm-server.log,報錯如圖-11,報錯不影響接入系統(后續得觀察運行穩定性)
圖-11?啟動報錯
5、登錄系統
登錄地址:http://192.168.25.47:7180/?如圖-12
圖-12?成功接入CM