分类目录 ‘Database’

MongoDB: 8. Sharding (1)

作者: seasun

将海量的数据水平或垂直切割,分区存储到多台服务器上是一个最基本的现实需求。从 1.6 版开始, Sharding 总算打上了 “production-ready” 标记。

MongoDB 的数据分块称为 chunk。每个 chunk 都是 Collection 中一段连续的数据记录,通常最大尺寸是 200MB,超出则生成新的数据块。

要构建一个 MongoDB Sharding Cluster,需要三种角色:

  • Shard Server: mongod 实例,用于存储实际的数据块。
  • Config Server: mongod 实例,存储了整个 Cluster Metadata,其中包括 chunk 信息。
  • Route Server: mongos 实例,前端路由,客户端由此接入,且让整个集群看上去像单一进程数据库。

Route 转发请求到实际的目标服务进程,并将多个结果合并回传给客户端。Route 本身并不存储任何数据和状态,仅在启动时从 Config Server 获取信息。Config Server 上的任何变动都会传递给所有的 Route Process。
(全文 …)

2. Master/Slave

Master/Slave 是一种典型的备份方案, 支持 “One Master Multi Salver” 和 “Multi Master One Slave” 等多种部署方式。

先从简单的 “镜像备份” 开始。

$ sudo mkdir -p /var/mongodb/0
$ sudo mkdir -p /var/mongodb/1

$ sudo ./mongod --fork --logpath /dev/null --dbpath /var/mongodb/0 --master
forked process: 1388
all output going to: /dev/null

$ sudo ./mongod --fork --logpath /dev/null --dbpath /var/mongodb/1 --port 27018 --slave --source localhost:27017 --autoresync
forked process: 1401
all output going to: /dev/null

autoresync 参数会在系统发生意外情况造成主从数据不同步时,自动启动复制操作 (同步复制 10 分钟内仅执行一次)。除此之外,还可以用 –slavedelay 设定更新频率(秒)。
(全文 …)

最新的 1.6 版总算提供了 Replica Sets,比起有点莫名其妙的 Replica Pairs,这才是高可用集群所需要的。

1. Replica Sets

Replica Sets 使用 n 个 Mongod 节点,构建具备自动容错转移(auto-failover)、自动恢复(auto-recovery) 的高可用方案。通常使用 3 个 mongod 实例,或者 2 mongod + 1 arbiter 方案。

(1) 首先启动所需的 Mongod 节点。注意使用 replSet 参数指定 Sets Name。

$ sudo mkdir -p /var//0
$ sudo mkdir -p /var//1
$ sudo mkdir -p /var//2

$ sudo ./mongod --fork --logpath /dev/null --dbpath /var//0 --port 27017 --replSet myset
forked process: 1166
all output going to: /dev/null

$ sudo ./mongod --fork --logpath /dev/null --dbpath /var//1 --port 27018 --replSet myset
forked process: 1173
all output going to: /dev/null

$ sudo ./mongod --fork --logpath /dev/null --dbpath /var//2 --port 27019 --replSet myset
forked process: 1180
all output going to: /dev/null

(全文 …)

MongoDB: 6. Optimization

作者: seasun

1. Profiler

自带 Profiler,可以非常方便地记录下所有耗时过长操作,以便于调优。

> db.setProfilingLevel(n)

n:
   0: Off;
   1: Log Slow Operations;
   2: Log All Operations.

通常我们只关心 Slow Operation,Level 1 默认记录 >100ms 的操作,当然我们也可以自己调整 “db.setProfilingLevel(2, 300)”。
Profiler 信息保存在 system.profile (Capped Collection) 中。

准备 1000000 条数据测试一下。

>>> from pymongo import *
>>> from random import randint
>>> conn = Connection()
>>> db = conn.blog

>>> for i in xrange(1000000):
    u = dict(name = "user" + str(i), age = randint(10, 90))
    db.users.insert(u)

开始调优操作。
(全文 …)

MongoDB: 5. Admin

作者: seasun

Mongod 是 核心程序,通常情况下我们只需折腾该程序即可。

1. dbpath & port

默 认数据存储路径是 /data/db,默认端口 27017,默认 HTTP 端口 28017。用 –dbpath 和 –port 改吧。

$ sudo ./mongod --dbpath /var/mongodb --port 1234

Sat Jul 24 22:58:50 MongoDB starting : pid=1683 port=1234 dbpath=/var/mongodb 64-bit

** NOTE: This is a development version (1.5.4) of MongoDB.
**       Not recommended for production.

Sat Jul 24 22:58:50 db version v1.5.4, pdfile version 4.5
Sat Jul 24 22:58:50 git version: 6c1361df41d9cabf9026364427a7df44b3c304fd
Sat Jul 24 22:58:50 sys info: Linux domU-12-31-39-06-79-A1 2.6.21.7-2.ec2.v1.2.fc8xen
[initandlisten] Sat Jul 24 22:58:50 waiting for connections on port 1234
[websvr] Sat Jul 24 22:58:50 web admin interface listening on port 2234

