这是我参与「第三届青训营 -后端场」笔记创作活动的第3篇笔记。
一.什么是对象存储
对象存储也叫做基于对象的存储,用来描述解决和处理离散单元的方法的通用术语,这些离散单元被称作对象。在对象存储中,数据与关联的元数据和唯一标识符捆绑在一起,以形成存储池。对象存储消除了文件存储中使用的分层文件结构,所有对象都在一个被称作存储池的扁平地址空间的同一级别里。每个对象都会被分配一个唯一的标识符,允许服务器或最终用户来检索对象而不必知道数据的物理地址。
二.为什么要有对象存储
1.海量数据场景下不同存储比较:
a.在海量数据存储情况下,单机存储和单机数据库都难以存下海量的数据。
b.分布式数据库虽在容量和弹性上有有很大的进展,但只适合存储结构化或半结构化的数据,要求数据和数据之间有一定的关联关系,且这些信息一般不超过KB级别。因而分布式存储更适合应对海量存储场景。
c.分布式文件系统HDFS同属于分布式存储,但其存储文件数量受Name Node限制,在易用性上存在提供的伪Posix文件接口开发略复杂无法直接HTTP访问、非云原生搭建维护较麻烦、视频图片相关生态接入略复杂的问题。
d.作为最后登场的主角,对象存储TOS支持海量存储在对象数量无限制。成本上同HDFS使用成本低的普通的X86服务器,但其具备冷热数据分级存储的能力在成本上更占优势。在易用性上其提供了Restful HTTP接口,开发使用起来更为简单;同时基于云原生搭建按需申请使用,减少搭建维护成本;对视频和图片相关生态丰富。
2.对象存储的优点总结
易用:提供Restful HTTP接口(GET HEAD PUT DELETE...)解放业务,让业务专注于业务逻辑开发。
海量:适用于存储海量的静态数据如图片、视频、备份等。
便宜:成本低,在大存储情况下节省宝贵的经费。
三.对象存储怎么用
1.首先上对象存储平台如字节的TOS、七牛云平台等,申请Bucket。
2.针对对象存储提供的Restful接口完成业务逻辑开发。
PUT:参数:Bucket, Key,对象内容 返回:成功/失败
GET:参数:Bucket, Key 返回: 对象内容
HEAD: Lite版GET 参数:Bucket, Key 返回:对象元信息,如大小/Content-Type等
DELETE:参数:Bucket,Key 返回:成功/失败
进阶模块:大文件分块上传、分页
、
四.TOS架构设计
五.简单实践
准备:登陆注册七牛云存储平台,创建存储空间
配置文件go.mod中添加sdk: require github.com/qiniu/go-sdk/v7 v7.12.1
cmd更新依赖:go mod tidy
import (
"fmt"
"github.com/qiniu/go-sdk/v7/auth/qbox"
"github.com/qiniu/go-sdk/v7/storage"
)
// 七牛云存储密钥配置
var (
accessKey = ""
secretKey = ""
bucketName = "" // 创建的空间名称
)
// UploadFileToObjectStore 输入要上传的文件地址,返回存储后的访问url地址
func UploadFileToObjectStore(toUploadFilePath string) (error, string) {
// 上传成功的时候返回存储后的文件访问URL地址
var fileUrlPath string
// 根据操作系统自动判断分隔符
sysType := runtime.GOOS
var sysSpliter string
if sysType == "windows" {
sysSpliter = "\"
} else {
sysSpliter = "/"
}
// 分割文件路径获取要上传的文件名
fileSlice := strings.Split(toUploadFilePath, sysSpliter)
fileName := fileSlice[len(fileSlice)-1]
bucket := bucketName
putPolicy := storage.PutPolicy{
Scope: bucket,
}
mac := qbox.NewMac(accessKey, secretKey)
upToken := putPolicy.UploadToken(mac)
cfg := storage.Config{}
// 空间对应的机房
cfg.Zone = &storage.ZoneHuanan
// 是否使用https域名
cfg.UseHTTPS = false
// 上传是否使用CDN上传加速
cfg.UseCdnDomains = true
// 构建表单上传的对象
formUploader := storage.NewFormUploader(&cfg)
ret := storage.PutRet{}
// 可选配置
putExtra := storage.PutExtra{
Params: map[string]string{
"x:name": "github logo",
},
}
// 上传文件
if err := formUploader.PutFile(context.Background(), &ret, upToken, fileName, toUploadFilePath, &putExtra); err != nil {
return err, fileUrlPath
}
fmt.Println("文件上传成功!")
fmt.Println(ret.Key, ret.Hash)
// 拼接返回文件的访问url地址
var bt1 bytes.Buffer
bt1.WriteString("") // 填写七牛云提供的临时解析域名即外链
bt1.WriteString(fileName)
fileUrlPath = bt1.String()
return nil, fileUrlPath
}