文件系统 vs minio
在开发的早期阶段,常见的做法是使用文件系统来存储和检索任何类型的对象。甚至当我们转向微服务时,我们也经常在某个指定的文件夹上硬编码静态文件。这使得开发或迁移到微服务变得快速,但很快我们就会后悔这个决定。
文件系统不足:
- 文件系统通常依赖于acl(访问控制列表),因此并非所有用户都具有相同的功能。使用任何类型的对象存储都可以完全避免这个acl问题。
- 文件系统与它们所在的操作系统紧密耦合。这可能会限制可移植性,并使在不同平台之间迁移或共享数据变得困难。另一方面,对象存储提供了一个标准化的接口(例如amazon s3的s3或azure blob storage api),允许轻松的数据传输和跨不同系统的兼容性。
- 当涉及到存储关于文件和对象的元数据时,文件系统通常有限制。另一方面,对象存储可以与每个对象一起存储大量元数据,从而更容易根据不同属性组织、搜索和分析数据。
- 与对象存储相比,文件系统需要更多的管理开销。对于文件系统,您需要管理目录结构、文件层次结构和访问控制列表。然而,对象存储使用平面地址空间,可以更简单地管理。
对象存储:minio
minio 是一个开源的高性能对象存储服务器,与传统的文件存储系统不同,它专注于以对象的方式存储数据。
从功能特性来看,它具有高度的可扩展性。可以很方便地通过添加节点来增加存储容量,满足数据量不断增长的需求。例如,在大数据存储场景下,随着数据的持续积累,minio 可以灵活地扩展存储规模。
minio 提供了出色的兼容性,它兼容亚马逊 s3 云存储服务的 api。这意味着,对于已经基于 s3 api 开发的应用程序,几乎可以无缝迁移到 minio 上运行,大大降低了开发和迁移成本。
在数据安全性方面,minio 支持数据加密,无论是在存储还是传输过程中,都能有效保护数据的安全。同时,它提供了多种数据冗余策略,像纠删码等方式,确保在部分存储设备出现故障时,数据依然能够完整恢复。
在性能表现上,minio 的读写速度比较快。通过分布式架构设计,它能够实现高并发的数据访问,在处理大量小文件存储和读取的场景下,如图片存储、视频存储等互联网应用场景,能够提供高效的存储服务。
在应用场景方面,minio 可用于企业数据备份与归档。企业可以将重要的数据备份到 minio 存储系统中,方便在需要时进行恢复。还可以用于云原生应用的数据存储,它能够很好地与容器编排工具(如 kubernetes)配合,为云原生应用提供可靠的存储支持。总之,minio 以其出色的性能、良好的兼容性和可靠的安全性,在对象存储领域发挥着重要作用。
golang连接minio
不管我们用minio做什么,有一些步骤是必须完成的,比如创建bucket、配置bucket策略等。我将提供一些golang代码片段,这将有助于与minio进行交互。
配置minio客户端
// 配置客户端的三个步骤
// 1. accesskey and secretkey : 创建minio集群后获取访问key和密钥key
// 2. endpoint : minio cluster 访问地址
// 3. usessl : 是否需要ssl 检查 ? (true or false)
import "github.com/minio/minio-go/v7"
func getminioclient(accesskey string, secretkey string, endpoint string,
usessl bool)(*minio.client, error) {
// context you want to use
context := context.background()
minioclient, err := getminioclient(accesskey, secretkey, endpoint, usessl)
return minioclient, err
}
创建和配置bucket
下面的代码将创建bucket,并将bucket配置为使用webhook端点,minio将通过它发送所有配置的fileevents。
这里比较棘手的部分是在minio集群中配置webhook arn。一种可能的方法是设置环境变量,以便minio能够理解,官方文档地址:publish events to webhook — minio object storage for kubernetes
set minio_notify_webhook_enable_primary=”on” set minio_notify_webhook_endpoint_primary=”endpoint”
package main
import (
"context"
"fmt"
"log"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/notification"
)
// createbucket创建minio存储桶并配置桶通知
func createbucket(bucketname, marn string, minioclient *minio.client) error {
// 1. 创建存储桶
ctx := context.background()
err := minioclient.makebucket(ctx, bucketname, minio.makebucketoptions{})
if err!= nil {
// 检查存储桶是否已存在,如果是因为已存在导致的错误则忽略
exists, errbucketexists := minioclient.bucketexists(ctx, bucketname)
if errbucketexists == nil && exists {
fmt.printf("存储桶 %s 已存在,无需重复创建\n", bucketname)
return nil
}
return fmt.errorf("创建存储桶失败: %v", err)
}
fmt.printf("存储桶 %s 创建成功\n", bucketname)
// 2. 配置桶通知
arn, err := notification.newarnfromstring(marn)
if err!= nil {
return fmt.errorf("解析arn失败: %v", err)
}
config := notification.newconfig(arn)
config.addevents(
notification.objectcreatedall,
notification.objectremovedall,
notification.objectaccessedall,
)
notificationconfig := notification.configuration{}
notificationconfig.addqueue(config)
err = minioclient.setbucketnotification(ctx, bucketname, ¬ificationconfig)
if err!= nil {
return fmt.errorf("设置存储桶通知失败: %v", err)
}
fmt.printf("存储桶 %s 的通知配置成功\n", bucketname)
return nil
}
以下是一个使用 go 语言结合 minio 客户端库创建 minio 存储桶(bucket)并配置桶通知(示例中以发送到一个 webhook 端点为例,假设 webhook 对应的 arn 已提前知晓)的更完整示例代码,代码中包含了必要的包导入以及一些错误处理优化等内容。
func main() {
// minio服务端的访问端点、访问密钥和秘密密钥
endpoint := "your_minio_endpoint"
accesskey := "your_access_key"
secretkey := "your_secret_key"
bucketname := "your_bucket_name"
marn := "your_webhook_arn"
// 创建minio客户端对象
minioclient, err := minio.new(endpoint, &minio.options{
credentials: minio.credentials{
accesskey: accesskey,
secretkey: secretkey,
},
})
if err!= nil {
log.fatalf("创建minio客户端失败: %v", err)
}
// 调用创建存储桶并配置通知的函数
err = createbucket(bucketname, marn, minioclient)
if err!= nil {
log.fatalf("执行创建存储桶及配置通知操作失败: %v", err)
}
}
注意要将代码中的 your_minio_endpoint、your_access_key、your_secret_key、your_bucket_name 和 your_webhook_arn 替换为实际的 minio 服务端信息、要创建的存储桶名称以及对应的 webhook 的 arn 信息。
读minio对象
func readobject(bucketname string, filepath string)([]byte, error) {
contentbuffer, err := minioclient.getobject(context, bucketname, filepath, minio.getobjectoptions{})
if err != nil {
return nil, err
}
// read the content from the buffer
contentbytes := new(bytes.buffer)
if _, err := io.copy(contentbytes, contentbuffer); err != nil {
return nil, err
}
return contentbytes.bytes(), nil
}
写minio对象
func uploadobject(bucketname string, objectname string, file *os.file) error {
// get the stat of file
filestat, err := file.stat()
if err != nil {
return err
}
// upload the file
uploadinfo, err := minioclient.putobject(
context,
bucketname,
objectname,
file,
filestat.size(),
minio.putobjectoptions{})
fmt.printf("uploaded info : %v", uploadinfo)
return err
}
过期策略
在 minio 中,存储桶的过期策略可以用于自动删除桶内满足一定条件(比如对象创建时间达到指定时长等)的对象。这在一些场景下非常有用,例如对于临时存储的数据、日志文件等,设定过期策略后,系统可以自动清理过期数据,节省存储空间,提升存储资源的利用效率。
**注意:**类似地,也可以实现转换策略。这会将文件重定向到远程存储。但是请确保,不要在同一个集群中配置远程存储。
import (
"context"
"fmt"
"log"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/lifecycle"
)
func setbucketlifecycle(bucketname string, days int, minioclient *minio.client) error {
ctx := context.background()
// 构建生命周期配置规则
rule := lifecycle.newrule{
id: "rule1",
status: "enabled",
filter: lifecycle.newprefixfilter(""), // 这里可以指定前缀来限制规则应用到特定前缀的对象,空字符串表示应用到桶内所有对象
expiration: lifecycle.expiration{
days: &days, // 设置过期天数,对象创建后达到这个天数就会被自动删除
},
}
// 将规则添加到生命周期配置对象中
config := lifecycle.newconfiguration()
config.rules = append(config.rules, rule)
// 使用minio客户端设置存储桶的生命周期配置(即过期策略)
err := minioclient.setbucketlifecycle(ctx, bucketname, config)
if err!= nil {
return fmt.errorf("设置存储桶 %s 生命周期配置失败: %v", bucketname, err)
}
fmt.printf("存储桶 %s 的过期策略设置成功,对象将在创建后 %d 天过期\n", bucketname, days)
return nil
}
在 main 函数中调用上述函数来实际设置存储桶过期策略的示例代码,你需要将相应的 minio 服务端地址、访问密钥、秘密密钥、存储桶名称以及期望的过期天数等参数替换为实际的值:
func main() {
endpoint := "your_minio_endpoint"
accesskey := "your_access_key"
secretkey := "your_secret_key"
bucketname := "your_bucket_name"
days := 30 // 这里假设设置对象30天后过期,你可以按需修改
// 创建minio客户端实例
minioclient, err := minio.new(endpoint, &minio.options{
credentials: minio.credentials{
accesskey: accesskey,
secretkey: secretkey,
},
})
if err!= nil {
log.fatalf("创建minio客户端失败: %v", err)
}
// 调用函数设置存储桶过期策略
err = setbucketlifecycle(bucketname, days, minioclient)
if err!= nil {
log.fatalf("设置存储桶过期策略时出现错误: %v", err)
}
}
需要注意的是:
- 要将代码中的占位符(如
"your_minio_endpoint"、"your_access_key"、"your_secret_key"、"your_bucket_name"等)替换为实际有效的 minio 相关参数信息。 - 确保已经正确引入了
minio-go库,可以通过go get github.com/minio/minio-go/v7命令获取该依赖(如果还未安装)。
通过以上代码示例,你可以在 go 语言项目中实现对 minio 存储对象读写、设置过期策略的功能,以满足不同业务场景下对数据自动过期清理的需求。
到此这篇关于golang使用minio替代文件系统的实战教程的文章就介绍到这了,更多相关golang minio替代文件系统内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论