專案上線之後,出現過線上問題嗎?怎麼排查和解決的?

王中阳Go發表於2024-11-19

在面試中,相信大家都遇到過這個問題。

本文將透過訓練營內部抽獎專案的問題案例——抽獎結果通知延遲和抽獎列表載入緩慢,講清楚它們的解決方法和最佳化策略。

回答思路

這些問題都是在我負責的專案中出現過的,給我留下了深刻的印象。

一、出現的線上問題

  1. 抽獎結果通知延遲

    • 問題表現:有部分中獎使用者未能及時收到抽獎結果通知,影響了使用者體驗。
    • 影響範圍:部分中獎使用者。
  2. 抽獎列表載入緩慢

    • 問題表現:在高峰時段,使用者獲取抽獎列表的速度明顯變慢,甚至出現長時間等待的情況。
    • 影響範圍:所有查詢抽獎列表的使用者。

二、問題排查

  1. 對於抽獎結果通知延遲問題

    • 檢查訊息佇列(如Kafka)的執行狀態,確認是否存在訊息積壓或消費緩慢的情況。
    • 檢視非同步任務佇列(如Asynq)的日誌,確定開獎策略執行和通知傳送的時間點。
    • 檢查小程式端的網路連線情況,排除網路問題導致的通知接收延遲。
  2. 對於抽獎列表載入緩慢問題

    • 分析資料庫效能指標,檢視是否存在查詢瓶頸,如慢查詢、索引失效等問題。
    • 檢查快取的命中率和過期策略,確定是否因為快取未命中或頻繁過期導致重新從資料庫載入資料。
    • 監控伺服器的資源使用情況,包括CPU、記憶體、網路頻寬等,判斷是否因為資源不足導致效能下降。

三、問題解決

  1. 針對抽獎結果通知延遲問題

    • 最佳化訊息佇列:透過調整Kafka的訊息佇列配置,比如增加消費者的數量和消費速率,確保訊息能夠迅速被處理。
    • 調整任務佇列:修改Asynq任務佇列的執行間隔和併發限制,確保開獎策略執行和通知推送的及時性。
    • 增強客戶端功能:在小程式中增加通知重試機制,若使用者在設定時間內沒有接收到通知,則自動重新查詢抽獎結果。
  2. 針對抽獎列表載入緩慢問題

    • 最佳化資料庫查詢:對抽獎列表的查詢語句進行最佳化,引入更適合的索引,提高資料庫查詢效率。
    • 改進快取策略:延長快取的有效期,減少因快取失效而導致的資料庫訪問次數。同時,採用快取預熱機制,在高峰時段前提前將熱門抽獎資料載入到快取中。
    • 動態調整服務容量:根據伺服器的實際負載,利用Docker和Kubernetes等技術實現服務的自動擴充套件和收縮,確保系統能夠在高峰期保持良好的響應速度。

程式碼示例

為了便於理解和應用上述解決方案,下面提供了一些關鍵的程式碼示例。

2.1 使用Go語言和Kafka訊息佇列最佳化消費者數量和消費速度

package main

import (
    "fmt"
    "github.com/Shopify/sarama"
    "time"
)

func main() {
    config := sarama.NewConfig()
    // 設定消費者組
    config.Consumer.Group.Rebalance.Strategy = sarama.BalanceStrategyRange
    // 增加消費者數量
    config.Consumer.Group.MembershipRebalanceTimeout = 5 * time.Second
    config.Consumer.Fetch.Min = 1024
    config.Consumer.Fetch.Default = 10 * 1024
    config.Consumer.MaxWaitTime = 2 * time.Second

    // 建立消費者
    consumer, err := sarama.NewConsumer([]string{"your-kafka-broker-address"}, config)
    if err != nil {
        panic(err)
    }
    defer consumer.Close()

    // 訂閱主題
    partitionConsumer, err := consumer.ConsumePartition("your-topic", 0, sarama.OffsetNewest)
    if err != nil {
        panic(err)
    }
    defer partitionConsumer.Close()

    // 處理訊息
    for msg := range partitionConsumer.Messages() {
        fmt.Printf("Received message: %s\n", string(msg.Value))
        // 處理通知訊息的邏輯
    }
}

在上述程式碼中,透過設定sarama.Config的引數來最佳化消費者的行為,增加了消費者數量(可以透過多個消費者組或多個分割槽消費者來實現)和消費速度(調整Fetch.MinFetch.DefaultMaxWaitTime等引數),以確保能夠及時處理通知訊息。同時,要確保Kafka叢集的配置也能夠支援高併發的消費。

2.2 使用Go語言結合Redis實現調整快取策略和快取預熱

package main

import (
    "context"
    "fmt"
    "time"

    "github.com/go-redis/redis/v8"
)

var ctx = context.Background()
var redisClient *redis.Client

func init() {
    redisClient = redis.NewClient(&redis.Options{
        Addr:     "localhost:6379",
        Password: "",
        DB:       0,
    })
}

// 設定快取並延長過期時間
func setWithExtendedTTL(key string, value interface{}, expiration time.Duration) error {
    return redisClient.Set(ctx, key, value, expiration).Err()
}

