Skip to content

Commit 146e12c

Browse files
author
yangjingjing
committed
init blog
1 parent 56c9d28 commit 146e12c

77 files changed

Lines changed: 4632 additions & 736 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

_posts/2015-03-11-并发源码ThreadPoolExecutor.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,3 +1257,9 @@ private void processWorkerExit(Worker w, boolean completedAbruptly) {
12571257
}
12581258
}
12591259
```
1260+
1261+
```
1262+
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10,
1263+
0L, TimeUnit.MILLISECONDS,
1264+
new ArrayBlockingQueue<>(200), r -> new Thread(r,"GraphRefreshRedisThread"), new ThreadPoolExecutor.CallerRunsPolicy());
1265+
```

_posts/2018-03-05-Mongodb查询.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ keywords: Mongodb
5353
在使用Collection对象查找和修改文档的操作中,有些操作允许您指定query参数。query参数对Cursor对象中返回的文档进行限制,使其值包含满足指定条件的文档。
5454
query参数是标准的JavaScript对象,但使用了MongoDB shell和服务器都能明白的特殊属性名。query参数的属性称为运算符,因为它们对数据进行运算,以确定文档是否应包含在结果集中。这些运算符判断文档中字段的值是否符合指定条件。
5555
例如,要查找所有字段count大于10且字段name为test的文档,可使用这样的query对象:
56-
```json
56+
```
5757
{count:{$gt:10}, name:'test'}
5858
```
5959
运算符$gt指定字段count大于10的文档。name:'test'使用了标准冒号语法,它指定字段name必须为test。注意到上述query对象包含多个运算符。在同一个查询中,可包含多个不同的运算符。
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
---
2+
layout: post
3+
categories: [Mongodb]
4+
description: none
5+
keywords: Mongodb
6+
---
7+
# MongoDB分片Sharding
8+
分片(sharding)是 MongoDB 用来将大型集合分割到不同服务器(或者说一个集群)上所采用的方法。
9+
10+
## MongoDB分片介绍
11+
尽管分片起源于关系型数据库分区,但 MongoDB 分片完全又是另一回事。MongoDB在1.6版本中提供分片和复本集技术使得MongoDB真正具备了生产环境部署的能力。
12+
13+
和 MySQL 分区方案相比,MongoDB 的最大区别在于它几乎能自动完成所有事情,只要告诉 MongoDB 要分配数据,它就能自动维护数据在不同服务器之间的均衡。
14+
15+
### 分片的目的
16+
高数据量和吞吐量的数据库应用会对单机的性能造成较大压力,大的查询量会将单机的CPU耗尽,大的数据量对单机的存储压力较大,最终会耗尽系统的内存而将压力转移到磁盘IO上。
17+
18+
为了解决这些问题,有两个基本的方法: 垂直扩展和水平扩展。
19+
20+
垂直扩展:增加更多的CPU和存储资源来扩展容量。
21+
22+
水平扩展:将数据集分布在多个服务器上。水平扩展即分片。
23+
24+
### 分片设计思想
25+
分片为应对高吞吐量与大数据量提供了方法。使用分片减少了每个分片需要处理的请求数,因此,通过水平扩展,集群可以提高自己的存储容量和吞吐量。举例来说,当插入一条数据时,应用只需要访问存储这条数据的分片。
26+
27+
使用分片减少了每个分片存储的数据。
28+
29+
例如,如果数据库1tb的数据集,并有4个分片,然后每个分片可能仅持有256 GB的数据。如果有40个分片,那么每个切分可能只有25GB的数据。
30+
31+
分片机制提供了如下三种优势
32+
- 对集群进行抽象,让集群“不可见”
33+
MongoDB自带了一个叫做mongos的专有路由进程。mongos就是掌握统一路口的路由器,其会将客户端发来的请求准确无误的路由到集群中的一个或者一组服务器上,同时会把接收到的响应拼装起来发回到客户端。
34+
35+
- 保证集群总是可读写
36+
MongoDB通过多种途径来确保集群的可用性和可靠性。将MongoDB的分片和复制功能结合使用,在确保数据分片到多台服务器的同时,也确保了每分数据都有相应的备份,这样就可以确保有服务器换掉时,其他的从库可以立即接替坏掉的部分继续工作。
37+
38+
- 使集群易于扩展
39+
当系统需要更多的空间和资源的时候,MongoDB使我们可以按需方便的扩充系统容量。
40+
41+
## 分片集群架构
42+
MongoDB分片群集包含以下组件:
43+
- shard
44+
分片(存储)每个分片包含分片数据的子集。每个分片都可以部署为副本集(replica set)。可以分片,不分片的数据存于主分片服务器上。部署为3成员副本集
45+
- mongos
46+
mongos充当查询路由器,提供客户端应用程序和分片集群之间的接口。可以部署多个mongos路由器。部署1个或者多个mongos
47+
- config servers
48+
配置服务器存储群集的元数据和配置设置。从MongoDB 3.4开始,必须将配置服务器部署为3成员副本集
49+
50+
注意:应用程序或者客户端必须要连接mongos才能与集群的数据进行交互,永远不应连接到单个分片以执行读取或写入操作。
51+
52+
shard是一个包含集合数据子集的容器,一个shard是一个mongod服务器或者复制集。因此,即使一个shard由很多服务器组成,也只有一个是主节点(primary),其余的包含同样的数据。
53+
54+
mongos一个路由进程。仅是路由请求并收集响应,不存储任何数据或者配置信息。可以有多个,相当于一个控制中心,负责路由和协调操作,使得集群像一个整体的系统。mongos可以运行在任何一台服务器上,有些选择放在shards服务器上,也有放在client服务器上。mongos启动时需要从config servers上获取基本信息,然后接受client端的请求,路由到shards服务器上,然后整理返回的结果发回给client服务器。
55+
56+
configserver存储集群的配置信息,包括分片和块数据信息,哪个块数据在哪个分片上。每个config server上都有一份所有块数据信息的拷贝,以保证每台config server上的数据的一致性。
57+
58+
分片键:分片键可以是单个索引字段,也可以是复合索引所涵盖的多个字段,该复合索引确定集合文档在集群分片之间的分布。
59+
60+
对冲读取:从版本4.4开始,实例可以对冲使用非读取首选项的读取。使用对冲读取实例将读取操作路由到每个查询分片的两个副本集成员,并返回每个分片的第一个响应者的结果。
61+
62+
### 分片集群的构造
63+
- mongos :数据路由,和客户端打交道的模块。mongos本身没有任何数据,他也不知道该怎么处理这数据,去找config server
64+
- config server:所有存、取数据的方式,所有shard节点的信息,分片功能的一些配置信息。可以理解为真实数据的元数据。
65+
- shard:真正的数据存储位置,以chunk为单位存数据。
66+
67+
Mongos本身并不持久化数据,Sharded cluster所有的元数据都会存储到Config Server,而用户的数据会议分散存储到各个shard。Mongos启动后,会从配置服务器加载元数据,开始提供服务,将用户的请求正确路由到对应的碎片。
68+
69+
### Mongos的路由功能
70+
当数据写入时,MongoDB Cluster根据分片键设计写入数据。 当外部语句发起数据查询时,MongoDB根据数据分布自动路由至指定节点返回数据。
71+
72+
MongoDB 包含一个自动分片模块 ("mongos")。自动分片可以用于构建一个大规模的可扩展的数据库集群,这个集群可以并入动态增加的机器,自动建立一个水平扩展的数据库集群系统,将数据库数据存储在sharding的各个节点上。
73+
74+
应用程序可以通过mongos process登陆shard集群,mongosprocess负责进行路由调度,将请求分发到合适的shard server上。对应用来说shard 端就像一个单节点数据库,但是数据库的存储空间无限扩大。假如要写大量数据到某个集合,这些数据会分发到多个shared server中,查询也是如此,因此查询效率会较高。
75+
76+
## 原理
77+
78+
### 工作原理
79+
MongoDB分片的基本原理是把集合分成更小的chunks。这些chunks可以分散到不同的shards,每个shard负责集合的一部分。应用程序不会知道哪个分片有哪些数据,甚至不知道数据被放到了不同的shards。只有在shards的前端运行的路由进程mongos,才知道所有的数据放在哪,应用程序连接mongos,就可像平常一样发起查询。
80+
81+
### chunks
82+
分割按有序分割方式,每个shard上的数据为某一范围的数据块(一个shard含有一个集合的多个chunk),故可支持指定分片的范围查询。数据块有指定的最大容量,一旦某个数据块的容量增长到最大容量时,这个数据块会切分成为两块;当分片的数据过多时,数据块将被迁移到系统的其他分片中。另外,新的分片加入时,数据块也会迁移。
83+
84+
### shared key
85+
分片的关键在于shard key。通过shard key划分每个shard上的chunk。比如,根据集合的title字段做shard key,分为三个shard,那么,分成A-F开头的文档chunk,G-N开头的文档chunk,及O-Z开头的文档chunk,将分别存储于三个shard中。当增加或者删除一个shard时,chunk块将重新划分,不过,mongodb会使每一个shard在负载和总量上保持平衡。一个高访问量的shard拥有的数据可能比一个低访问量的shard少。
86+
87+
对已经存在的集合,如果该集合都在一个shard上,增加一个新的shard,按照集合的title作为shard key分片,那么,mongodb会按照title的开头字母将这个集合分成两个chunk,其中一个chunk将会被移动到新增的shard中。
88+
89+
被查询的数据,不论来自于1台shard,还是在所有shard中获取,都是由mongos来统一整理的。
90+
91+
## 集群中数据分布
92+
93+
### Chunk是什么
94+
在一个shard server内部,MongoDB还是会把数据分为chunks,每个chunk代表这个shard server内部一部分数据。
95+
96+
chunk的产生,会有以下两个用途:
97+
- Splitting:当一个chunk的大小超过配置中的chunk size时,MongoDB的后台进程会把这个chunk切分成更小的chunk,从而避免chunk过大的情况
98+
- Balancing:在MongoDB中,balancer是一个后台进程,负责chunk的迁移,从而均衡各个shard server的负载,系统初始1个chunk,chunk size默认值64M,生产库上选择适合业务的chunk size是最好的。ongoDB会自动拆分和迁移chunks。
99+
100+
分片集群的数据分布(shard节点)
101+
- 使用chunk来存储数据
102+
- 进群搭建完成之后,默认开启一个chunk,大小是64M,
103+
- 存储需求超过64M,chunk会进行分裂,如果单位时间存储需求很大,设置更大的chunk
104+
- chunk会被自动均衡迁移。
105+
106+
### chunksize 的选择
107+
适合业务的chunksize是最好的。 chunk的分裂和迁移非常消耗IO资源;chunk分裂的时机:在插入和更新,读数据不会分裂。
108+
109+
chunksize的选择:
110+
111+
小的chunksize:数据均衡是迁移速度快,数据分布更均匀。数据分裂频繁,路由节点消耗更多资源。大的chunksize:数据分裂少。数据块移动集中消耗IO资源。通常100-200M
112+
113+
## chunk分裂及迁移
114+
随着数据的增长,其中的数据大小超过了配置的chunk size,默认是64M,则这个chunk就会分裂成两个。数据的增长会让chunk分裂得越来越多。
115+
116+
这时候,各个shard 上的chunk数量就会不平衡。这时候,mongos中的一个组件balancer 就会执行自动平衡。把chunk从chunk数量最多的shard节点挪动到数量最少的节点。
117+
118+
### chunkSize 对分裂及迁移的影响
119+
MongoDB 默认的 chunkSize 为64MB,如无特殊需求,建议保持默认值;chunkSize 会直接影响到 chunk 分裂、迁移的行为。
120+
121+
chunkSize 越小,chunk 分裂及迁移越多,数据分布越均衡;反之,chunkSize 越大,chunk 分裂及迁移会更少,但可能导致数据分布不均。
122+
123+
chunkSize 太小,容易出现 jumbo chunk(即shardKey 的某个取值出现频率很高,这些文档只能放到一个 chunk 里,无法再分裂)而无法迁移;chunkSize 越大,则可能出现 chunk 内文档数太多(chunk 内文档数不能超过 250000 )而无法迁移。
124+
125+
chunk 自动分裂只会在数据写入时触发,所以如果将 chunkSize 改小,系统需要一定的时间来将 chunk 分裂到指定的大小。
126+
127+
chunk 只会分裂,不会合并,所以即使将 chunkSize 改大,现有的 chunk 数量不会减少,但 chunk 大小会随着写入不断增长,直到达到目标大小。
128+
129+
## 数据区分
130+
131+
### 分片键shard key
132+
MongoDB 中数据的分片是、以集合为基本单位的,集合中的数据通过片键(Shard key)被分成多部分。其实片键就是在集合中选一个键,用该键的值作为数据拆分的依据。
133+
134+
所以一个好的片键对分片至关重要。片键必须是一个索引,通过sh.shardCollection加会自动创建索引(前提是此集合不存在的情况下)。一个自增的片键对写入和数据均匀分布就不是很好,因为自增的片键总会在一个分片上写入,后续达到某个阀值可能会写到别的分片。但是按照片键查询会非常高效。
135+
136+
随机片键对数据的均匀分布效果很好。注意尽量避免在多个分片上进行查询。在所有分片上查询,mongos会对结果进行归并排序。
137+
138+
对集合进行分片时,你需要选择一个片键,片键是每条记录都必须包含的,且建立了索引的单个字段或复合字段,MongoDB按照片键将数据划分到不同的数据块中,并将数据块均衡地分布到所有分片中。
139+
140+
为了按照片键划分数据块,MongoDB使用基于范围的分片方式或者 基于哈希的分片方式。
141+
142+
注意:
143+
144+
分片键是不可变。
145+
146+
分片键必须有索引。
147+
148+
分片键大小限制512bytes。
149+
150+
分片键用于路由查询。
151+
152+
MongoDB不接受已进行collection级分片的collection上插入无分片
153+
154+
键的文档(也不支持空值插入)
155+
156+
## 分片策略
157+
158+
### 基于哈希的分片
159+
分片过程中利用哈希索引作为分片的单个键,且哈希分片的片键只能使用一个字段,而基于哈希片键最大的好处就是保证数据在各个节点分布基本均匀。
160+
161+
对于基于哈希的分片,MongoDB计算一个字段的哈希值,并用这个哈希值来创建数据块。在使用基于哈希分片的系统中,拥有”相近”片键的文档很可能不会存储在同一个数据块中,因此数据的分离性更好一些。
162+
163+
Hash分片与范围分片互补,能将文档随机的分散到各个chunk,充分的扩展写能力,弥补了范围分片的不足,但不能高效的服务范围查询,所有的范围查询要分发到后端所有的Shard才能找出满足条件的文档。
164+
165+
### 以范围为基础的分片Sharded Cluster
166+
Sharded Cluster支持将单个集合的数据分散存储在多shard上,用户可以指定根据集合内文档的某个字段即shard key来进行范围分片(range sharding)。
167+
168+
对于基于范围的分片,MongoDB按照片键的范围把数据分成不同部分。
169+
170+
假设有一个数字的片键:想象一个从负无穷到正无穷的直线,每一个片键的值都在直线上画了一个点。MongoDB把这条直线划分为更短的不重叠的片段,并称之为数据块,每个数据块包含了片键在一定范围内的数据。在使用片键做范围划分的系统中,拥有”相近”片键的文档很可能存储在同一个数据块中,因此也会存储在同一个分片中。
171+
172+
173+
174+
## 分片键选择建议
175+
- 递增的sharding key
176+
数据文件挪动小。(优势)
177+
因为数据文件递增,所以会把insert的写IO永久放在最后一片上,造成最后一片的写热点。同时,随着最后一片的数据量增大,将不断的发生迁移至之前的片上。
178+
179+
- 随机的sharding key
180+
数据分布均匀,insert的写IO均匀分布在多个片上。(优势) 大量的随机IO,磁盘不堪重荷。
181+
182+
- 混合型key
183+
大方向随机递增,小范围随机分布。 为了防止出现大量的chunk均衡迁移,可能造成的IO压力。我们需要设置合理分片使用策略(片键的选择、分片算法(range、hash))
184+
185+
分片注意:
186+
- 分片键是不可变、分片键必须有索引、分片键大小限制512bytes、分片键用于路由查询。
187+
- MongoDB不接受已进行collection级分片的collection上插入无分片键的文档(也不支持空值插入)
188+

0 commit comments

Comments
 (0)