golang 操作 mongodb 使用的包是 “gopkg.in/mgo.v2”,coding 过程中需要并发读写 mongodb 数据库,简单观摩了下源码,记录下自己的一些理解,如有错误,敬请斧正。 

一般来说,我们直接这样创建一个 Session:

Session, err = mgo.Dial(URL)if err != nil {log.Println(err)}

来看看Dial这个函数做了什么:

func Dial(url string) (*Session, error) {session, err := DialWithTimeout(url, 10*time.Second)if err == nil {session.SetSyncTimeout(1 * time.Minute)session.SetSocketTimeout(1 * time.Minute)}return session, err
}

调用 DialWithTimeout 函数设置默认的超时时间是 10 秒。该函数中调用了 DialWithInfo 这个函数,而 DialWithInfo 函数中比较重要是是调用了newSession,看看这个函数做了什么操作:

func newSession(consistency Mode, cluster *mongoCluster, timeout time.Duration) (session *Session) {cluster.Acquire()session = &Session{cluster_:    cluster,syncTimeout: timeout,sockTimeout: timeout,poolLimit:   4096,}debugf("New session %p on cluster %p", session, cluster)session.SetMode(consistency, true)session.SetSafe(&Safe{})session.queryConfig.prefetch = defaultPrefetchreturn session}

返回的session设置了一些默认的参数,暂时先忽略,直接看看Session的数据结构:

type Session struct {m                sync.RWMutexcluster_         *mongoClusterslaveSocket      *mongoSocketmasterSocket     *mongoSocketslaveOk          boolconsistency      ModequeryConfig      querysafeOp           *queryOpsyncTimeout      time.DurationsockTimeout      time.Durationdefaultdb        stringsourcedb         stringdialCred         *Credentialcreds            []CredentialpoolLimit        intbypassValidation bool
}

m 是 mgo.Session 的并发锁,因此所有的 Session 实例都是线程安全的。slaveSocket,masterSocket 代表了该 Session 到 mongodb 主节点和从节点的一个物理连接的缓存。而 Session 的策略总是优先使用缓存的连接。是否缓存连接,由 consistency 也就是该 Session 的模式决定。假设在并发程序中,使用同一个 Session 实例,不使用 Copy,而该 Session 实例的模式又恰好会缓存连接,那么,所有的通过该 Session 实例的操作,都会通过同一条连接到达 mongodb。虽然 mongodb 本身的网络模型是非阻塞通信,请求可以通过一条链路,非阻塞地处理,但是会影响效率。

其次 mgo.Session 缓存的一主一从连接,实例本身不负责维护。也就是说,当 slaveSocket,masterSocket 任意其一,连接断开,Session 自己不会重置缓存,该 Session 的使用者如果不主动重置缓存,调用者得到的将永远是 EOF。这种情况在主从切换时就会发生,在网络抖动时也会发生。

mgo 的 DB 句柄需要你做一个 copy 操作:

// Copy works just like New, but preserves the exact authentication
// information from the original session.
func (s *Session) Copy() *Session {s.m.Lock()scopy := copySession(s, true)s.m.Unlock()scopy.Refresh()return scopy
}

copySession 将源 Session 浅拷贝到临时 Session 中,这样源 Session 的配置就拷贝到了临时 Session 中。关键的 Refresh,将源 Session 浅拷贝到临时 Session 的连接缓存指针,也就是 slaveSocket,masterSocket 置为空,这样临时 Session 就不存在缓存连接,而转为去尝试获取一个空闲的连接。

mgo 自身维护了一套到 mongodb 集群的连接池。这套连接池机制以 mongodb 数据库服务器为最小单位,每个 mongodb 都会在 mgo 内部,对应一个 mongoServer 结构体的实例,一个实例代表着 mgo 持有的到该数据库的连接。看看这个连接池的定义:

type mongoServer struct {sync.RWMutexAddr          stringResolvedAddr  stringtcpaddr       *net.TCPAddrunusedSockets []*mongoSocketliveSockets   []*mongoSocketclosed        boolabended       boolsync          chan booldial          dialerpingValue     time.DurationpingIndex     intpingCount     uint32pingWindow    [6]time.Durationinfo          *mongoServerInfo
}

info 代表了该实例对应的数据库服务器在集群中的信息——是否 master,ReplicaSetName 等。而两个 Slice,就是传说中的连接池。unusedSockets 存储当前空闲的连接,liveSockets 存储当前活跃中的连接,Session 缓存的连接就同时存放在 liveSockets 切片中,而临时 Session 获取到的连接就位于 unusedSockets 切片中。

每个 mongoServer 都会隶属于一个 mongoCluster 结构,相当于 mgo 在内部,模拟出了 mongodb 数据库集群的模型。

type mongoCluster struct {sync.RWMutexserverSynced sync.ConduserSeeds    []stringdynaSeeds    []stringservers      mongoServersmasters      mongoServersreferences   intsyncing      booldirect       boolfailFast     boolsyncCount    uintsetName      stringcachedIndex  map[string]boolsync         chan booldial         dialer
}