// 獲取快取
func getFromCache(key string) (string, error) {
    return redisClient.Get(ctx, key).Result()
}

// 快取預熱(假設熱門抽獎資料的key有特定字首)
func warmUpCache() {
    // 假設熱門抽獎資料的key字首為"hot_lottery_"
    for i := 1; i <= 10; i++ {
        key := fmt.Sprintf("hot_lottery_%d", i)
        // 這裡模擬從資料庫獲取熱門抽獎資料
        value := fmt.Sprintf("Hot lottery data %d", i)
        err := setWithExtendedTTL(key, value, 2*time.Hour)
        if err != nil {
            fmt.Printf("Error warming up cache for key %s: %v\n", key, err)
        }
    }
}

你可以在專案啟動時呼叫warmUpCache函式進行快取預熱,並且在設定快取資料時使用setWithExtendedTTL函式來延長快取過期時間,減少快取未命中的情況。注意:程式碼中的模擬資料只是為了示例目的,實際應用中需要從真實的資料來源獲取資料進行快取預熱。

2.3 監控Linux伺服器的資源使用情況,包括CPU、記憶體、網路頻寬等,常用命令有哪些?

1. CPU監控

  • top

    • 這是一個功能強大且常用的命令。執行top後,會實時顯示系統的程序資訊以及CPU、記憶體等資源的使用情況。
    • 輸出結果中,%Cpu(s)部分展示了總的CPU使用率,包括us(使用者空間佔用CPU百分比)、sy(核心空間佔用CPU百分比)、ni(使用者程序空間內改變過優先順序的程序佔用CPU百分比)、id(空閒CPU百分比)、wa(等待輸入輸出的CPU時間百分比)等子項。
    • 對於每個程序,%CPU列顯示該程序佔用CPU的百分比,可以據此找出佔用CPU資源較高的程序。
  • mpstat

    • 用於檢視多處理器系統的CPU統計資訊。例如,mpstat -P ALL 1命令會每秒更新一次所有CPU核心的使用情況。
    • 輸出結果包括每個CPU核心的%usr(使用者模式時間百分比)、%nice(使用者模式下nice值為負的程序佔用CPU時間百分比)、%sys(核心模式時間百分比)、%iowait(等待I/O完成時間百分比)等資訊,方便檢視各個核心的負載情況。
  • vmstat

    • 可以檢視CPU和其他系統資源的綜合情況。例如,vmstat 1(每秒更新一次)。
    • 在輸出中,r列表示執行佇列中的程序數量,b列表示處於不可中斷睡眠狀態的程序數量,us(使用者CPU時間百分比)、sy(系統CPU時間百分比)、id(空閒CPU時間百分比)等列能幫助判斷CPU的使用狀態。

2. 記憶體監控

  • free

    • 簡單直觀地顯示系統記憶體的使用情況。free -h命令以人類可讀的格式(如KB、MB、GB)輸出記憶體資訊。
    • 輸出內容包括total(總記憶體)、used(已使用記憶體)、free(空閒記憶體)、shared(共享記憶體)、buff/cache(緩衝/快取記憶體)等項,並且還會顯示available(可用於啟動新應用的記憶體)。
  • vmstat

    • 除了能檢視CPU資訊外,也能監控記憶體。swpd列表示交換分割槽(虛擬記憶體)的使用量,free列是空閒實體記憶體量,buff(緩衝記憶體)和cache(快取記憶體)列的大小也能幫助瞭解記憶體的使用情況。
  • top

    • top命令的輸出中,%MEM列顯示每個程序佔用記憶體的百分比,同時也可以看到系統總的記憶體使用情況,包括總記憶體、已用記憶體和空閒記憶體等資訊。

3. 網路頻寬監控

  • ifconfig(較舊但仍常用)或ip

    • ifconfig可以檢視網路介面的基本資訊。例如,ifconfig eth0(假設eth0是網路介面)可以檢視該介面接收和傳送的位元組數、資料包數量等。
    • ip -s link show dev eth0(較新的方式)也可以檢視類似的網路介面統計資訊,包括接收和傳送的位元組數、資料包數量、錯誤數等詳細資料。
  • nload

    • 這是一個實時檢視網路頻寬使用情況的實用命令。執行nload後,會顯示網路介面的入站和出站流量,以直觀的圖表形式展示頻寬使用情況,並且可以透過-i-o選項指定要監控的網路介面的入站和出站頻寬。
  • sar -n DEV

    • sar -n DEV 1命令可以每秒更新一次網路裝置的統計資訊。
    • 輸出內容包括每個網路介面的接收和傳送的資料包數量(rxpck/stxpck/s)、位元組數(rxbyt/stxbyt/s)等詳細資料,用於檢視網路介面的吞吐率。

希望這些經驗和方法能夠給你帶來啟發和幫助。

歡迎關注 ❤

我們搞了一個免費的面試真題共享群,互通有無,一起刷題進步。

沒準能讓你能刷到自己意向公司的最新面試題呢。

感興趣的朋友們可以加我微信:wangzhongyang1993,備註:面試群。

相關文章