最近project需要mongo做存储,因此在这里总结一些mongo的东西

基本概念

Mongo是一个开源的文档型数据库,它提供了高性能、高可用和自动扩展的特性。

概念对应关系如下表:

SQL术语/概念 MongoDB术语/概念 解释/说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins 表连接,MongoDB不支持
primary key primary key 主键,MongoDB自动将_id字段设置为主键
aggregation(group by) aggregation pipeline 聚合函数
transactions transactions 事物

mongo支持包括mongo shell、c++、java、python、php等几乎所有主流语言。只需要下好对应的driver即可,下面的操作我们使用pymongo来完成。

CURD操作

CURD是数据库基本操作。这里用pymongo来创建mongo client。

1
2
3
4
5
6
7
from pymongo import MongoClient

#首先要创建一个mongo client来运行mongo instance
client = MongoClient('localhost', 27017)

#选中需要操作的database(test)和collection(inventory)
inventory = client['test']['inventory']

Read操作

1
2
3
4
5
6
result = collection.find_one({filter})

results = collection.find({filter}).limit(5)

#example
values = inventory.find({"type": {"$regex": "Event"}})

Update操作

1
2
3
4
collection.update_one({filter},<{$set}>)

#example
inventory.update_one({"id": "2614896652"}, {"$set": {"type": "CreateEvent"}})

Create操作

1
2
3
4
5
6
7
#在这里我读取一个json文件,然后存入数据库中
data = []
with open("/data/test.json", 'r', encoding="utf-8") as f:
for content in f.readlines():
data.append(json.loads(content))

inventory.insert_many(data)

Delete操作

1
2
3
4
collection.delete_many({filter})

#example
inventory.delete_many({}) #删除全部记录

Bulk Write操作

1
2
3
4
5
6
7
8
from pymongo import InsertOne,DeleteMany,UpdateOne

#第一个参数数组为operations数组,ordered表示是否顺序执行
inventory.bulk_write([
InsertOne(data[0]),
UpdateOne({"id": "2614896652"}, {"$set": {"type": "PushEvent"}}),
DeleteMany({})
], ordered=True)

Text Search操作

1
2
3
4
5
6
7
#mongo提供了针对文本内容search的方法,要想使用这个就要先对对应field创建text index

#创建text index
db.inventory.createIndex({"type":"text"})

#文本搜索
values = inventory.find({"$text": {"$search": "CreateEvent"}})

Replication

replica

一组replica只指存相同数据的节点集。其中只有一个被认为是primary节点,其他是secondary节点(类似于master-slave)。

只有primary节点可以接受所有的写操作,并且通过{w:”majority”}来确认通知。同时primary会把所有数据操作放在oplog里。

对于secondary节点,他们会备份primary节点的oplog,然后把log里的东西apply到自己的节点上,这样primary上的dataset也就映射到了secondary上。当primary不可用时,secondaries会通过选举决定谁是primary。

secondaySelection

你可以额外增加一个叫arbiter的节点,arbiter不维护任何数据,它通过应答其他节点发出的心跳和选举请求,维护了投票时需要的法定人数。因为它本身不维护dataset,所以它占用的资源很少,也不要单独硬件。所以当节点数为偶数时,可以增加一个arbiter来维护。

arbiter

Asynchronous Replication

secondary本身异步地从primary复制。完成备份后,即使。

Automatic Failover

当primary在一定时间(configured by electionTimeoutMillis,10s default)不与secondary通信时,有资格的secondary会提名自己参加选举,cluster会试图完成选举并恢复正常功能。

在选举阶段,这个replica set都无法进行写操作,个别secondary如果配置了允许读操作的话还是正常进行的。通常系统会在12s只能判定一个primary不可用并完成选举工作。

Sharding

Sharding是Mongo采用的一种在多台机器上分布数据的方法。对于在大量、高吞吐率的数据在单台服务器上无法承载,有两种方法来扩展机器:

  • Vertical Scaling:增加单机的容量、内存,使用更好的cpu等方式。但这种受限于目前可用的技术能力。
  • Horizontal Scaling:增加机器的数量,每个机器只要handle一部分数据。比较便宜,但维护和部署基础设施成本较高。

Sharding cluster包含一下组件:

  • Shard:每个shard包含总的一个子数据集。每个shard都可以被部署为备用数据集。
  • mongos:mongos作为query router,提供了client和sharded cluster之间的借口。
  • config servers:储存了metadata和cluster的配置设置。在mongo3.4,其必须被部署为一个备用数据集(CSRS)。

关系组图如下:

sharded cluster

MongoDB从collection层面来分割数据。

Shard Keys

MongoDB是根据shard key来分割一个collection的。shard key是由目标collection中每个document都有的fields或者不变的field组成的。

在分割collection时要选择shard key,分割完后shard key就不能再改变了。

对于非空collection,必须有一个index是以shard key开头的;而对于空collection,MongoDB则会创建一个index。

shard keys的选择会影响sharded cluster的性能、效率、扩展性等问题,它和它背后的index也会影响你的集群可以使用的sharding策略。

Chunks

MongoDB会数据分成一个个的chunks,其中包含了左闭右开的shard key范围。Mongo使用shared cluster balancer来实现在sharded cluster上的不同shards间移动chunks。

Sharded and Non-sharded Collections

每个数据库都可以既有sharded collections又有un-sharded collections。unsharded collection存在数据库的primary shard上。每个数据库都有primary shard。

Connecting to a sharded Cluster

shaded connection

用户通过mongos router来实现和sharded cluster(包含sharded和unsharded collections)的交互。client做读写操作时不能只连接一个shard。

Sharding Strategy

具体来说sharding的方式有两种:

Hashed Sharding

通过计算shard key的hash值来分到不同的chunk中。在使用hashed indexes来处理查询时,client不需要计算hash,这个由MongoDB自动完成。

hashed sharding

对于那种很接近的shard key(例如单调递增的),hash通常会比较均匀地把他们分到不同的chunk里。这样存在个问题:当我要取一定范围内的数据时,需要从各个不同的chunk里取,造成较大范围的broadcast operations。

Ranged Sharding

把shard key的值分成一定范围区间,然后分配。

ranged sharding

这样相近的shard key实在同一个chunk里的,这样mongos只需要把operation route到包含这些数据的shards。

这个方式很依赖shard key的选择,不理想的话可能造成数据分配不平衡。

Zones in Sharded clusters

在sharded clusters里,可以把几个shard对应到一个zone中,一个shard也可以对应到多个zone里。chunks只在相同zone下的几个shards中转移。

zoneMongoDB

zones存在的目的是提高在大的sharded clusters里数据的本地化程度。