实验干货分享:用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

参考资料

posted @ 2021-08-12 18:18  蓝桥云课  阅读(318)  评论(0编辑  收藏  举报