mongoCluster 持有一系列 mongoServer 的实例,以主从结构分散到两个数组中。 每个 Session 都会存储自己对应的,要操作的 mongoCluster 的引用。

前面的描述可以总结成下面这张图:

那么我们在使用的时候就可以创建一个 Session,然后 clone 操作,用 clone 得到的 copysession 完成操作,结束后关闭这个 copysession 就可以了。

Golang mgo 剖析之 Session相关推荐

  1. golang mgo 使用

    golang使用mongodb,目前比较多人用的是mgo(pronounced as mango) github地址 官网 文档 直接上官方example的代码 Example 首先是要获得模块 go ...

  2. golang 性能剖析pprof

    作为一个golang coder,使用golang编写代码是基本的要求. 能够写出代码,并能够熟悉程序执行过程中各方面的性能指标,则是更上一层楼. 如果在程序出现性能问题的时候,可以快速定位和解决问题 ...

  3. golang常用库之-mgo.v2包、MongoDB官方go-mongo-driver包、七牛Qmgo包 | go操作mongodb、mongodb bson

    文章目录 golang常用库之-mgo.v2包.MongoDB官方go-mongo-driver包.七牛Qmgo包 | go操作mongodb.mongodb bson 一.[不推荐]mgo.v2包 ...

  4. Golang使用mgo.v2包操作MongoDB的基础示例

    golang对MongoDB的操作使用gopkg.in/mgo.v2库操作.如下是基本的一些用法 连接 package main import ( "log" "time ...

  5. MongoDB的Go语言驱动----mgo的使用指南

    转自:https://blog.csdn.net/skh2015java/article/details/53033473 mgo简介 mgo(音mango)是MongoDB的Go语言驱动,它用基于G ...

  6. session机制详解以及session的相关应用

    2019独角兽企业重金招聘Python工程师标准>>> session是web开发里一个重要的概念,在大多数web应用里session都是被当做现成的东西,拿来就直接用,但是一些复杂 ...

  7. mgo和mongo-go-driver使用心得比较

    mgo和mongo-go-driver使用心得比较 >> 资源下载: https://72k.us/file/14896800-396374653 mgo和mongo-go-driver比 ...

  8. Java Web 项目入门指南(http、Servlet、Request、Response、ServletContext、会话技术[cookie、session]、Filter、Listener)

    概述 web 服务器.项目.资源概述 web 服务器:可以被浏览器访问到的服务器 常见的 web 服务器: tomcat:中小型的服务器软件,免费开源,支持 JSP 和 Servlet apache ...

  9. go使用mongodb

    何为MongoDB? 简介  MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统.  在高负载的情况下,添加更多的节点,可以保证服务器性能.  MongoDB 旨在为WEB ...

最新文章

  1. java.utilDate和java.sql.Date
  2. telegraf监控mysql数据库_部署Telegraf+Influxdb+Grafana 架构来监控 MySQL
  3. python编程之slice与indices函数用法
  4. UPS远程监控系统的设计与实现
  5. hihoCoder 1014trie树(字典树)
  6. 图神经网络(GNN)模型原理及应用综述
  7. stm32 上电初始化串口输出一个字节FF问题
  8. 勤哲excel服务器2017试用
  9. 间接蒸发冷却在华北地区某数据中心的应用
  10. 每日一算法:杨辉三角形
  11. 单层决策树python_基于单层决策树的adaboost算法Python实现
  12. MFQE 2.0: A New Approach for Multi-FrameQuality Enhancement on Compressed Video
  13. 飞图FLYTOUAV垂起固定翼无人机采用交叉环绕飞行搭载单镜头相机做高精度,高效率,长航时,大比例尺地籍测量中应用
  14. 关于iOS端引入Myscript 的爬坑过程(pod install error)
  15. 最后一个道士 第二章
  16. 查看对方使用什么手机型号
  17. Docker存储驱动之Btrfs简介
  18. ImageLoader 图片异步加载类库的使用
  19. c语言用随机投点法计算圆周率,(原创精品)用随机投点法计算π值【compute π with dartpoint randomly】...
  20. python五大模块_python-5-常用模块

热门文章

  1. 黑产系列02-黑产画像
  2. linux系统Centos7更换下载源阿里云
  3. IntelliJ IDEA -2017.3.2(Ultimate Edition)的激活方式
  4. 计算机领域职业简介-PM,RD,FE,UE,UI,QA,OP,DBA,BRD,MRD,PRD,FSD等缩写的全称解析
  5. java中整数的整数次方_数值的整数次方
  6. CSX Corp(CSX)2020年第三季度收益电话会议记录
  7. odis工程师使用教程_odis工程师版6.7.5图文安装教程
  8. 产品经理(20) #PRD产品需求文档
  9. 2017 java 面试大全
  10. 震撼人心的战争类背景音乐