ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Go Web 编程实战:使用 Redis 与 MongoDB 操作 NoSQL 数据库

Go Web 编程实战:使用 Redis 与 MongoDB 操作 NoSQL 数据库 文档教程【免费下载链接】build-web-application-with-golangA golang ebook intro how to build a web with golang项目地址https://gitcode.com/gh_mirrors/bu/build-web-application-with-golang点击查看免费下载导读在构建高并发、超大规模 Web 应用时传统关系型数据库在读写性能与扩展性上常常成为瓶颈而 NoSQL 数据库凭借其高性能、高并发读写的特性成为 Web 2.0 时代的重要存储选型。本文基于开源电子书《Build Web Application with Golang》zh/preface.md第 5.6 节的内容系统讲解如何在 Go 应用中操作两大主流 NoSQL 数据库——Redis 与 MongoDB从驱动选型、连接池配置到 String/List 与文档集合的增删改查并结合仓库内 en/code/src/apps/ch.5.6 下的可运行示例代码让你在读完本文后能够独立完成 Go 与 NoSQL 存储的对接开发。认识 NoSQL为什么 Go 应用需要它NoSQLNot Only SQL指非关系型数据库。随着 Web 2.0 的兴起传统关系数据库在应对超大规模、高并发的 SNS 类纯动态网站时暴露出扩展难、读写吞吐受限等问题而非关系型数据库凭借其自身特点得到了快速发展。Go 语言被誉为21 世纪的 C 语言对 NoSQL 的支持非常友好。目前流行的 NoSQL 数据库主要有Rediskey-value 存储系统MongoDB文档型数据库Cassandra分布式列存储数据库Membase面向 Web 应用的分布式内存缓存数据库。这些数据库都具有高性能、高并发读写等特点已广泛应用于各类应用之中。本文接下来重点讲解 Redis 和 MongoDB 在 Go 中的操作方式。使用 Redis从连接池到业务读写Redis 是什么Redis 是一个 key-value 存储系统与 Memcached 类似但它支持存储的 value 类型相对更多包括string字符串list链表set集合zset有序集合部分实现还支持 hash 类型在本书写作时Redis 最广泛的应用案例包括新浪微博平台以及 Facebook 收购的图片社交网站 Instagram 等大型互联网企业。Go 生态中的 Redis 驱动Go 目前支持的 Redis 驱动主要有redigo由 gomodule 维护社区推荐使用go-redis/redishoisie/redisalphazero/Go-Redissimonz05/godis本书作者还 fork 了最后一个驱动并修复了一些 bug形成了自己的维护版本goredis并实际应用于自己的短域名服务项目日均约 200 万 PV这一实战背景也说明了该驱动在真实高并发场景下的可用性。基于 redigo 的连接池实战以 redigo 驱动为例演示如何通过连接池redis.Pool进行数据操作。连接池能复用连接、减少频繁建连的开销是生产环境推荐的使用方式package main import ( fmt os os/signal syscall time github.com/gomodule/redigo/redis ) var ( Pool *redis.Pool ) func init() { redisHost : :6379 Pool newPool(redisHost) close() } func newPool(server string) *redis.Pool { return redis.Pool{ MaxIdle: 3, IdleTimeout: 240 * time.Second, Dial: func() (redis.Conn, error) { c, err : redis.Dial(tcp, server) if err ! nil { return nil, err } return c, err }, TestOnBorrow: func(c redis.Conn, t time.Time) error { _, err : c.Do(PING) return err } } } func close() { c : make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) signal.Notify(c, syscall.SIGTERM) signal.Notify(c, syscall.SIGKILL) go func() { -c Pool.Close() os.Exit(0) }() } func Get(key string) ([]byte, error) { conn : Pool.Get() defer conn.Close() var data []byte data, err : redis.Bytes(conn.Do(GET, key)) if err ! nil { return data, fmt.Errorf(error get key %s: %v, key, err) } return data, err } func main() { test, err : Get(test) fmt.Println(test, err) }代码中的关键连接池参数说明如下MaxIdle: 3连接池中最多保持 3 条空闲连接超出后多余的连接会被关闭用于控制空闲资源占用IdleTimeout: 240 * time.Second空闲连接超过 240 秒未使用即被回收关闭避免长时间占用服务端连接资源Dial负责创建新连接的函数这里通过redis.Dial(tcp, server)建立 TCP 连接其中server形如:6379省略主机名表示本机端口为 Redis 默认端口TestOnBorrow每次从池中借出连接时执行的健康检查这里发送PING命令验证连接仍可用若返回错误则说明连接已失效池会丢弃该连接并重建Get方法从池中获取连接Pool.Get()通过conn.Do(GET, key)执行 Redis 原生命令再用redis.Bytes将响应转换为[]byte最后defer conn.Close()归还连接。close()函数则通过os/signal监听中断与终止信号在程序退出前主动关闭连接池属于资源清理的工程化细节。基于 goredis 的直连 CRUD 实战goredis 驱动的设计理念是client 的命令和 Redis 原生命令基本保持一致因此使用体验非常接近直接操作 Redis 命令行。下面的代码演示字符串String与链表List两类数据的操作package main import ( fmt github.com/astaxie/goredis ) func main() { var client goredis.Client // 设置端口为redis默认端口 client.Addr 127.0.0.1:6379 //字符串操作 client.Set(a, []byte(hello)) val, _ : client.Get(a) fmt.Println(string(val)) client.Del(a) //list操作 vals : []string{a, b, c, d, e} for _, v : range vals { client.Rpush(l, []byte(v)) } dbvals,_ : client.Lrange(l, 0, 4) for i, v : range dbvals { println(i,:,string(v)) } client.Del(l) }可以看到操作非常方便实际项目应用下来性能也很高。代码解读String 操作client.Set(a, []byte(hello))写入键值client.Get(a)读取并以string(val)还原为字符串client.Del(a)删除List 操作循环调用client.Rpush(l, []byte(v))将a、b、c、d、e依次从链表右侧入队client.Lrange(l, 0, 4)取出索引 04 的 5 个元素最后client.Del(l)清理。仓库中的完整 CRUD 示例与运行步骤仓库 en/code/src/apps/ch.5.6/redis/main.go 提供了一个更完整的 goredis CRUD 示例在插入阶段写入 String 与 List 数据后还演示了更新重新Set、继续Rpush与查询Get、Lrange最后统一删除Del并封装了checkError统一处理错误。该示例将连接地址定义为常量const ( DB_PORT 9191 DB_URL 127.0.0.1 )注意仓库示例将 Redis 端口配置为9191而非默认的6379运行前需要按 en/code/src/apps/ch.5.6/redis/readme.md 的说明将本地 Redis 服务启动在与DB_URL:DB_PORT常量匹配的地址上。完整的运行步骤对应仓库 readme为安装并运行 Redis启动与代码中DB_PORT 9191、DB_URL 127.0.0.1常量匹配的 Redis 服务端通过go get下载安装远程依赖包使用go run main.go执行程序。使用 MongoDB文档型数据库的 Go 实践MongoDB 简介与 MySQL 对比MongoDB 是一个高性能、开源、无模式的文档型数据库是介于关系数据库和非关系数据库之间的产品也是非关系数据库中功能最丰富、最像关系数据库的。它支持的数据结构非常松散采用类似 JSON 的 BSON 格式来存储数据因此可以存储比较复杂的数据类型。MongoDB 最大的特点是查询语言非常强大其语法类似于面向对象的查询语言几乎可以实现类似关系数据库单表查询的绝大部分功能并且支持对数据建立索引。下图展示了 MySQL 与 MongoDB 之间的操作对应关系从图中可以看到MySQL 的SELECT查询项、FROM表、WHERE过滤条件、GROUP BY分组、HAVING聚合过滤、ORDER BY排序、LIMIT分页等操作在 MongoDB 中都有对应的实现方式查询指令、映射/归约函数、结果查找/排序/分页等两者可以实现同类数据查询聚合需求而 MongoDB 的性能表现非常出色。安装 mgo 驱动在本书写作时期Go 支持 MongoDB 最好的驱动是mgo该驱动当时被认为最有可能成为官方标准包。安装命令go get gopkg.in/mgo.v2基于 mgo 的 struct 式 CRUD 实战下面演示如何通过 Go 操作 MongoDB核心思路是定义结构体 → 建立会话 → 按 struct 插入与查询package main import ( fmt log gopkg.in/mgo.v2 gopkg.in/mgo.v2/bson ) type Person struct { Name string Phone string } func main() { session, err : mgo.Dial(server1.example.com,server2.example.com) if err ! nil { panic(err) } defer session.Close() // Optional. Switch the session to a monotonic behavior. session.SetMode(mgo.Monotonic, true) c : session.DB(test).C(people) err c.Insert(Person{Ale, 55 53 8116 9639}, Person{Cla, 55 53 8402 8510}) if err ! nil { log.Fatal(err) } result : Person{} err c.Find(bson.M{name: Ale}).One(result) if err ! nil { log.Fatal(err) } fmt.Println(Phone:, result.Phone) }代码要点解读mgo.Dial(server1.example.com,server2.example.com)连接 MongoDB支持传入逗号分隔的多个服务器地址以构成副本集连接串本地开发可简写为mgo.Dial(localhost)session.SetMode(mgo.Monotonic, true)将会话切换到单调Monotonic一致性模式适用于读多写少、允许一定程度数据延迟的场景session.DB(test).C(people)选择名为test的数据库与名为people的集合类比关系数据库中的表c.Insert(Person{...})直接以结构体指针批量插入文档MongoDB 会为每条文档自动生成_idc.Find(bson.M{name: Ale}).One(result)以 BSON 映射bson.M构造查询条件等价于WHERE name AleOne将单条结果反序列化到result结构体中。可以明显看出mgo 的操作方式和本书第 5.5 节介绍的 beedb 操作方式几乎类似——都是基于 struct 的操作方式这正是 Go 的风格Go Style。仓库中的完整 CRUD 示例与运行步骤仓库 en/code/src/apps/ch.5.6/mongodb/main.go 提供了更完整的 mgo CRUD 版本将数据库名、集合名抽为常量const ( DB_NAME test DB_COLLECTION people )其流程覆盖了完整的增删改查连接与会话mgo.Dial(localhost)连接本地实例defer session.Close()释放会话清空集合先调用c.DropCollection()保证示例可重复运行插入c.Insert(ale, cla)批量插入两条Person文档更新修改ale.Phone后调用c.Update(bson.M{name: Ale}, ale)按条件更新整条文档查询c.Find(bson.M{name: Ale}).One(result)查询单条并输出Phone字段删除c.Remove(bson.M{name: Ale})删除匹配条件的文档。运行步骤对应 en/code/src/apps/ch.5.6/mongodb/readme.md安装并运行 MongoDB启动 MongoDB 守护进程mongod以开启服务端通过go get下载安装远程依赖包使用go run main.go执行程序。Go 风格的数据库操作struct 与原生命令哲学综合本章两个示例可以总结出 Go 操作 NoSQL 的两条风格主线面向命令的驱动如 redigo、goredisclient 的方法名与 Redis 原生命令一一对应SET/Set、GET/Get、RPUSH/Rpush、LRANGE/Lrange、DEL/Del学习成本极低性能高适合需要精细控制命令语义的缓存、计数器、队列等场景面向结构的驱动如 mgo以 Go struct 作为文档的载体Insert、Find、Update、Remove天然映射文档集合的增删改查与关系型 ORM如第 5.5 节的 beedb体验一致适合业务模型明确的应用。两者共同体现了 Go 语言简洁、直接、贴近底层又拥抱结构的工程风格。小结与相关章节本文完整讲解了 Go 操作 NoSQL 数据库的两大主流方案Redis 方向以 redigo 连接池保证生产可用性MaxIdle、IdleTimeout、TestOnBorrow以 goredis 直连方式贴近原生命令并给出仓库内完整的 CRUD 示例与运行步骤MongoDB 方向理解 BSON 文档模型与 MySQL 的对应关系掌握 mgo 的安装、会话模式与基于 struct 的增删改查。需要提醒的是本文所引用的驱动redigo、goredis、mgo与命令go get gopkg.in/mgo.v2均为本书写作时期的流行方案当前 Go 生态中驱动与模块路径已发生演化实际使用时请以官方最新文档为准但连接池管理、原生命令映射、struct 式文档操作这三条核心方法论仍然通用。本节属于访问数据库章节的一部分相关内容可继续阅读上一节使用 Beego orm 库进行 ORM 开发下一节小结全书目录zh/preface.md赞分享文档教程【免费下载链接】build-web-application-with-golangA golang ebook intro how to build a web with golang项目地址https://gitcode.com/gh_mirrors/bu/build-web-application-with-golang点击查看免费下载相关推荐使用 Go 语言操作 NoSQL 数据库Redis 与 MongoDB 实战指南使用 Go 语言操作 NoSQL 数据库Redis 与 MongoDB 实战指南 NoSQLNot Only SQL非关系型数据库在 Web2.0 时代文档教程Build Web Application with Golang 第 5.6 节使用 Go 操作 NoSQL 数据库Redis 与 MongoDB 实战Build Web Application with Golang 第 5.6 节使用 Go 操作 NoSQL 数据库Redis 与 MongoDB 实战文档教程用 Go 操作 NoSQL 数据库Redis 与 MongoDB 实战指南Build Web Application with Golang · 第 5.6 节用 Go 操作 NoSQL 数据库Redis 与 MongoDB 实战指南Build Web Application with Golang · 第 5.6文档教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表