存)
MongoDB
事务型数据库
SQL DB2 INFORMIX ORACLE MYSQL…
非事务型数据库(Not Only SQL)
Data Model | Query API | |
---|---|---|
Cassandra | Column | Thrift |
CouchDB | Document | map/reduce views |
Hbase | Column | Thrift,REST |
MongoDB | Document | Cursor |
Neo4j | Graph | Graph |
Redis | Key/value | Collection |
Riak | Document | Nested hashes |
Scalaris | Key/value | get/put |
Tokyo Cabinet | Key/value | get/put |
Voldemort | Key/value | get/put |
-
非结构化
-
非事务型
-
分布式
NoSQL数据库在以下的这几种情况下比较适用:
1、数据模型比较简单;
2、对数据库性能要求较高;
3、不需要高度的数据一致性(事务方面);
分类 | 优点 | 代表数据库 |
---|---|---|
键值(Key-Value) | 键值对,使用简单,过滤及多值更新不方便 | Redis、Tokyo Cabinet等 |
列式存储 | 通常是用来应对分布式存储的海量数据 | HBase、Cassandra |
文档型 | 键值存储相类似。该类型的数据模型是版本化的文档,半结构化的文档以特定的格式存储,比如JSON,允许之间嵌套键值,文档型数据库比键值数据库的查询效率更高 | MongoDb、CouchDB |
图形(Graph) | 使用灵活的图形模型,并且能够扩展到多个服务器上 | Neo4J、HyperGraphDB |
分布式
1998年,加州大学的计算机科学家 Eric Brewer 提出,
分布式系统有三个指标:
-
一致性(C):在分布式系统中的所有数据备份,
在同一时刻是否同样的值。(等同于所有节点访问
同一份最新的数据副本)
-
可用性(A):在集群中一部分节点故障后,集群整体
是否还能响应客户端的读写请求。(对数据更新具备
高可用性)
-
分区容忍性(P):以实际效果而言,分区相当于对
通信的时限要求。系统如果不能在时限内达成数据
一致性,就意味着发生了分区的情况,必须就当前
操作在C和A之间做出选择。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x3KKWoHJ-1685440319329)(https://notes-1307435281.cos.ap-shanghai.myqcloud.com/note/master/202209010920748.png)]
CAP原则的精髓就是要么AP,要么CP,要么AC,但是不存在CAP。
-
如果在某个分布式系统中数据无副本,那么系统必然满足强一致性条件, 因为只有独一数据,不会出现数据不一致的情况,此时C和A两要素具备
-
如果在某个分布式系统中数据有副本,但是如果系统发生了网络分区状况或者宕机,必然导致某些数据不可以访问,
-
如果选择系统高可用,可立即启动恢复,则数据一致性要求不满足,即在此情况下获得了AP系统,但是CAP不可同时满足
-
如果选择数据一致性,则必须先确保数据一致再对外提供服务, 即在此情况下获得了CP系统,但是CAP不可同时满足
因此在进行分布式架构设计时,必须做出取舍。
支持的模型
支持的分布式集群模型
Master/Slaver
主从模型,适合简单小型应用,高可用要求较低
-
ReplicaSet
复制模型,适合中型应用,对可用性要求相对较高
-
Sharding
分片模型,适合高并发场景,对可用性要求较高
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EyOAWj2F-1685440319330)(https://notes-1307435281.cos.ap-shanghai.myqcloud.com/note/master/202209010952069.png)]
Master:可以读写
Slaver:可以读
Failover : Master节点Crush,整个系统Crush.
ReplicaSet模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KnjNUO0K-1685440319330)(https://notes-1307435281.cos.ap-shanghai.myqcloud.com/note/master/202209010953837.png)]
-
Primary:可以读写
-
Secondary:可以读
-
Failover :主节点Crush,可以自动转移
Sharding模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kKzh2aWm-1685440319331)(https://notes-1307435281.cos.ap-shanghai.myqcloud.com/note/master/202209010957048.png)]
Sharding:将一个数据集合,按照Sharding Key, 依次存储在Slice片上。
Slice片:上图的shard0…shard3,其实他们就是ReplicaSet复制模型,各自独立
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dSDNj7d3-1685440319331)(https://notes-1307435281.cos.ap-shanghai.myqcloud.com/note/master/202209011001530.png)]
TableT=Shard1+shard2+shard3
Shard 分片各个节点的数据是一样的,其实就是复制模型
Sharding Key对应一个要求unique的索引,并不是指一个Field唯一性的索引
Chunk是一个连续的数据集合,范围:MinKey<=Shard Key<maxKey一个Chunk一个文件,缺省情况下是200M,如果超过了200M,将会生成另外一个Chunk文件,这个值可以指定.
功能支持
- 基于文档式存储,支持bson格式
- 全文索引,3.2版本后支持文本全文索引
- 高可用,支持多种集群模式,提供稳定服务
- 数据分片存储,简单设置,自动完成分片存储
- 语义丰富,查询方便
- 高性能数据更新,3.0版本后支持表级锁,部分数据结构支持无锁
- 分布式查询 ,MapReduce原理,对请求拆分合并、支持复杂聚合运算
- GridFS 文件存储,支持大文件存储
- 专业支持,文档丰富,社区成熟
组成
MongoDB由Mongos、ConfigServer、Mongo实例三个部分组成
- Mongos
MongoDB的前置机,用于命令分发、结果集合并
- ConfigServer
配置中心,所有元数据、分片信息、集群信息都保存中ConfigServer中
- Mongod
存储实例,数据存储
处理步骤
Mongos—Routing Process
- 接收Client的请求,并将请求分发到指定的Mongod Processes,然后对返回的结果进行Merged,最后将Merged结果返回给Client.
- Route Processes是一个代理,客户端的请求都是通过该代理来访问整个Cluster的。根据实际情况,Route Processes可以配置多个.
- Routing Processes依赖于Config Servers。
- Config server存储整个Cluster的数据表,数据库,chunks信息,mongos信息,shards信息配置信息,tags信息以及锁的信息,以及日志信息
- Config server是一个Set复制模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eJW8D3ok-1685440319332)(https://notes-1307435281.cos.ap-shanghai.myqcloud.com/note/master/202209010941241.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FvgU3iB2-1685440319332)(https://notes-1307435281.cos.ap-shanghai.myqcloud.com/note/master/202209010941537.png)]
存储引擎
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2kIxpL1z-1685440319333)(https://notes-1307435281.cos.ap-shanghai.myqcloud.com/note/master/202209010942403.png)]
2.6以前的版本是采用的MMAP1技术,数据库级别的锁.
3.0以后的版本,缺省采用WiredTiger技术,实现了表级和行级的锁。行级别的锁,是将锁的颗粒度细分到具体的B+树上的对应节点,颗粒度比较细。
工作原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L8JJnSQf-1685440319333)(https://notes-1307435281.cos.ap-shanghai.myqcloud.com/note/master/202209010944066.png)]
Step1:客户端向mongos发送客户端请求
Step2:从ConfigServer获取查询语句对应的分片信息
Step3:返回数据分片信息
Step4:根据Step3的分片信息,将请求发送到对应的分片集群上
Step5:将各个分片集群的结果进行合并并返回
Step6:返回客户端请求
应用场景
mongoDB集群
UserInfo所用mongodb集群示意图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z1FOpCh7-1685440319334)(https://notes-1307435281.cos.ap-shanghai.myqcloud.com/note/master/202209011006053.png)]
安装搭建
一主,一从,一仲裁
安装 MongoDB服务
D:\mongDB\bin\mongod.exe --config "D:\mongDB\mongod.conf" --install
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1gxszz7p-1685440319334)(https://notes-1307435281.cos.ap-shanghai.myqcloud.com/note/master/202209011818372.png)]
net start MongoDB
通过配置文件启动数据库实例
#配置文件mongod.conf
port=22937
replSet=hli.lihao
dbpath=D:\mongDB\data\db\01
logpath=D:\mongDB\data\log\mongod
D:\mongDB\bin\mongod --config D:\mongDB\mongod.conf
注:在windows环境下若无设置后台运行,需一个进程一个窗口,启动完毕不要关闭窗口
测试是否成功
telnet 127.0.0.1 22937
三台全部完毕后启动客户端
#客户端连接主节点
D:\mongDB\bin>mongo.exe -port 22937
#运行
rs.initiate()
#测试查看当前状态
rs.status()
#添加从节点
rs.add('127.0.0.1:22938')
#添加仲裁节点
rs.addArb('127.0.0.1:22939')
最后查看状态输出为
MongoDB Enterprise hli.lihao:PRIMARY> rs.status()
{
"set" : "hli.lihao",
"date" : ISODate("2022-09-01T09:57:25.976Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"majorityVoteCount" : 2,
"writeMajorityCount" : 2,
"votingMembersCount" : 3,
"writableVotingMembersCount" : 2,
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1662026233, 1),
"t" : NumberLong(1)
},
"lastCommittedWallTime" : ISODate("2022-09-01T09:57:13.108Z"),
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1662026233, 1),
"t" : NumberLong(1)
},
"readConcernMajorityWallTime" : ISODate("2022-09-01T09:57:13.108Z"),
"appliedOpTime" : {
"ts" : Timestamp(1662026233, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1662026233, 1),
"t" : NumberLong(1)
},
"lastAppliedWallTime" : ISODate("2022-09-01T09:57:13.108Z"),
"lastDurableWallTime" : ISODate("2022-09-01T09:57:13.108Z")
},
"lastStableRecoveryTimestamp" : Timestamp(1662026226, 1),
"electionCandidateMetrics" : {
"lastElectionReason" : "electionTimeout",
"lastElectionDate" : ISODate("2022-09-01T09:53:06.075Z"),
"electionTerm" : NumberLong(1),
"lastCommittedOpTimeAtElection" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"lastSeenOpTimeAtElection" : {
"ts" : Timestamp(1662025986, 1),
"t" : NumberLong(-1)
},
"numVotesNeeded" : 1,
"priorityAtElection" : 1,
"electionTimeoutMillis" : NumberLong(10000),
"newTermStartDate" : ISODate("2022-09-01T09:53:06.094Z"),
"wMajorityWriteAvailabilityDate" : ISODate("2022-09-01T09:53:06.107Z")
},
"members" : [
{
"_id" : 0,
"name" : "localhost:22937",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 733,
"optime" : {
"ts" : Timestamp(1662026233, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2022-09-01T09:57:13Z"),
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1662025986, 2),
"electionDate" : ISODate("2022-09-01T09:53:06Z"),
"configVersion" : 3,
"configTerm" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "127.0.0.1:22938",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 124,
"optime" : {
"ts" : Timestamp(1662026233, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1662026233, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2022-09-01T09:57:13Z"),
"optimeDurableDate" : ISODate("2022-09-01T09:57:13Z"),
"lastHeartbeat" : ISODate("2022-09-01T09:57:25.117Z"),
"lastHeartbeatRecv" : ISODate("2022-09-01T09:57:25.135Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "localhost:22937",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 3,
"configTerm" : 1
},
{
"_id" : 2,
"name" : "127.0.0.1:22939",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 12,
"lastHeartbeat" : ISODate("2022-09-01T09:57:25.117Z"),
"lastHeartbeatRecv" : ISODate("2022-09-01T09:57:25.135Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"configVersion" : 3,
"configTerm" : 1
}
],
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1662026233, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1662026233, 1)
}
MongoDB Enterprise hli.lihao:PRIMARY>
待解决
数据一致性问题
- 一主两从
- 主节点写,从节点读
- 此时插入一张表
- 主节点刚刚写入时,还没有来的及分发给从节点时
- 这时候,默认读的是从节点的数据,此时我就想读刚插进去的这张表的数据
- 而此时从节点又没有,怎么保证数据的一致性?