我們一起聊聊 StarRocks 升級注意事項(xiàng)
前段時(shí)間升級了生產(chǎn)環(huán)境的 StarRocks,從 3.3.3 升級到了 3.3.9,期間還是踩了不少坑所以在這里記錄下。
圖片
因?yàn)槲覀兊募菏褂玫氖谴嫠惴蛛x的版本,也是使用官方提供的 operator 部署在 kubernetes 里的,所以沒法按照官方的流程進(jìn)入虛擬機(jī)手動啟停對應(yīng)的服務(wù)。
只能使用 operator 提供的方案手動修改對應(yīng)組件的鏡像版本,后續(xù)的升級操作交給 operator 去完成。
圖片
理論上這個(gè)升級流程沒什么問題,修改鏡像版本之后只需要安靜等待他滾動更新即可。
元數(shù)據(jù)備份與恢復(fù)
但考慮到之前在社區(qū)看到有存算分離集群升級失敗導(dǎo)致數(shù)據(jù)丟失的案例,我們的全量業(yè)務(wù)已經(jīng)切換到 StarRocks,如果數(shù)據(jù)丟失那需要花幾天時(shí)間進(jìn)行數(shù)據(jù)同步,這在業(yè)務(wù)上是無法接受的,所以我們最好是可以在升級前備份數(shù)據(jù),即便是升級失敗數(shù)據(jù)依然還在。
圖片
原本官方社區(qū)是有提供數(shù)據(jù)備份與恢復(fù)能力的,但是我們使用的存算分離集群不支持??,而想要獲得社區(qū)版的支持應(yīng)該還要等一段時(shí)間,即便是支持了我們升級到那個(gè)版本依然是需要備份的。
圖片
好消息,在最新的 3.4.1 版本中已經(jīng)支持了快照備份了,只是作為一個(gè)新 feature,穩(wěn)定性還有待觀察。
所以我們的計(jì)劃是在當(dāng)前這個(gè)版本(3.3.3)能否自己備份數(shù)據(jù),由于我們是存算分離的版本,所以數(shù)據(jù)主要分為兩部分:
- 存儲在所有 FE 節(jié)點(diǎn)里的 meta 元數(shù)據(jù)
- 存儲在云存儲里的業(yè)務(wù)數(shù)據(jù)
備份的時(shí)候自然就需要備份這兩部分的數(shù)據(jù)。
備份元數(shù)據(jù)
在元數(shù)據(jù)里存放了所有的數(shù)據(jù)庫、表、視圖等信息,具體在磁盤的結(jié)構(gòu)如下:
|-- bdb
| |-- 00000000.jdb
| |-- je.config.csv
| |-- je.info.0
| |-- je.info.0.lck
| |-- je.lck
| `-- je.stat.csv
|-- image
| |-- ROLE
| |-- VERSION
| |-- image.327375
| |-- starmgr
| | `-- image.390
| `-- v2
| |-- checksum.327375
| `-- image.327375
bdb 目錄主要是用于 leader 選舉的,理論上并不需要備份,真正需要的是 image 目錄下的 image.327375 等元數(shù)據(jù)文件。
圖片
圖片
里面是用 JSON 存儲的各種類型的元數(shù)據(jù),F(xiàn)E 在啟動的時(shí)候會讀取該文件,然后根據(jù)不同的類型取不同的偏移量讀取其中的元數(shù)據(jù)加載到內(nèi)存里。
我們的 FE 一共有三個(gè)節(jié)點(diǎn),需要找到其中的 leader 節(jié)點(diǎn)(理論上只需要備份 leader 節(jié)點(diǎn)即可,其他節(jié)點(diǎn)會在 leader 啟動后同步過去),直接將這個(gè) meta 目錄備份到本地即可:
在開始之前需要停掉所有的寫入任務(wù),暫停所有的物化視圖刷新。
# inactive 所有的物化視圖
SELECT CONCAT('ALTER MATERIALIZED VIEW ', TABLE_NAME, ' INACTIVE;') FROM information_schema.materialized_views;
# 手動創(chuàng)建鏡像
ALTER SYSTEM CREATE IMAGE;
# 找到 leader 節(jié)點(diǎn)
SHOW FRONTENDS;
然后進(jìn)入 leader 節(jié)點(diǎn)備份元數(shù)據(jù):
k exec -it kube-starrocks-fe-0-n sr -- bash
tar -zcvf meta.tar.gz meta/
# 下載備份元數(shù)據(jù)到本地
k cp starrocks-fe-0:/opt/starrocks/fe/meta/image.tar.gz image.tar.gz -n starrocks -c fe --retries=5
備份云存儲數(shù)據(jù)
云存儲的備份就需要結(jié)合你使用的云廠商來備份了,通常他們都有提供對應(yīng)的備份能力。
要注意的是我們再備份的時(shí)候需要記錄在存儲桶里的目錄名稱,之后還原的時(shí)候名稱得保持一致才行。
恢復(fù)元數(shù)據(jù)
當(dāng)出現(xiàn)極端情況升級失敗的時(shí)候,我們需要把元數(shù)據(jù)覆蓋回去;但由于我們的應(yīng)用運(yùn)行在容器里,不可以在應(yīng)用啟動之后再替換元數(shù)據(jù)。
只能在應(yīng)用啟動之前將之前備份的元數(shù)據(jù)覆蓋回去,這里可以使用 kubernetes 中的 initContainers 提前將數(shù)據(jù)復(fù)制到應(yīng)用容器里。
在開始之前我們需要先把備份的元數(shù)據(jù)打包為一個(gè)鏡像。
FROM busybox
ADD meta.tar.gz /temp
然后我們需要手動修改 FE 的 statefulset 的資源,創(chuàng)建一個(gè) initContainers。
initContainers:
-name:copy-file-init
image:meta:0.0.1
command:["/bin/sh","-c"]
args:["rm-rf/meta-target/*&&cp-r/temp/meta/./meta-target"]
volumeMounts:
-name:fe-meta
mountPath:"/meta-target"
原理就是在 initContainers 中掛載原本 FE 的元數(shù)據(jù)目錄,這樣就可以直接將之前備份的元數(shù)據(jù)覆蓋過去。
當(dāng)然也可以直接使用 k8s 的 go client 用代碼的方式來修改,會更容易維護(hù)。
還原的時(shí)候需要先將云存儲里的數(shù)據(jù)先還原之后再還原元數(shù)據(jù)。
物化視圖刷新策略
真正升級的時(shí)候倒是沒有碰到升級失敗的情況,所以沒有走恢復(fù)流程;但是卻碰到了一個(gè)更麻煩的事情。
物化視圖作為基表
我們在升級前將所有的物化視圖設(shè)置為了 INACTIVE,升級成功后需要將他們都改為 ACTIVE。
第一個(gè)問題是如果某個(gè)物化視圖 MV1 的基表也是一個(gè)物化視圖 MV-base,這樣會導(dǎo)致 MV1 的全量刷新。
我之前在這個(gè) PR 里新增了一個(gè)參數(shù):excluded_refresh_tables 可以用于排除基表發(fā)生變化的時(shí)候刷新物化視圖,但是忘記了基表也是物化視圖的場景。
圖片
所以在這個(gè) PR 中修復(fù)了該問題,現(xiàn)在基表是物化視圖的時(shí)候也可以使用了。
物化視圖手動 ACTIVE
前面提到在升級之前需要將所有的物化視圖設(shè)置為 INACTIVE,升級成功后再手動設(shè)置為 ACTIVE。
我們在手動 ACTIVE 之后發(fā)現(xiàn)這些物化視圖又在做全量刷新了,于是我們檢查了代碼。
圖片
發(fā)現(xiàn)在使用 ALTER MATERIALIZED VIEW order_mv ACTIVE; 修改視圖狀態(tài)的時(shí)候會強(qiáng)制刷新物化視圖的所有分區(qū)。
圖片
force: true 的時(shí)候會直接跳過基表的分區(qū)檢查,導(dǎo)致分區(qū)的全量刷新。
圖片
同時(shí)會在 ACTIVE 的時(shí)候?qū)⒁晥D基表的 baseTableVisibleVersionMap 版本號緩存清空,F(xiàn)E 需要在刷新的時(shí)候判斷當(dāng)前需要刷新的分區(qū)是否存在與緩存中,如果存在的話說明不需要刷新,現(xiàn)在被清空后就一定會被刷新。
所以我提了一個(gè) PR 可以在 ACTIVE 物化視圖的時(shí)候人工判斷是否需要刷新:
alter materialized view mv_test1 ACTIVE WITH NO_VALIDATION
這樣帶上 NO_VALIDATION 參數(shù)后就 force=false 也就不會全量刷新了。
如果在 ACTIVE 物化視圖的時(shí)候碰到類似場景,可以在這個(gè) PR 發(fā)布之后加上 NO_VALIDATION 來跳過刷新。
參考鏈接: