天天看點

StarRocks BE節點崩潰原因查找及解決思路:std::bad_alloc

問題分析

StarRocks BE 5個節點突然在幾分鐘内全部掉線。查找BE的be.out日志,輸出如下:

tcmalloc: large alloc 1811947520 bytes == 0x77f9f0000 @  0x384f94f 0x39ce2dc 0x399646a
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
*** Aborted at 1641348199 (unix time) try "date -d @1641348199" if you are using GNU date ***
PC: @     0x7fa8c7db4387 __GI_raise
*** SIGABRT (@0x2ab9) received by PID 10937 (TID 0x7fa7f0658700) from PID 10937; stack trace: ***
    @          0x2da5562 google::(anonymous namespace)::FailureSignalHandler()
    @     0x7fa8c99cc630 (unknown)
    @     0x7fa8c7db4387 __GI_raise
    @     0x7fa8c7db5a78 __GI_abort
    @          0x12e91ff _ZN9__gnu_cxx27__verbose_terminate_handlerEv.cold
    @          0x391d6f6 __cxxabiv1::__terminate()
    @          0x391d761 std::terminate()
    @          0x391d8b5 __cxa_throw
    @          0x12e80de _ZN12_GLOBAL__N_110handle_oomEPFPvS0_ES0_bb.cold
    @          0x39ce27e tcmalloc::allocate_full_cpp_throw_oom()
    @          0x399646a std::__cxx11::basic_string<>::_M_mutate()
    @          0x3996e90 std::__cxx11::basic_string<>::_M_replace_aux()
    @          0x1c5c4fd apache::thrift::protocol::TBinaryProtocolT<>::readStringBody<>()
    @          0x1c5c6ac apache::thrift::protocol::TVirtualProtocol<>::readMessageBegin_virt()
    @          0x1e3d3c9 apache::thrift::TDispatchProcessor::process()
    @          0x2d91062 apache::thrift::server::TConnectedClient::run()
    @          0x2d88d13 apache::thrift::server::TThreadedServer::TConnectedClientRunner::run()
    @          0x2d8ab10 apache::thrift::concurrency::Thread::threadMain()
    @          0x2d7c500 _ZNSt6thread11_State_implINS_8_InvokerISt5tupleIJPFvSt10shared_ptrIN6apache6thrift11concurrency6ThreadEEES8_EEEEE6_M_runEv
    @          0x3998d40 execute_native_thread_routine
    @     0x7fa8c99c4ea5 start_thread
    @     0x7fa8c7e7c9fd __clone
           
分析日志,關鍵詞是:std::bad_alloc
	
顯然是記憶體不夠發生了雪崩效應,如果節點比較多,可能不會都挂掉。

BE是C++開發的,錯誤解釋參考:https://www.zhihu.com/question/24926411
           

operator new抛bad_alloc算是比較嚴重的資源問題了,因為無法配置設定記憶體,對象無法構造,肯定不能按照原來的邏輯運作了,而且很可能連給你clean up的記憶體都不夠。

在這種情況下,讓程式挂掉是正确的做法...

解決思路

增加記憶體

最好的方法肯定是增加記憶體。畢竟随着資料量增加,對記憶體使用必然會增加,可能就無法應對突然導入資料量增大的情況。

優化導入配置

在StarRocke目前版本(1.19)中有一個配置項:

mem_limit=80%	# BE可以使用的機器總記憶體的比例,如果是BE單獨部署的話,不需要配置,如果是和其它占用記憶體比較多的服務混合部署的話,要單獨配置下
load_process_max_memory_limit_bytes=107374182400	# 單節點上所有的導入線程占據的記憶體上限,100GB
load_process_max_memory_limit_percent=80	# 單節點上所有的導入線程占據的記憶體上限比例,80%
           

可以通過設定這個選項限制記憶體占用。

其他記憶體優化參數可以檢視:

https://docs.starrocks.com/zh-cn/main/administration/Memory_management#記憶體管理

設定記憶體配置設定參數

建議把 cat /proc/sys/vm/overcommit_memory 設成 1。

echo 1 | sudo tee /proc/sys/vm/overcommit_memory
           

表優化

記憶體表:StarRocks支援把表資料全部緩存在記憶體中,用于加速查詢,記憶體表适合資料行數不多元度表的存儲。

但是記憶體表在實際使用中優化并不完善,建議暫時先不使用記憶體表。

更新StarRocks

新版StarRocks(2.0),對記憶體管理進行了優化,也可以一定程度上解決問題:

  • 記憶體管理優化
    • 重構記憶體統計/控制架構,精确統計記憶體使用,徹底解決OOM
    • 優化中繼資料記憶體使用
    • 解決大記憶體釋放長時間卡住執行線程的問題
    • 程序優雅退出機制,支援記憶體洩漏檢查#1093
歡迎關注微信公衆号:資料架構探索

繼續閱讀