Metric模組原始碼解析
分散式系統的監控告警及運維服務離不開指標監控,開務作為浪潮自主研發的一款分散式資料庫自然也不例外。在兼顧強一致性、高可用分散式架構、線上水平擴充套件、企業級安全等特性下,開務的 metric 模組可提供監控指標,實現預先定義指標的週期性採集。同時,可以提供相容 Prometheus 標準格式的 API 介面,方便與外部的 Prometheus 服務進行整合。
開務資料庫 metric 模組收集各模組相關統計的 metric 資訊,並將其作為 Prometheus 格式的指標儲存起來用於進一步查閱,對判斷開務資料庫的執行情況有著重要作用,同時也是開務資料庫 adminUI 指標的資料來源。本期內容將圍繞下圖展示的 metric 模組基本框架,帶領大家深入瞭解開務資料庫 metric 模組的原始碼,圖中各模組的詳細介紹將持續為大家更新。
1、定義介面介紹
1.IterableIterable:提供了一個同步訪問內部物件的方法。方法如下:
GetName() string 返回指標名
GetHelp() string 返回指標幫助文字
GetMeasurement() string 返回指標的lable
GetUnit() Unit 返回指標使用的單位
GetMetadata() Metdata 返回指標的Metadata
Inspect(func(interface{})) Inspect對每個包含的項呼叫給定的閉包
2.PrometheusExportable:是標準獨立指標介面,可供指標匯入 Prometheus。方法如下:
GetName() string 返回指標名
GetHelp() string 返回指標幫助文字
GetType() *prometheusgo.MetricType 返回指標的Prometheus型別
GetLables() []*prometheusgo.LabelPair Metadata中的一個方法,返回指標的標籤
ToPrometheusMetric() *prometheusgo.Metric 返回一個完成值填充的Prometheus指標
3.PrometheusIterable:是 PrometheusExportable 的擴充套件,用於指示該指標由增加父標籤值的子指標組成。包含成員:PrometheusExportable。方法如下:
Each([]*prometheusgo.LabelPair, func(metric *prometheusgo.Metric))
“Each”獲取與父指標相關聯的標籤對切片,並使用每個子指標呼叫所傳遞的函式
2、Metric Metadata介紹
Metadata 包含關於指標的元資料,它必須嵌入到每個 metric object 中。它用於將有關指標的資訊匯出到 Promethues 和 adminUI 圖表。
type Metadata struct {
Name string
Help string
Measurement string
Unit Unit
MetricType _go.MetricType
Labels []*LabelPair
}
// 方法
GetName() string
GetHelp() string
GetMeasurement() string
GetUnit() Unit
GetLabels() []*prometheusgo.LabelPair
Addlabel(name value string)//給一個指標新增標籤/值對映
3、指標型別介紹
1.Histogram:在一段時間範圍內對資料進行取樣(通常是請求持續時間、響應大小等),並將其計入可配置的儲存桶(bucket)中,後續可通過指定區間篩選樣本,也可以統計樣本總數,最後一般將資料展示為直方圖。
Prometheus 的 Histogram 是一種累積直方圖,與上面的區間劃分方式是有差別的。它的劃分方式如下:假設每個 bucket 的寬度是 0.2s,那麼第一個 bucket 表示響應時間小於等於 0.2s 的請求數量,第二個 bucket 表示響應時間小於等於 0.4s 的請求數量,以此類推。也就是說,每一個 bucket 的樣本包含了之前所有 bucket 的樣本,所以叫累積直方圖。
type Histogram {
Metadata
maxVal int64
mu struct {
syncutil.Mutex
cumulative *hdrhistogram.Histogram
sliding *slidingHistogram
}
//hdrhistogram.Histogram
type Histogram struct {
lowestTrackableValue int64
highestTrackableValue int64
unitMagnitude int64
significantFigures int64
subBucketHalfCountMagnitude int32
subBucketHalfCount int32
subBucketMask int64
subBucketCount int32
bucketCount int32
countsLen int32
totalCount int64
counts []int64
}
//slidingHistogram
type slidingHistogram struct {
windowed *hdrhistogram.WindowedHistogram
nextT time.Time
duration time.Duration
}
type WindowedHistogram struct {
idx int
h []Histogram
m *Histogram
Current *Histogram
}
//相關方法介紹
func (h *Histogram) Windowed() (*hdrhistogram.Histogram, time.Duration)
返回一份當前的視窗化直方圖的資料和其中的時間間隔
func (h *Histogram) Snapshot() *hdrhistogram.Histogram
返回累積(即所有樣本)直方圖資料的副本
func (h *Histogram) RecordValue(v int64)
RecordValue將給定的值新增到直方圖。記錄超過該直方圖配置最大值使用方法
func (h *Histogram) TotalCount() int64
TotalCount返回樣本的(累計)數量
func (h *Histogram) Min() int64
返回最小值
func (h *Histogram) Inspect(f func(interface{}))
呼叫帶有空字串和接收方的閉包
func (h *Histogram) GetType() *prometheusgo.MetricType
返回此指標的Prometheus型別enum
func (h *Histogram) ToPrometheusMetric() *prometheusgo.Metric
返回正確型別的已填充的Prometheus度量值
func (h *Histogram) GetMetadata() Metadata
返回指標的元資料,包括Prometheus MetricType
func NewHistogram(metadata Metadata, duration time.Duration, maxVal int64, sigFigs int) (*Histogram)
例項化一個新histogram
func NewLatency(metadata Metadata, histogramWindow time.Duration) *Histogram
NewLatency
返回一個帶有適當預設值的直方圖來跟蹤延遲。數值以ns表示,截斷為間隔[0,MaxLatency],並以1位精度記錄(即誤差在100ms時<10ms,在60s時<6s)
2.Counter:代表一種樣本資料單調遞增的指標,即只增不減,除非監控系統發生了重置。例如,你可以使用 Counter 型別的指標來表示服務的請求數、已完成的任務數、錯誤發生的次數等。
type Counter struct {
Metadata
metrics.Counter
}
type Counter interface {
Clear()
Count() int64
Dec(int64)
Inc(int64)
Snapshot() Counter
}
//相關方法介紹
func (c *Counter) Dec(int64)
Dec過載了metric.Counter的方法。不能使用這種方法,它只用於防止誤用metric型別
func (c *Counter) GetType() *prometheusgo.MetricType
返回此指標的Prometheus型別enum
func (c *Counter) Inspect(f func(interface{}))
呼叫帶有空字串和接收方的閉包,即返回自己c
func (c *Counter) MarshalJSON() ([]byte, error)
MarshalJSON將資料封裝到JSON
func (c *Counter) GetMetadata() Metadata
返回指標的元資料,包括Prometheus MetricType
3.Gauge:代表一種樣本資料可以任意變化的指標,即可增可減。Guage 通常用於像溫度或者記憶體使用率這種指標資料,也可以表示能隨時增加或減少的“總數”,例如:當前併發請求的數量。
type Gauge struct {
Metadata
value *int64
fn func() int64
}
//相關方法介紹
func (g *Gauge) Snapshot() metrics.Gauge
Snapshot返回Gauge的只讀副本
func (g *Gauge) Update(v int64)
更新Gauge的值
func (g *Gauge) Inc(i int64)
增加Gauge的當前值
func (g *Gauge) Dec(i int64)
減少Gauge的當前值
func (g *Gauge) Value() int64
Value返回Gauge的當前值
func (g *Gauge) GetType() *prometheusgo.MetricType
返回此指標的Prometheus型別enum
func (g *Gauge) ToPrometheusMetric() *prometheusgo.Metric
返回此指標的Prometheus型別enum
func (g *Gauge) GetMetadata() Metadata
返回指標的元資料,包括Prometheus MetricType
4.Rate:用來計算某個指標在最近一個區間時間內的變化率。
type Rate struct {
Metadata
mu syncutil.Mutex // protects fields below
curSum float64
wrapped ewma.MovingAverage
interval time.Duration
nextT time.Time
}
//相關方法介紹
func (e *Rate) GetType() *prometheusgo.MetricType
GetType返回該指標的Prometheus型別enum
func (e *Rate) Inspect(f func(interface{}))
Inspect用自身呼叫給定的閉包
func (e *Rate) ToPrometheusMetric() *prometheusgo.Metric
返回此指標的Prometheus型別enum
func (c *Counter) MarshalJSON() ([]byte, error)
MarshalJSON將資料封裝到JSON
func (e *Rate) GetMetadata() Metadata
GetMetadata返回指標的元資料,包括Prometheus MetricType
func (e *Rate) Value() float64
Value返回Rate的當前值
func (e *Rate) tick()
Rate時間前進
func (e *Rate) nextTick() time.Time
返回Rate的當前時間。
func (e *Rate) Add(v float64)
新增將給定的測量值新增到Rate
4、註冊器Registry介紹
Registry 是 metric 的列表,它提供了一種處理指標的方法,可以將 metric 編組成 JSON,並生成 Prometheus 格式的 metric。同時可以給註冊的指標打上標籤,當匯出到 Prometheus 時,這些標籤將應用於它的所有指標。
type Registry struct {
syncutil.Mutex
labels []*prometheusgo.LabelPair
tracked []Iterable
}
//相關方法介紹
func (r *Registry) AddLabel(name, value string)
AddLabel為這個登錄檔新增一個標籤/值對
func (r *Registry) AddMetric(metric Iterable)
AddMetric將傳入的metric新增到登錄檔
func (r *Registry) WriteMetricsMetadata(dest map[string]Metadata)
WriteMetricsMetadata將所有跟蹤metric的元資料寫入引數對映
func (r *Registry) Each(f func(name string, val interface{}))
每個函式對所有metric呼叫給定的閉包
func (r *Registry) MarshalJSON() ([]byte, error)
格式化到JSON格式
5、註冊新Registry步驟
// 以txnMetric說明
//txn_metric.go
//宣告定義的指標結構體型別
type TxnMetrics struct {
Commits *metric.Counter
...
}
//定義指標的metadata
var(
metaCommitsRates = metric.Metadata{
Name: "txn.commits",
Help: "Number of committed KV transactions (including 1PC)",
Measurement: "KV Transactions",
Unit: metric.Unit_COUNT,
}
...
)
//將定義的指標型別和metadata相關聯
func MakeTxnMetrics(histogramWindow time.Duration) TxnMetrics {
return TxnMetrics{
Commits: metric.NewCounter(metaCommitsRates),
}
//server.go:
//註冊進Registry
txnMetrics := kvcoord.MakeTxnMetrics(cfg.HistogramWindowInterval())
registry.AddMetricStruct(txnMetrics)
開務資料庫是一款浪潮集團核心研發的先進、安全的雲原生分散式資料庫;具備雲原生、多中心、高可用、事務強一致等特性,滿足 HTAP 場景需求。業務範圍覆蓋能源、工業網際網路、政務、教育、金融等多行業。我們是一支平均年齡 30 歲的年輕團隊,在短短不到三年的時間裡,我們已取得近 300 項發明專利受理,10 項自有產品軟著授權。熱烈歡迎廣大夥伴加入我們的團隊,熱門崗位火熱招聘中,簡歷投遞郵箱: [email protected] / [email protected]
資料庫儲存核心研發工程師
工作職責:
1、負責儲存子系統的研發路線規劃、架構設計和關鍵技術問題攻關;
2、負責編寫功能測試用例,測試工具進行系統驗證;
3、負責資料庫的系統性能診斷與調優;
4、負責資料庫相關關鍵技術的預研和在團隊中的引導;
5、深入理解業務場景的資料庫儲存需求,針對性的為不同業務場景提供最合適的儲存方案。
任職要求:
1、學歷:本科或者本科以上學歷;
2、專業:計算機或相關專業;
3、專業知識:
— 3 年及以上 GO/C++ 開發經驗;
— 精通 C/C++/GO 語言,Linux 系統程式設計。熟悉無鎖資料結構,熟悉現代硬體體系結構 (CPU/Cache/Memory/Storage), 熟悉併發程式設計;
— 熟練使用 MySQL、PostgeSQL 等主流資料庫;
— 熟悉資料庫儲存系統的基本理論,熟悉事務處理,日誌與恢復策略,多版本併發控制技術的實現,對資料庫的基本理論和內部實現機制有深刻的理解;
— 技術視野開闊,有一定的系統性能優化經驗,掌握各種效能診斷工具和各種優化方法;
— 熟悉時序資料庫,有實際的時序資料庫開發經驗優先;
— 熟悉 RocksDB、Arrow、Parquet 等開源儲存專案原始碼者優先。
Base 地: 上海 / 天津 / 濟南 / 北京
資料庫方案工程師
工作職責:
1、負責分散式資料庫,或其相關工具、平臺等產品的梳理、規劃、設計和推進工作;
2、進行解決方案的調研、設計和驗證;
3、設計、撰寫和維護產品紅皮書;
4、跨部門溝通,協調各類資源以確保產品順利上線,推進產品迭代。
任職要求:
1、5 年以上的資料庫運維及方案設計經驗(ORACLE/Mysql/PostgreSQL 任意一種),對部署,優化,災備,恢復,高可用有實際經驗;
2、1 年左右的分散式資料庫經驗,瞭解國內任意一款分散式資料庫,有部署,POC,問題處理經驗;
3、對 OLTP 和 OLAP 系統或其中一種有實際運維設計經驗;
4、對資料庫災備,同步方案有實際專案經驗;
5、會一種資料庫 benchmark 工具,設計相應場景進行測試並結合已有經驗給與相應調整優化;
6、有基本的程式設計能力,如 go,shell,python 其中一項,可以寫簡單程式對資料庫進行併發測試,功能驗證;
7、有專案管理能力,很好的溝通能力,可以與開發人員順暢溝通,並於合作高校學生完成實驗及文件編寫;
8、紮實的技術,linux 和資料庫方面有一定積累,能對開發人員及學生進行一定指導,促使相關工作順利推進;
9、較強的文件編寫組織能力,根據實驗文件及相關手冊,編寫使用者解決方案手冊;
10、有一定語言表達能力,能做資料庫相關功能培訓。
Base 地: 上海 / 天津 / 濟南 / 北京