从启动信息可以看到 Web 管理端口 2234,CTRL + C 即可停止该进程。–bind_ip 用于设定监听绑定 IP。
(全文 …)

MongoDB: 4. Index

作者: seasun

提供了多样性的索引支持。

> for (var i = 0; i < 30; i++) {
...     u = { name : "user" + i,
...           age : 20 + i,
...           contact : {
...              address : ["address1_" + i, "address2_" + i],
...              postcode : 100000 + i,
...           }
...     };
...     db.users.insert(u);
... }

索引信息被保存在 system.indexes 中,且默认总是为 _id 创建索引。
(全文 …)

MongoDB: 3. Schema Design

作者: seasun

1. Document-Oriented

是一种面向文档(document-oriented)的数据库,其内存储的是一种 JSON-like 结构化数据。尽管拥有和关系型数据库 /Table 类似的的 DB/Collection 概念,但同一 Collection 内的 Document 可以拥有不同的属性。

(注: 以下 > 提示符表示 mongo JS 代码,>>> 为 Python 代码)

> use blog
switched to db blog

> db.users.insert({name:"user1", age:15})
> db.users.insert({name:"user2", age:20, sex:1})

> db.users.find()
{ "_id" : ObjectId("4c479885089df9b53474170a"), "name" : "user1", "age" : 15 }
{ "_id" : ObjectId("4c479896089df9b53474170b"), "name" : "user2", "age" : 20, "sex" : 1 }

(全文 …)

MongoDB: 2. Basic Usage

作者: seasun

须安装 PyMongo (Documentation)。

$ sudo easy_install -U pymongo

(注: 以下 > 提示符表示 mongo JS 代码,>>> 为 Python 代码)

1. INSERT

使 用 insert 插入文档。

> use blog
switched to db blog

> u = { name:"user1", age:23 }
{ "name" : "user1", "age" : 23 }

> db.users.insert(u)

> u2 = db.users.findOne({name:"user1"})
{
        "_id" : ObjectId("4c44fe0edef8f3492fe67d60"),
        "name" : "user1",
        "age" : 23
}

> u2.age += 3
26

> db.users.save(u2)

> db.users.find()
{ "_id" : ObjectId("4c44fe0edef8f3492fe67d60"), "name" : "user1", "age" : 26 }

(全文 …)

MongoDB: 1. Database

作者: seasun

mongo 是 MongoDB 自带的交互式 Javascript shell,用来对 Mongod 进行操作和管理的交互式环境。

使用 “./mongo –help” 可查看相关连接参数。

$ ./mongo --help

 shell version: 1.5.3

usage: ./mongo [options] [db address] [file names (ending in .js)]

db address can be:
  foo                   foo  on local machine
  192.169.0.5/foo       foo  on 192.168.0.5 machine
  192.169.0.5:9999/foo  foo  on 192.168.0.5 machine on port 9999

options:
  --shell               run the shell after executing files
  --nodb                don't connect to mongod on startup - no 'db address'
                        arg expected
  --quiet               be less chatty
  --port arg            port to connect to
  --host arg            server to connect to
  --eval arg            evaluate javascript
  -u [ --username ] arg username for authentication
  -p [ --password ] arg password for authentication
  -h [ --help ]         show this usage information
  --version             show version information
  --ipv6                enable IPv6 support (disabled by default)

file names: a list of files to run. files have to end in .js and will exit after unless --shell is specified

(全文 …)

相信MongoDB的名头不少人 已经听说过了,虽然已有针对它的Java驱动,但我敢打保票,只要你用过一次,很快就会怀念使用GORM的好时光。拜Grails的插件架构所赐,对于Grails项目来说,这不再是幻想。目前在Grails社区至少已经有两个针对MongoDB的插件:MongoDB ToolsGrails MongoDB plugin,我们该选择哪一个呢?

在查看了两个插件的信息后,我坚定地选择了后者:Grails MongoDB plugin。 原因无它:完全保留了GORM的使用习惯,而且特性几乎一样:

  • 实例方法:save、delete
  • 类方法:get、find、findAll、delete、deleteAll、exists、count、list
  • 诸如findAllByNameAndDegreeBetween(…)这样的动态查找器
  • 支持约束和验证
  • 支持自动时辍:dateCreated和lastUpdated
  • Gorm事件:beforeSave、afterSave、beforeDelete、afterDelete(还有Morphia支持的 afterLoad)
  • 支持MongoDB 1.4和1.5
  • 提供了注入所有必需字段和Morphia注解的AST Transformations
  • 支持延迟引用
  • 支持generate-all

(全文 …)