實驗干貨分享:用Go語言實現分布式緩存開發之map


本實驗是整個分布式緩存開發的基礎實驗,主要會使用 Go 語言的內置庫完成一個單機版的緩存服務,后面會基於這個單機版的緩存服務來升級改造,逐步迭代成為一個分布式的緩存服務。本實驗會使用 Go 語言的 map 來開發一個緩存結構,並使用 sync 包來保證並發安全,最后使用 http 包來提供網絡服務。由於篇幅有限,這里僅展現map容器的使用,我會把后續和源代碼放在文章最后,大家自取哦~

知識點

  • Go map 容器的使用

緩存的介紹

緩存的第一印象
我們先來看這樣一個問題:一個程序有 1TB 的數據都存在硬盤上,但其中只有 1GB 的數據會被頻繁地讀取,假設硬盤的讀取速度是 100MB/s,那么每一次讀取都會消耗 10 秒,有沒有什么辦法可以提高讀取的速度?

很明顯,這個問題是由於硬盤的速度太慢了,導致讀取時間太久,而且只是其中 1GB 數據會被頻繁地讀取,那我們能不能把這 1GB 的數據存到一個速度更快的地方,比如存到內存中,假設內存速度是 10GB/s,那么每一次讀取這 1GB 的數據就只需要 0.1 秒。可能有人會說,那為什么不把全部數據都存到內存中呢?當然可以,只要你有足夠大的內存,但是內存的價格要比硬盤高不少,整個程序的花費就會非常大,而且其他數據存進內存的意義不大。

如果要給這里的“內存”起一個名字,就可以叫它“緩存”了。我們不用去糾結緩存的概念是什么,更重要的是它解決了什么問題。

緩存的特點
還是從上面的問題入手,我們可以提取出兩個關鍵點:頻繁,速度。

這兩個關鍵點意味着緩存中的數據往往是會被反復讀取的,因為經常要讀取,所以要提高讀取的速度。另外,由於數據本身是存在硬盤上的,所以不管緩存中有沒有這些數據,程序都應該是正常運行的,當緩存中沒有數據的時候,需要去硬盤中讀取。如果程序修改了硬盤上的數據,緩存中的數據就沒有用了,屬於過時的數據,所以還需要去更新緩存。

所以,我們可以總結出緩存的特點:

  • 速度很快(這個快是相對於被緩存的設備來說的)
  • 數據可以丟失(甚至需要定期丟失)
  • 容量有限(因為價格比較高)

map 的常用操作

map 的介紹
Go 語言的 map 是一種鍵值對的結構,每一個鍵值對都分為 key 和 value 兩個部分。在使用 map 的時候需要指定 key 和 value 的類型,其中 key 在 map 中是唯一的。下面讓我們來學習幾個 map 的常見操作:

在后面的示例內容中,我們只會給到對應功能的代碼,未給出完整程序,請自行補充 main 函數等內容。

map 的創建

func create() {

    // map 的創建需要指定 key 和 value 的類型
    // 其中 [] 中的類型是 key 的類型,[] 后面的類型是 value 的

    // 1. 使用 make 創建 map
    m1 := make(map[string]string)
    fmt.Println(m1) // map[]

    // 2. 直接創建 map
    m2 := map[string]string{}
    fmt.Println(m2) // map[]

    // 3. 創建 map 的同時添加數據
    m3 := map[string]string{
        "key": "value",
    }
    fmt.Println(m3) // map[key:value]
}

運行截圖:
請添加圖片描述

map 的增刪改查

func crud() {

    // 創建 map
    m := make(map[string]string)
    fmt.Println(m) // map[]

    // 添加數據
    m["key"] = "value"
    fmt.Println(m) // map[key:value]

    // 修改數據
    m["key"] = "newValue"
    fmt.Println(m) // map[key:newValue]

    // 查詢數據
    // 第一個返回值是數據,第二個返回值表示 key 是否存在
    value, ok := m["key"]
    fmt.Println(value, ok) // newValue true
    value, ok = m["not existed key"]
    fmt.Println(value, ok) //  false,這里的 value 是空字符串

    // 刪除數據
    delete(m, "key")
}

運行截圖:

請添加圖片描述

map 的其他操作

func other() {

    // 創建 map
    m := map[string]int{
        "a": 1,
        "b": 3,
        "c": 4,
        "d": 2,
        "e": 0,
    }

    // 遍歷 map 可以使用 for range
    // 每一次遍歷 map 的順序可能都是不一樣的
    for key, value := range m {
        fmt.Println(key, value) // 亂序打印出 m 中的 key 和 value
    }

    // 查看 map 中的鍵值對個數
    count := len(m)
    fmt.Println(count) // 5
}

運行截圖:

請添加圖片描述

第一個熱身實驗的第一部分就到這里啦。后續我們經過開發可以完成單機版緩存,之后會進行迭代,升級成分布式緩存。

怎么樣,是不是 so easy 啊,別急,后面我們會遇到各種各樣的難題,需要大家一起拿起“屠龍刀”去殺敵。

本章節代碼可以直接獲取:

wget 
https://labfile.oss.aliyuncs.com/courses/2943/code1.zip

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM