mongo复制集之读写分离(php)

准备工作

偷我大哥@mike.wang两篇博客

  1. 复制集入门
  2. 复制集连接
    接着往下说

读取首选项

了解了读取首选项之后,问题就来了,我既想读写分离,又要数据一致怎么办。

等待写入复制

配置 描述 是否能保证读写分离时数据一致
w=0 写完后就不管了
w=1 默认值,等待主节点确认成功
w=n 一直等待直到主节点和n-1个从节点确认成功 是,但是每新增一个节点就要改一次配置,不可取
w=majority 一直等待直到大多数数据节点确认成功
w={tag set} 一直等待直到tag set里的所有数据节点确认成功 是(配置灵活且新增配置不用改配置文件,推荐)

一定,千万,绝对不要忘了wtimeout
牺牲了写入速度,但问题好像确实解决了,但是这样真的好吗?当数据一致性要求较高的时候,适合做读写分离吗?我也不知道,之后再说。
个人觉得当数据一致性要求较高的时候,如果从节点不是很多,对读取性能提升不是很大,那还是不要做了

php mongo配置

关于php mongo配置的介绍
还有优化参考,下面是我copy的一部分觉得有必要看一下的

减少is_master_interval值

对于对可用性要求高的应用程序来说,建议检查默认的驱动程序运行时的配置设置。
mongo.is_master_interval选项控制着在复制集重新选举时驱动如何快速恢复。
is_master_interval选项默认值为15s,设置驱动发送“isMaster”请求每个mongod实例的时间间隔。这些请求帮助驱动程序判断复制集的拓扑结构,具体的来说,就是请求检测哪个节点是primary并可以接收写操作。
建议将该值设置为1或2秒,以让驱动程序在集群选举或故障转移时,能够迅速的定位到primary节点。当然啦,这也取决于有多少客户端以及ping的频率。
注意,当primary节点发生变化时,如选举或故障转移,总是会有几秒钟驱动程序会收到一个“MongoConnectionException” 信息 “No candidate servers found”。这些异常需要在你的代码中进行处理.

default_socket_timeout

PHP驱动程序不显示的定义一个默认的连接超时。相反,默认值由php.ini文件中的default_socket_timeout选项决定,默认是60秒。连接将等待60秒断开,时间有些长,需要降低些。

还有一个mongo集群管理图形化工具umongo

Go语言环境搭建(windows版)

下载地址

我用的是1.5.2, 系统win10 64位版本

更改环境变量

  • $GOROOT go安装目录 (msi安装会在安装过程中写入系统环境变量GOROOT)
  • $GOBIN bin目录 (msi安装也会在安装过程中加入系统环境变量Path中)
  • $GOARCH 目标平台(编译后的目标平台)的处理器架构(386、amd64、arm)
  • $GOOS 目标平台(编译后的目标平台)的操作系统(darwin、freebsd、linux、windows)

都配好之后打开一个新的,新的,新的命令行窗口(重要的事情说三遍,喜欢提前准备一堆命令行窗口的同学注意了)运行go version如果能看到版本信息说明配置成功。

Hello World

江湖规矩, hello world, 只不过这一次是hello go

hello.go

1
2
3
4
5
6
7
package main

import "fmt"

func main(){
fmt.Printf("Hello,GO!\n")
}

我们来分析下这个程序:

  1. 程序中的第1行这个是必须的。所有的Go文件以package 开头,对于独立运行的执行文件必须是package main;

  2. 第3行说需要将”fmt”包加入main。不是main的其他包都被称为库,其他许多编程语言有着类似的概念。

  3. package main 必须首先出现,紧跟着是import。在Go中,package 总是首先出现,然后是import,然后是其他所有内容。当Go 程序在执行的时候,首先调用的函数是main.main(),这是从C 中继承而来。

  4. 第6行调用了来自于fmt包的函数打印字符串到屏幕

应用目录结构

GOPATH设置

仅仅是hello world肯定是不够的,我们的目标是星辰大海。这个时候我们就需要了解GOPATH,GOPATH其实就是工作目录,GOPATH允许多个目录,当有多个目录时,请注意分隔符,多个目录的时候Windows是分号,Linux系统是冒号,当有多个GOPATH时,默认会将go get的内容放在第一个目录下。

新建环境变量GOPATH,目录可以随意设置,但是需要注意的是不能和GOROOT设置为同一个目录

$GOPATH 目录约定有三个子目录:

  1. src 存放源代码(比如:.go .c .h .s等)

  2. pkg 编译后生成的文件(比如:.a)

  3. bin 编译后生成的可执行文件(为了方便,可以把此目录加入到 $PATH 变量中

    应用目录结构

建立包和目录:$GOPATH/src/collection/arrayHelper.go(包名:”collection”)

arrayHelper.go

1
2
3
4
5
6
7
8
9
10
package collections

func InArray(needle string, haystack []string) bool {
for _, item := range haystack {
if item == needle {
return true
}
}
return false
}

以后自己新建应用或者一个代码包都是在src目录下新建一个文件夹,文件夹名称一般是代码包名称,当然也允许多级目录,例如在src下面新建了目录$GOPATH/src/github.com/astaxie/beedb,那么这个包路径就是“github.com/astaxie/beedb”,包名称是最后一个目录beedb

编译应用

上面我们已经建立了自己的应用包,如何进行编译安装呢?有两种方式可以进行安装

  1. 只要进入对应的应用包目录,然后执行go install,就可以安装了

  2. 在任意的目录执行如下代码go install collections

安装完之后,我们可以进入目录: $GOPATH/pkg/${GOOS}_${GOARCH}, 还记得刚刚神秘的$GOOS和$GOARCH吗?

没错他们出现了,比如我的目录就是$GOPATH/pkg/pkg/windows_amd64

这个.a文件是应用包,那么我们如何进行调用呢?

我们来修改一下刚刚的hello.go

1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"
import "collections"

func main(){
backendGroup := []string{"rex", "mike"}
fmt.Printf("Is rex in backend group: ", collections.InArray("rex", backendGroup))
fmt.Printf("\nIs hank in backend group: ", collections.InArray("hank", backendGroup))
fmt.Printf("\nHello,GO!\n")
}

如何编译程序呢?进入该应用目录,然后执行go build,那么在该目录下面会生成一个和文件夹名字相同的可执行文件,比如我的是hellogo.exe

如何安装该应用?进入该目录执行go install,那么在$GOPATH/bin/下增加了一个可执行文件hellogo.exe,这样可以在命令行输入如下命令就可以执行。当然前提是你已经把bin目录加入到Path下了

最后贴一下这次的代码目录结构

目录结构

参考资料
  1. http://www.cnblogs.com/draem0507/p/3327487.html
  2. http://www.jb51.net/article/56779.htm