分布式文档存储独角兽MongoDB、知识图谱存储数据库Neo
2021-09-21 19:04:07 1 举报
AI智能生成
分布式文档存储独角兽MongoDB、知识图谱存储数据库Neo4j
作者其他创作
大纲/内容
分布式文档存储独角兽MongoDB、知识图谱存储数据库Neo4j
1. 分布式文档存储MongDB
1. 体系结构
简介
NoSQL
Not Only SQL,支持类似SQL的功能,与关系型数据库相辅相成
其性能较高,不使用SQL意味着没有结构化的存储要求,没有约束之后架构更加灵活
四大家族
列存储 HBase
键值存储 Redis
图像存储 Neo4j
文档存储 MongoDB
MongoDB
是一个基于分布式文件存储的数据库,由C++编写,可以为Web应用提供可扩展、高性能、易部署的数据存储解决方案
是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库中功能最丰富,最像关系数据库的
在高负载的情况下,通过添加更多的节点,可以保证服务器性能
体系结构
磁盘文件
MongoDB实例
Mongo数据库
Collection
对应Table
Document
对应Row,BSON文档
Field
对应Column
BSON
介绍
一种类json的二进制形式的存储格式,简称Binary JSON
它和JSON一样,支持内嵌的文档对象和数据组对象,但是BSON有JSON没有的一些数据类型,如Date和Binary Data类型
BSON可以作为网络数据交换的一种存储形式,是一种schema-less的存储形式,它的优点是灵活性高,缺点是空间利用率不是很理想
特点
BSON有三个特点:轻量性、可遍历性、高效性
使用
MongoDB使用BSON结构来存储数据和网络数据交换
MongoDB把这种格式转化为文档这个概念,只不过Document的变化跟丰富一些,如支持嵌套
数据类型
String
字符串:UTF-8编码的字符串才是合法的
{key: "cba"}
Integer
整型数值:根据所采用的服务器,可分为32/64位
{key: 1}
Boolean
布尔值:用于存储布尔值(真/假)
{key: false}
Double
双精度浮点值:用于存储浮点值
{key: 3.14}
ObjectId
对象ID:用于创建文档的ID
{_id: new ObjectId()}
Array
数组:用于将数组或列表或多个值存储为一个键
{key: ["a", "b"]}
Timestamp
时间戳:从开始纪元开始的毫秒数
{ts: new Timestamp()}
Object
内嵌文档:文档可以作为文档中的某个key的value
{o: {foo: "bar"}}
Null
空值:表示空值或未定义的对象
{key: null}
Data/ISODate
格林威治时间:日期时间,用Unix日期格式来存储当前日期或时间
{birth: new Date()}
Code
代码:可以包含Js代码
{x: function(){}}
File
文件
二进制转码后存储(Base64,<16M)
GridFS(>16M)
用两个集合来存储一个文件:fs.files/fs.chunks
真正存储需要使用mongofiles -d gridfs put song.mp3
安装
1. 下载
2. 解压
tar -xvf
3. 启动
./bin/mongod
需自己创建 /data/db 文件夹
./bin/mongod -f mongo.cnf
指定配置文件
启动参数
dbpath
数据库目录,默认/data/db
port
监听的端口,默认27017
bind_ip
监听IP地址,默认全部可以访问
fork
是否以后台启动的方式登录
logpath
日志路径
logappend
是否追加日志
auth
是否开启用户密码登录
config
指定配置文件
mongo shell
启动
./bin/mongo
本机启动
./bin/mongo --host=xxx --port=xxx
指定主机和端口启动
GUI工具
MongDB Compass
由MongoDB开发人员开发,意味着更高的可靠性和兼容性
它为MongDB提供GUI工具,以探索数据库交互,具有完整的CRUD功能并提供可视方式
借助内置模式可视化,用户可以分析文档并显示丰富的结构
为了监控服务器的负载,它提供了数据库操作的实时统计信息
NoSQLBooster(Mongobooster)
是MongoDB_CLI界面中非常流行的GUI工具
跨平台,带有一堆mongodb工具来管理和监控数据库
2. 操作/命令
基本操作
查看数据库
show dbs
show databases
切换数据库
use dbname
如果没有对应的数据库则创建
创建集合
db.createCollection(name)
查看集合
show tables
show collections
删除集合
db.集合名.drop()
删除数据库
db.dropDatabase()
数据添加
单条数据
db.集合名.insert(文档)
所有存储在集合中的数据都是BSON格式
没有指定_id字段,系统会自动生成
_id是ObjectId类型
前4个字节表示时间戳
接下来3个字节是机器标识码
然后2个字节由进程id组成(PID)
最后三个字节是随机数
多条数据
db.集合名.insert([文档A, 文档B])
数据查询
比较条件查询
db.集合名.find(条件)
等于
{key: value}
大于
{key: {$gt:value}}
小于
{key: {$lt:value}}
大于等于
{key: {$gte:value}}
小于等于
{key: {$lte:value}}
不等于
{key: {$ne:value}}
逻辑条件查询
and
db.集合名.find({key1: value1, key2: value2})
or
db.集合名.find({$or: [{key1: values1}, {key2: values2}]})
not
db.集合名.find({key: {$not: {$操作符: value}}})
分页查询
db.集合名.find(条件).sort({排序字段: 排序方式}).skip(n).limit(size)
数据更新
操作
$set
设置字段值
$unset
删除指定字段
$inc
对修改的值进行自增
语法
db.集合名.update(, , {upsert: , multi: , writeConcern: })
参数说明
query
update的查询条件
update
update的对象和一些更新的操作符(如$set,$inc)
upsert
可选,表示不存在update的记录,是否插入objNew
默认false,不插入
multi
可选,表示是否更新所有记录
默认false,只更新第一条记录
writeConcern
可选,指定mongod对写操作的回执行为
数据删除
语法
db.集合名.remove(, { justOne: , writeConcern: })
参数说明
query
删除的文档的条件,可选
justOne
设为true/1,则只删除一个文档
默认值false
可选
writeConcern
指定mongodb对写操作的回执行为,可选
注
writeConcern
语法
{ w: , j: , wtimeout: }
参数
w
指定写操作传播到的成员数量
默认1,要求得到写操作已经传播到独立的Mongd实例或副本集的primary成员的确认
0,不要求确认写操作,可能会返回socket exceptions和networking errors
majority,要求得到写操作已经传播到大多数具有存储数据具有投票的成员的确认
j
是否要求得到Mongodb的写操作已经写到影片日志的确认
true,本身并不保证因为副本集故障而不会回滚
wtimeout
指定writeConcern的时间限制,只适用于w>1的情况
在超过指定时间后写操作会返回error,即使写操作最后执行成功,当这些写操作返回时,MongoDB不会撤销在wtimeout之前执行成功的数据修改
如果未指定wtimeout且指定writeConcern级别,则写操作将无限期阻止
0,等同于没有wtimeout选项
3. 聚合操作
简介
聚合是MongoDB的高级查询语言,允许通过转化合并由多个文档的数据来生成新的在单个文档里不存在的文档信息
一般都是将记录按条件分组之后进行一系列求最大值,最小值,平均值的简单操作,也可以对记录进行复杂数据统计,数据挖掘的操作
聚合操作输入的是集中的文档,输出可以是一个文档也可以是多个文档
分类
单目的聚合
count()
distinct()
聚合管道
db.集合名.aggregate(AGGREGATE_OPERATION)
主要用于统计数据,并返回计算后的数据结果
表达式
处理输入文档并输出
只能用于计算当前聚合管道的文档,不能处理其他文档
类型
$sum
计算总和
$avg
计算平均值
$min
获取集合中所有文档对应值的最小值
$max
获取集合中所有文档对应值的最大值
$push
在结果文档中插入值到一个数组中
$addToSet
在结构文档中插入值到一个数组中,但数据不重复
$first
根据资源文档的排序获取第一个文档数据
$last
根据资源文档排序获取最后一个文档数据
常用操作
$group
将集合中的文档分组,可用于统计结果
$project
修改输入文档的结构,可以用来重命名、增加或删除域,也可以用于创建计算结果及嵌套文档
$match
用于过滤数据,只输出符合条件的文档
使用MongDB的标准查询操作
$limit
用来限制MongoDB聚合管道返回的文档数
$skip
在聚合管道中跳过指定数量的文档,并返回余下的文档
$sort
将输入文档排序后输出
$geoNear
输出接近某一地理位置的有序文档
MongoDB中使用db.COLLECTION_NAME.aggregate([{},....])方法来创建和使用聚合管道,每个文档通过一个又一个或多个阶段(stage)组成的管道,经过一系列处理,输出相应的结果
聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的
MapReduce编程模型
说明
Pipeline查询速度快于Map Reduce,但MapReduce能够在多台Server上并行执行复杂的聚合逻辑
MongoDB不允许单个聚合操作占用过多的系统内存,如果一个聚合操作消耗20%以上的内存,那么MongoDB直接停止操作,并输出错误消息
MapReduce是一种计算模型,即将大批量工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(REDUCE)
语法
使用MapReduce要实现两个函数
Map
调用 emit(key, value), 遍历集合中的所有记录,将key/value传递给 Reduce 进行处理
JavaScript函数,负责将每一个输入文档转换为零或多个文档,生成键值对序列,传给reduce函数
Reduce
JavaScript函数,对Map操作的输出做合并的化简操作
参数
out
统计结果存放集合
query
筛选条件,只有满足条件的文档才会调用map函数
sort
和limit结合,用于在发往map前给文档排序,可以优化分组机制
limit
发往map函数的文档数量的上限
如果没有limit,单独使用sort作用不大
finalize
可以对reduce输出结果再一次修改
verbose
是否包括结果信息中的时间信息,默认为false
4. 索引
简介
默认情况下Mongo在一个集合创建时,自动的对集合_id创建了唯一索引
类型
单键索引(Single Field)
MongoDB支持所有数据类型中的单字段索引,且可以在文档中的任何字段上定义
对于单键索引,索引键的排序顺序无关紧要,因为MongoDB可以在任一方向读取索引
语法
db.集合名.createIndex({ "fieldName": 排序方式})
过期索引TTL
TTL索引是MongoDB中的一种特殊索引,可以支持文档在一定时间之后自动过期删除
目前TTL索引只能在单字段上建立,且字段类型必须为日期类型
语法
db.集合名.createIndex({"日期字段": 排序方式}, { expireAfterSeconds: 秒数})
复合索引(Compound Index)
复合索引支持基于多个字段的索引,这扩展了索引的概念并将他们扩展到索引中的更大域
创建复合索引时要注意的重要事项有:字段顺序和索引方向
语法
db.集合名.createIndex( { "field1": 排序方式, "field2": 排序方式} )
多键索引 Multikey Indexes
针对属性包含数组数据的情况。MongoDB支持针对数组中每一个element创建索引
多键索引支持strings、numbers、nested documents
地理控件索引 Geospatial Index
针对地理空间坐标数据创建索引
2dsphere索引
用于存储和查找球面上的点
2d索引
用于存储和查找平面上的点
全文索引 Fulltext Index
MongoDB提供了针对string内容的文本查询,全文索引支持任意属性值为string或string数组元素的索引查询
注意:一个集合仅支持最多一个全文索引,中文分词不理想(推荐ES)
语法
db.集合名.createIndex({ "字段": "text" })
db.集合名.find({ "$text": { "$search": "coffee" }})
哈希索引 Hashed Index
针对属性的哈希值进行索引查询
需要使用哈希索引时,MongoDB能够自动计算hash值,无需程序计算
仅支持定值查询,不支持范围查询
语法
db.集合.createIndex( {"fied": "hashed"})
管理
创建索引并后台运行
.createIndex({ ''field': sort}, {background: true})
获取针对某个集合的索引
db.collection.getIndexes()
索引大小
.totalIndexSize()
索引重建
.reIndex()
索引删除
.dropIndex(indexName)
.dropIndexes()
_id对应的索引无法删除
分析
explain(verbosity)
通过设置不同参数,可以查看更详细的查询计划
参数
queryPlanner
默认参数
executionStats
返回执行计划的一些统计信息
allPlansExecution
获取所有执行计划
结果参数与executionStats基本相同
返回
queryPlanner
plannerVesion
查询计划版本
namespace
要查询的集合:数据库.集合
indexFilterSet
针对该query是否有indexFilter
parsedQuery
查询条件
filter
过滤条件
winningPlan
被选中的执行计划
子参数
stage
被选中执行计划的查询方式
常见有
COLLSCAN:全表扫描
IXSCAN:索引扫描
FETCH:根据索引去检索文档
SHARD_MERGE:合并分片结果
IDHACK:针对_id进行查询
SORT:表明在内存中进行了排序
LIMIT:使用limit限制返回数
SKIP:使用skip进行跳过
SHARDING_FILTER:通过mongos对分片数据进行查询
COUNT:利用db.coll.explain().count()之类进行count运算
TEXT:使用全文索引进行查询
PROJECTION:限定返回字段时候返回
.....
stage.childstage
如果是IXSCAN,表示进行的是index scanning
inputStage
描述子stage,且为其父stage提供文档和索引关键字
keyPattern
所扫描的index内容
indexName
所选用的index
isMultikey
是否是多键索引
如果索引建立在array上,返回true
direction
此query的查询顺序,forward/backward
indexBounds
扫描的索引范围,如果没有指定就是[minkey, maxkey]
主要是直接定位到mongodb的chunks中去查找数据,加快数据读取
rejectedPlans
被拒绝的执行计划的详细返回
具体信息和winningPlan相同
executionStats
executionSuccess
是否执行成功
nReturned
返回的文档数
executionTimeMillis
执行耗时
totalKeysExamined
索引扫描次数
totalDocsExamined
文档扫描次数
executionStages
这个分类下描述执行的状态
stage
扫描方式
executionTimeMillisEstimate
检索document获得数据的时间
inputStage.executionTimeMillisEstimate
该查询扫描文档index所用时间
works
工作单元数,一个查询会分解成小的工作单元
advanced
优先返回的结果数
docsExamined
文档检查数目,与totalDocsExamined一致
检查了总共的document个数,返回nReturned数量
serverInfo
MongoDB服务器信息
结果分析
首先
executionTimeMillis:查询返回时间,越小越好
有3个
executionStats.executionTimeMillis
整体查询时间
executionStats.executionStages.executionTimeMillisEstimate
检索文档获得数据的时间
executionStats.executionStages.inputStage.executionTimeMillisEstimate
扫描索引所用时间
然后
index与document扫描数/查询数
有3个
nRetured
返回条目数
totalKeyExamined
索引扫描条目数
totalDocumentExamined
文档扫描条目数
最后
stage状态分析
一般希望看到
FETCH+ IDHACK
FETCH + IXSCAN
LIMIT + FETCH + IXSCAN
PROJECTION + IXSCAN
SHARDING_FILTER + IXSCAN
不希望看到
COLLSCAN
SORT
使用sort但没有index
COUNT
不使用index进行count
慢查询
1.开启内置的查询分析器,记录读写操作效率
db.setProfilingLevel(n, m)
n
0:表示不记录
1:表示记录慢速操作,m必须赋值(单位:ms,定义慢速查询时间的阈值)
2:表示记录所有读写操作
2.查询监控结果
db.system.profile.find().sort( { millis: -1}).limit(3)
3.分析慢速查询
应用程序设计是否合理
数据模型是否正确
硬件配置
索引建立
4.解读explain()结果
确定是否缺少索引
底层原理
MongoDB是文档型数据库,使用BSON格式保存数据,比关系型数据库存储更方便
MongoDB使用B-树,所有节点都存储Data,只要找到指定索引就可以进行访问,单次查询从结构上来看要快于MySQL
对比
B-树
特点
多路,非二叉树
每个节点既保存数据又保存索引
搜索时,相当于二分查找
每个节点key和data在一起,适合随机读写,区间查找效率差
如使用磁盘存储,每次磁盘预读中很多数据用不上,不能很好的利用磁盘预读提供的数据
每个节点既保存数据又保存索引,树的深度小,所以磁盘IO次数很少
B+树
特点
多路非二叉
只有叶子节点保存数据
搜索时,二分查找
增加了相邻节点指针
相邻节点的指针大大增加区间访问性,可使用在范围查询
更适合外部存储,即磁盘存储
相较B树,深度大,磁盘IO多,但是区间访问比较好
5. 应用
简述
适用场景
网站数据
非常适合实时的插入、更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性
缓存
由于性能很高,Mongo也适合作为信息基础设施的缓存层
在系统重启后,由Mongo搭建的持久化缓存层可以避免下层的数据源过载
大尺寸、低价值数据
使用传统的关系型数据库存储一些大尺寸低价值的数据时会比较浪费
在此之前一般选择文件存储
高伸缩性的场景
非常适合由数十/数百台服务器组成的数据库,Mongo路线图中已经包含对MapReduce引擎的内置支持以及集群高可用的解决方案
基于对象/JSON数据的存储
Mongo的BSON数据格式非常适合文档化格式的存储及查询
行业具体应用
游戏场景
存储游戏用户信息,用户装备、积分等直接以内嵌文档的形式存储,方便查询、更新
物流场景
存储订单信息,订单状态在运送过程中会不断更新,以内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来
社交场景
存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
物联网场景
存储所有接入的只能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析
直播
存储用户信息、礼物信息等
是否使用
应用特征
不需要事务及复杂join支持
新应用,需求会变,数据模型无法确定,想快速迭代开发
需要2000-3000以上读写QPS
需要TB甚至PB级别数据存储
发展迅速,需要能快速水平扩展
要求存储的数据不丢失
需要99.999%高可用
需要大量的地理位置查询、文本查询
Java访问
1. 导入依赖
2. 编写代码
Spring访问
1. 导入依赖
2. 配置MongoTemplate
3. 对象中注入MongoTemplate
4. 测试
boot访问
基于MongoTemplate
1. 导入依赖
2. 配置
spring.data.mongodb
host=192.168.0.112
port=27017
database=resume
3. 注入类
4. 测试
基于MongoRepository
1. 导入依赖
2. 配置
3. 编写实现类
添加注解@Document("Coll_name")
4. 继承 MongoRepository
5. 从容器获取 Respository对象
6. 测试
6. 架构
逻辑结构
查询语言
数据模型
MongoDB对数据的存储与RDBMS有较大差异,所以创建了一套不同的数据模型和查询语言
存储引擎
MongoDB与MySQL架构相差不多,底层都使用了可插拔的存储引擎以满足用户的不同需要
用户可以根据程序的数据特征选择不同的存储引擎
在最新版本的MongoDB使用了WiredTiger作为默认的存储引擎
WiredTiger提供了不同粒度的并发控制和压缩机制,能够为不同种类的应用提供最好的性能和存储率
数据模型
描述方式
内嵌
指把相关联的数据保存在同一个文档结构之中
MongoDB文档结构允许一个字段或一个数组内的值作为一个嵌套的文档
引用
通过存储数据引用信息来实现两个不同文档之间的关联
应用程序可以通过解析这些数据引用来访问相关数据
如何选择
内嵌
1. 数据对象之间有包含关系,一般是数据对象之间有一对多或一对一关系
2. 需要经常一起读取的数据
3. 有map-reduce/aggregation需求的数据放在一起,这些操作都只能操作单个collection
引用
1. 当内嵌数据会导致很多数据的重复,并且读性能的优势有不足与覆盖数据重复的弊端
2. 需要表达比较复杂的多对多关系的时候
3. 大型层次结果数据集,嵌套不要太深
存储引擎
介绍
存储引擎是MongoDB的核心组件,负责管理数据如何存储在硬盘和内存上
配置
boot
支持种类
MMAPV1
MongoDB3.2之前的默认引擎
MongoDB4.x不再支持
WiredTiger
MongoDB3.2开始的默认引擎
InMemory
用于将数据只存储在内存中,只将少量元数据(meta-data)和诊断日志(Diagnostic)存储在硬盘文件中
由于不需要Disk的IO操作,就能获取所需的数据,它大幅度降低了数据查询的延迟(Latency)
WiredTiger
优势
1. 文档空间分配方式
使用B树存储
MMAPV1线性存储,需要Padding
2. 并发级别
文档级别锁
MMAPV1使用表级锁
3. 数据压缩
snappy(默认),zlib
相比MMAPV1(无压缩)空间节省数倍
4. 内存使用
可以指定内存的使用大小
5. Cache使用
使用了二级缓存来保证磁盘数据的最终一致性
MMAPV1只有journal日志
包含文件
WiredTiger.basecfg
存储基本配置信息,与ConfigServer有关系
WiredTiger.lock
定义锁操作
table*.wt
存储各张表的数据
WiredTiger.wt
存储table*的元数据
WiredTiger.turtle
存储WiredTiger.wt的元数据
journal
存储WAL(Write Ahead Log)
实现原理
写请求
写操作会默认写入cace,并持久化到WAL,每60s或Log文件达到2G做一次checkpoint,产生快照文件
初始化时,恢复至最新的快照状态,然后再根据WAL恢复数据,保证数据的完整性
可以在写入操作时传入 j: true 强制journal文件同步
cache
是基于B树的,节点是一个page,root_page是根节点,internal_page是中间索引节点,leaf_page真正存储数据,数据以page为单位读写
WiredTiger采用Copy_on_write方式管理写操作,写操作会先缓存在cache里,持久化时,写操作不会在原来的leaf_page上进行,而是写入新分配的page
每次checkpoint都会产生一个新的root_page
checkpoint流程
1.对所有table进行一次checkpoint,每个table的checkpoint的元数据更新至WiredTiger.wt
2.对WiredTiger.wt进行checkpoint,将该table_checkpoint的元数据更新至临时文件WiredTiger.turtle.set
3.将WiredTiger.turtle.set重命名为WiredTiger.turtle
4.上述过程如果中间失败,WiredTiger在下次连接初始化时,首先将数据恢复至最新的快照状态,然后根据WAL恢复数据,以保证存储可靠性
Journaling
数据库宕机时,为保证MongoDB中数据的持久性,MongoDB使用了WAL向磁盘上的journal文件预先进行写入
除了journal日志,MongoDB还是用checkpoint来保证数据的一致性,当数据库发生宕机时,就需要checkpoint和journal文件写作完成数据的恢复工作
流程
1. 在数据文件中查找上一个checkpoint的标识符
2. 在journal文件中查找标识符对应的记录
3. 重做对应记录之后的全部操作
7. 集群高可用
主从复制
原理
主从架构中master节点负责数据的读写,slave只有读权限
主从结构中,master节点的操作记录成为oplog(operation_log)
oplog存储在系统数据库local的oplog.$main集合中,这个集合的每个文档都代表主节点上执行的一个操作
slave节点会定期从master节点中获取oplog记录,然后在本机执行
对于存储oplog的集合,MongoDB采用的是固定集合,即随着操作过多,新的操作会覆盖旧的操作
缺点
没有自动故障转移功能,需要指定master和slave,不推荐在生产中使用
MongoDB4.0后不再支持
复制集
介绍
复制集是由一组拥有相同数据集的mongodb实例组成的集群
它由2台及以上服务器组成,成员包括primary主节点,secondary从节点和投票节点
它提供了数据冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性,保证数据的安全性
使用原因
1. 高可用
防止设备故障
提供自动failover功能
技术来保证高可用
2. 灾难恢复
发生故障时,可以从其他节点恢复
3. 功能隔离
可以在从节点上执行读操作,减少主节点的压力
架构原理
一个复制集中Primary节点上能够完成读写操作,Secondary节点仅能用于读操作
Primary节点需要记录所有改变数据库状态的操作,这些记录保存在oplog中,这个文件存储在local数据库,各个Secondary节点通过此oplog来复制数据并应用于本地,保持本地的数据与主节点的一致
oplog具有幂等性,即无论执行几次其结果一直,这个比mysql_binlog更好用
oplog组成
ts
操作时间,当前timestamp + 计数器,计数器每秒都被重置
h
操作的全局唯一标识
v
oplog版本信息
op
操作类型
i:插入操作
u:更新操作
d:删除操作
c:执行命令,如createDatabase,dropDatabase
n
空操作,特殊用途
ns
操作针对的集合
o
操作内容
o2
更新查询条件,仅update操作包含该字段
数据同步
初始化同步
指全量从主节点同步数据,如果primary节点数据量比较大同步时间会比较长
触发
1. Secondary第一次加入
2. Secondary落后的数据量超过了oplog大小
keep复制同步
指初始化同步过后,节点之间的实时同步,一般是增量同步
节点选举
MongoDB的Primary节点选举基于心跳触发,一个复制集N个节点中任意两个节点维持心跳,每个节点维护其他N-1个节点的状态
选举触发时机
第一次初始化一个复制集
Secondary节点权重比Primary高时,发起替换选举
Secondary节点发现集群中没有Primary时,发起选举
Primary节点不能访问到大部分成员时主动降级
触发选举事
Secondary节点尝试将自身选举为Primary,是一个二阶段过程+多数派协议
第一阶段
检测自身是否有被选举的资格,如果符合就会向其它节点发起本节点是否有选举资格的FreshnessCheck,进行同僚仲裁
第二阶段
发起者向集群中存活节点发送Elect(选举)请求,仲裁者收到请求的节点会执行一系列合法性检查,如果检查通过,则仲裁者给发起者一票
一个复制集中最多50个节点,其中只有7个具有投票权
协议
pv0通过30秒选举锁防止一次选举中两次投票
pv1使用了terms来防止在一次选举中两次投票
多数派协议
发起者如果获得超过半数的投票,则选举通过,自身成为Primary
获得低于半数投票的原因,除了常见的网络问题之外,相同优先级的节点同时通过第一阶段的同僚仲裁并进入第二阶段也是一个原因
当选票不足时,会Sleep[0, 1]秒内的随机时间,之后再次尝试选举
心跳检测
整个集群需要保持一定的通信才能知道哪些节点存活
MongoDB节点会向副本集中其他节点每2秒发送一次pings包,如果其他节点10s内没有返回就标识为不能访问
每个节点内部都会维护一个状态映射表,表明当前每个节点是什么角色、日志时间戳等关键信息
如果主节点发现自己无法与大部分节点通讯则把自己降级为secondary只读节点
搭建
1. 主节点配置
replSet=clusterName
2. 从节点配置
replSet=clusterName
3. 初始化节点配置
启动所有节点
进入任意节点,运行命令
4. 节点动态增删
增加节点
删除节点
注意
默认节点下从节点不能读取数据,调用 rs.slaveOk() 解决
rs.status()
PRIMARY
可以查询和新增数据
SECONDARY
只能查询,不能新增,基于Priority权重可以被选为主节点
ARBITER
不能查询/新增数据,不能成为主节点
rs.reconfig()
重新装载配置,并重新生成集群节点
成员配置参数
_id
整数,复制集中的标识
host
字符串,节点主机名
arbiterOnly
布尔值,是否为仲裁节点
priority
整数,默认1,是否有资格成为主节点
取值 0-1000,0代表不会成为主节点
hidden
布尔值,隐藏,权重为0才可以设置
votes
整数,是否为投票节点
1:是,0:否
slaveDelay
整数,从库的延迟秒数
buildIndexes
布尔值,主库的索引,从库也创建
_id索引无效
分片
介绍
分片是MongoDB用来将大型j集合水平分割到不同服务器(或复制集)上所采用的方法
不需要功能强大的计算机就可以存储更多的数据,处理更大的负载
原因
1.存储容量需求超出单机磁盘容量
2.活跃的数据集超出单机内存容量,导致很多请求都要从磁盘读取数据,影响性能
3.IOPS超出单个MongoDB节点的服务能力,随着数据的增长,单机实例的瓶颈会越来越明显
4.副本集具有节点数量限制
工作原理
集群组成
Shards Server
每个Shard由一个或多个Mongod进程组成,用于存储数据
Router Server
数据库集群的入口,所有请求都通过Router进行协调,不需要在应用程序添加一个路由选择器,Router就是一个请求分发中心,它负责把应用程序的请求转发到对应的Shard服务器上
Config Server
配置服务器,存储所有数据库元信息(路由、分片)的配置
片键
为了在数据集合中分配文档,MongoDB使用分片主键分割集合
区块 Chunk
在一个Shard_Server内部,MongoDB还是会把数据分为chunks,每个chunk代表这个Shard_Server内部一部分数据
MongoDB分割分片数据到区块,每一个区块包含基于分片主键的左闭右开的区间范围
分片策略
范围分片
是基于分片主键的值切分数据,每一个区块将会分配到一个范围
适合满足一定范围内的查找,mongo路由根据Config_Server中存储的元数据,可以直接定位到指定的shard的chunk中
缺点
如果shard_key有明显递增(递减)趋势,则新插入的文档多会分布到同一个chunk,无法扩展写的能力
hash分片
是计算一个分片主键的hash值,每一个区块将分配一个范围的hash值
Hash分片和范围分片互补,能将文档随机的分散到各个chunk,充分的扩展写能力,弥补了范围分片的不足
缺点
不能高效的服务范围查询,所有的范围查询要分发到后端所有的shard才能找出满足条件的文档
组合片键
散列思想,不能是直接hash
数据库中没有比较合适的片键供选择,或者打算使用的片键基数太小,可以选另一个字段使用组合片键,甚至可以添加冗余字段来组合
一般是粗粒度+细粒度进行组合
分片主键选择
从数据的查询/写入来考虑,最好的效果是数据查询时能够命中更少的分片,数据写入时能够随机的写入每个分片,关键在于如何权衡性能和负载
集群搭建
1. config节点集群
配置
configsvr=true
replSet=configsvr
操作
启动配置节点
进入任意节点,配置节点集群,注意 use admin
2. shard集群
配置
replSet=shard
shardsvr=true
操作
搭建各个分片集群,replSet设为不同
启动每个节点,每个集群进入任意一个节点配置
3. router节点
配置
configdb=configscr/host1,host2.....
操作
启动路由节点,使用mongos
./bin/mongos -f router.conf
4. 添加分片节点
操作
进入路由节点mongos
sh.status()
sh.addShard("shard1/host1,host2......")
5. 开启数据库和集合分片
sh.enableSharding(DB_Name)
为数据库开启分片功能
sh.shardCollection(db_name.coll_name, {"分片键“: 索引说明})
为指定集合开启分片功能
6. 测试
安全认证
概述
MongoDB默认没有账号,可以直接连接,无须身份认证
相关操作
1. 切换到admin数据库添加用户
role
MongoDB已经约定好的角色,不同角色对应不同的权限
2. 修改密码
3. 添加角色
4. 以auth方式启动mongod
也可以在配置中添加auth=true
5. 验证用户
6. 删除用户
角色
内置角色
read
允许用户读取指定数据库
readwrite
允许用户读写指定数据库
dbAdmin
允许用户在指定数据库中执行管理函数,如索引创建、删除、查看统计或访问system.profile
userAdmin
允许用户向system.users集合写入,可以在指定数据库里创建、删除、管理用户
clusterAdmin
只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限
readAnyDatabase
只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase
只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase
只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase
只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限
root
只在admin数据库中可用,超级账号
dbOwner
库拥有者,即readWrite、dbAdmin、userAdmin的合体
各类型用户对应角色
数据库用户
read、readWrite
数据库管理
dbAdmin、dbOwner、userAdmin
集群管理
clusterAdmin、clusterManager、clusterMonitor、hostManager
备份恢复
backup、restore
超级用户
root
单机实现
1. 创建管理
MongoDB服务端开启安全检查之前,至少需要一个管理员账号
admin数据库中的用户都被视为管理员
如果admin库没有任何用户,即使在其他数据库中创建了用户并启用身份验证,默认的连接方式依然会有超级权限,即可以不验证照阳进行CRUD,安全认证相当于无效
2. 创建普通用户
3. MongoDB安全认证方式启动
4. 分别以普通用户登录验证
5. 以管理员登录
集群实现
1. 开启安全认证之前,进入路由创建管理员和普通用户
2. 关闭所有配置节点、分片节点和路由节点
安装psmisc
yum install psmisc
安装完之后可以使用killall命令,快速关闭多个进程
3. 生成密钥文件,修改权限
4. 配置节点集群和分片节点集群,开启安全认证和指定密钥文件
auth=true
keyFile=data/keyFile.file
5. 在路由配置文件中,设置密钥文件
keyFile=data/keyFile.file
6. 启动所有的配置节点、分片节点和路由节点,使用路由进行权限验证
2. 知识图谱存储Neo4j
1. 概论
1. 图论
起源
科尼斯堡七桥问题
满足一笔画的图有两个条件
图必须是一个完整图
有零个或二个奇数点
图和节点
图由一组节点和连接这些节点的关系组成。图形数据存储在节点和关系所在的属性上,属性是键值对表示的数据
图论中,可以使用圆表示一个节点,并且可以向里面添加键值对形式的数据
节点关系表达
简单关系
复杂关系
属性图模型规则
图表示节点、关系和属性中的数据
节点和关系都包含属性
关系连接节点
属性是键值对
节点用圆圈标识,关系用方向键表示
关系具有方向:单向和双向
每个关系包含“开始节点/从节点“和“到节点/结束节点”
2. 知识图谱和图库
知识图谱
一种基于图的数据结构,由节点(Node)和边(Edge)组成。节点即实体,由一个全局唯一的ID标识,边就是关系用于连接两个节点
知识图谱即把所有不同种类的信息连接在一起而得到的一个关系网络,它提供了从”关系“的角度去分析问题的能力
图数据库
一般情况下,使用数据库查找事物间的联系时,只需要短程关系的查询(两层一内的关联)
当需要进行更长程的,更广范围的关系查询时,就需要图数据库的功能
图数据库指以图数据结构的形式来存储和查询数据的数据库
知识图谱中,知识的组织形式采用的就是图结构,所以非常适合用图库进行存储
优势
在需要表示多对多关系时,常常需要创建一个关联表来记录不同实体的多对多关系。如果实体之间拥有多种关系,就需要在它们之间创建多个关联表
而在一个图形数据库中,只需要标明两者之间存在着不同的关系。如果希望在两个结点集间建立双向关系,就需要为每个方向定义一个关系
相对于关系型数据库中的各种关联表,图形数据库中的关系可以通过关系属性这一功能来提供更为丰富的关系展现方式
总结
性能上,对长程关系的查询速度快
善于发现隐藏的关系,如通过判断图上两点之间有没有走得通的路径,可以发现事物间的关联
3. Neo4j
简介
Neo4j是一个开源的无Schema的基于Java开发的图形数据库,它将结构化数据存储在图中而不是表中
它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎
程序数据是在一个面向对象的、灵活的网络结构下,而不是严格、静态的表中,但可以享受到具备完全的事务特性、企业级的数据库的所有好处
模块构建
节点
图表的基本单位,包含具有键值对的属性
属性
用于描述图节点和关系的键值对
关系
图形数据库的另一个主要构建块
连接两个节点,每个关系包含一个起始节点和一个结束节点
关系也可以包含属性作为键值对
标签
将一个公共名称与一组节点或关系相关联
节点或关系可以包含一个或多个标签
可以为现有节点或关系创建/删除标签
数据浏览器
应用场景
社交媒体和社交网络
推荐引擎和产品推荐系统
身份和访问管理
金融反欺诈多为关联分析场景
搭建
1. 下载、解压
2. 修改配置文件 neo4j.conf
主要是修改允许远程访问的地址,打开对应的注释即可
3. 开放对应端口 7474/7687
4. 启动
./bin/neo4j start
5. 访问
2. CQL
简介
CQL代表Cypher查询语言,类似关系型数据库的SQL
它是Neo4j图形数据库的查询语言
是一种声明性模式匹配语言
它遵循SQL语法
它的语法是非常简单且人性化、可读的格式
常用命令
CREATE
创建节点,关系,属性
MATCH
检索有关节点,关系和属性数据
RETURN
返回查询结果
WHERE
提供条件过滤检索MATCH数据
DELETE
删除节点和关系
REMOVE
删除节点和关系的属性
SET
添加或更新标签
ORDER BY
对结果排序
SKIP LIMIT
分页
DISTINCT
排重
创建节点
语法
MATCH RETURN
语法
获取系统id:ID(node-name)
关系创建
类型
使用现有节点创建没有属性的关系
使用现有节点创建有属性的关系
使用新节点创建没有属性的关系
使用新节点创建有属性的关系
属性支持类型
boolean
true|false
byte
8位整数
short
16位整数
int
32位整数
long
64位整数
float
32位浮点数
double
64位浮点数
char
16位字符
string
字符串
创建多个标签
语法
WHERE子句
语法
比较符
=、!=、<>、>、<
OR
AND
NOT
DELETE子句
删除节点
删除节点及相关节点和关系
REMOVE子句
删除节点或关系的标签
删除节点或关系的属性
SET子句
向现有节点或关系添加新属性
更新属性值
ORDER BY子句
对match查询返回的结果进行排序
可以按升序或降序进行排序
默认按升序
SKIP和LIMIT
DISTINCT
3. 高级
CQL函数
字符串函数
UPPER()
Lower()
SubString()
Replace()
聚合函数
Count()
Max()
Min()
Sum()
Avg()
关系函数
StartNode()
返回关系的开始节点
EndNode()
返回关系的结束节点
ID()
返回关系的ID
Type()
返回字符串表示中的一个关系的Type
最短路径
ShortestPath()
多深度关系节点
1. 使用With关键字
with可以将前面查询结果作为后面查询条件
2. 直接拼接关系节点
3. 慎用深度运算符
可变数量的关系->节点可以使用 [:Type*minHops..maxHops]
事务
为了保持数据的完整性和保持良浩的事务行为,Neo4j也支持ACID特性
注
所有对Neo4j数据库的数据修改操作都必须封装在事务里
默认的隔离级别是RC
死锁保护已经内置到核心事务管理
Neo4j会在死锁发生之前检测死锁并抛出异常
异常抛出之前,事务会被标志为回滚
事务结束时,事务会释放它所持有的锁,则该事务的锁所引起的死锁也就解除,其他事务可以继续运行
当用户需要时,抛出异常的事务可以尝试重新执行
除特别说明,Neo4j的API操作都是线程安全的,Neo4j数据库的操作没有必要使用外部的同步方法
索引
简介
Neo4j CQL支持节点或关系属性上的索引,以提高应用程序的性能
可以为具有相同标签名称的属性上创建索引
可以在Match或Where运算符上使用这些索引列来改进CQL的执行
单一索引
Create Index On :Person(name)
复合索引
Create Index on :Person(age, gender)
全文模式索引
创建
使用db.index.fulltext.createNodeIndex|createRelationshipIndex,创建全文模式索引
创建索引时,每个索引必须指定一个唯一名称,用于在查询或删除索引时引用相关的特定索引
查询
查看
call db.indexes
:schema
删除
drop index on :Person(name)
call db.index.fulltext.drop("nameAndDescription")
约束
唯一性约束
作用
避免重复记录
强制执行数据完整性规则
创建,删除
属性存在约束
企业版中可用
语法
查看
call db.constraints
:schema
4. 管理
备份/恢复
对Neo4j数据进行备份、还原、迁移操作时,首先要关闭Neo4j
./bin/neo4j stop
数据备份
./bin/neo4j -admin dump --database=graph.db --to=/back/1.dump
还原
./bin/neo4j -admin load --database=graph.db --from=/back/1.dump --force
重启
./bin/neo4j start
优化
1. 增加服务器内存,调整Neo4j配置文件
2. Neo4j刚启动数据是冷的,需要预热
3. 查看执行计划进行索引优化
Cypher查询计划程序将每个查询转换为执行计划,执行计划高速Neo4j在执行查询时要执行哪些操作
对于执行计划的生成,Neo4j使用的是基于成本的优化器(Cost_Based_Optimizer,CBO),用于指定精确的执行过程
工作机制
EXPLAIN
解释机制,加入该关键字的Cypher语句可以预览执行的过程但并不实际执行,所以也不会产生任何结果
PROFILE
画像机制,查询中使用该关键字,不仅能够看到执行计划的详细内容,也可以看到查询的执行结果
关注指标
estimated rows
需要被扫描行数的预估值
dbhits
实际运行结果的命中绩效
5. 程序访问
数据库访问
由应用程序的性质、性能、监控和数据安全性来决定架构选择
方式
嵌入式数据库
性能的最佳选择,通过指定数据库存储的路径以编程方式访问嵌入式数据库
选择原因
使用Java作为项目的编程语言时
应用程序是独立的
程序追求很高的性能
服务器模式(通过Rest访问)
Neo4j_Server是相互操作性,安全性和监控的最佳选择
实际上,REST接口允许所有现代平台和编程语言与它进行互操作
作为独立应用程序,它比嵌入式配置更安全(客户端中的潜在故障不会影响服务器),且更易于监控
选择这种模式,应用程序将充当Neo4j服务器的客户端。可以使用任何编程语言的REST来访问数据库
Java客户端操作
SpringBoot
0 条评论
下一页