数据库图谱
2021-06-16 17:16:52 2 举报
AI智能生成
数据库专题整理,由于时间关系,文档尚未完整,持续更新中...
作者其他创作
大纲/内容
数据库
数据库分类
非关系型数据库
分类
key-value数据库
Redis
数据结构
string(字符串)
string 是 redis 最基本的数据类型。一个 key 对应一个 value。
string 是二进制安全的。也就是说 redis 的 string 可以包含任何数据。比如 jpg 图片或者序列化的对象。
string 类型是 redis 最基本的数据类型,string 类型的值最大能存储 512 MB。
hash(哈希)
hash 是一个键值对(key - value)集合。
hash 是一个 string 类型的 key 和 value 的映射表,hash 特别适合用于存储对象。
与 string 区别:string 是 一个 key - value 键值对,而 hash 是多个 key - value 键值对。
list(列表)
list 就是一个简单的字符串集合,和 Java 中的 list 相差不大,区别就是这里的 list 存放的是字符串。list 内的元素是可重复的。
set(集合)
set 是字符串类型的无序集合。集合是通过哈希表实现的,因此添加、删除、查找的复杂度都是 O(1)
set 与 java 中的 set 还是有点区别的。
set 是一个 key 对应着 多个字符串类型的 value,也是一个字符串类型的集合
set 中的字符串集合元素不能重复,但是 list 可以。
zset(sorted set:有序集合)
zset 和 set 一样都是 字符串类型元素的集合,并且集合内的元素不能重复。
zset 每个元素都会关联一个 double 类型的分数。redis 通过分数来为集合中的成员进行从小到大的排序。
zset 的元素是唯一的,但是分数(score)却可以重复。
zset 是按照分数的大小来排序的。
跳跃表
结构图
性质
由很多层结构组成
每一层都是一个有序的链表
最底层(Level 1)的链表包含所有元素
如果一个元素出现在 Level i 的链表中,则它在 Level i 之下的链表也都会出现。
每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。
跳跃表高度
n 个元素的跳表,每个元素插入的时候都要做一次实验,用来决定元素占据的层数 K,跳表的高度等于这 n 次实验中产生的最大 K,待续。。。
跳跃表的空间复杂度分析
每个元素的期望高度为 2, 一个大小为 n 的跳表,其节点数目的期望值是 2n。
跳跃表删除
在各个层中找到包含 x 的节点,使用标准的 delete from list 方法删除该节点。
优势
性能极高
丰富的数据类型
原子性
Redis 的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过 MULTI 和 EXEC 指令包起来。
其他特性
Redis 还支持 publish/subscribe 通知,key 过期等特性。
事务
事务执行阶段
开始事务
命令入队
执行事务
命令
DISCARD
取消事务,放弃执行事务块内的所有命令。
EXEC
执行所有事务块内的命令。
MULTI
标记一个事务块的开始。
UNWATCH
取消 WATCH 命令对所有 key 的监视。
WATCH key [key …]
监视一个 (或多个) key ,如果在事务执行之前这个 (或这些) key 被其他命令所改动,那么事务将被打断。
持久化
RDB 持久化
将某个时间点的所有数据都存放到硬盘上。
可以将快照复制到其他服务器从而创建具有相同数据的服务器副本。
如果系统发生故障,将会丢失最后一次创建快照之后的数据。
如果数据量大,保存快照的时间会很长。
AOF 持久化
将写命令添加到 AOF 文件(append only file)末尾。
使用 AOF 持久化需要设置同步选项,从而确保写命令同步到磁盘文件上的时机。
这是因为对文件进行写入并不会马上将内容同步到磁盘上,而是先存储到缓冲区,然后由操作系统决定什么时候同步到磁盘。
选项同步频率always每个写命令都同步eyerysec每秒同步一次no让操作系统来决定何时同步
always 选项会严重减低服务器的性能
everysec 选项比较合适,可以保证系统崩溃时只会丢失一秒左右的数据,并且 Redis 每秒执行一次同步对服务器几乎没有任何影响。
no 选项并不能给服务器性能带来多大的提升,而且会增加系统崩溃时数据丢失的数量。
随着服务器写请求的增多,AOF 文件会越来越大。Redis 提供了一种将 AOF 重写的特性,能够去除 AOF 文件中的冗余写命令。
主从复制
原理
通过使用 slaveof host port 命令来让一个服务器成为另一个服务器的从服务器。一个从服务器只能有一个主服务器,并且不支持主主复制。
连接过程
1、主服务器创建快照文件,即 RDB 文件,发送给从服务器,并在发送期间使用缓冲区记录执行的写命令。
2、快照文件发送完毕之后,开始像从服务器发送存储在缓冲区的写命令。
3、从服务器丢弃所有旧数据,载入主服务器发来的快照文件,之后从服务器开始接受主服务器发来的写命令。
4、主服务器每执行一次写命令,就向从服务器发送相同的写命令。
主从链
随着负载不断上升,主服务器无法很快的更新所有从服务器,或者重新连接和重新同步从服务器将导致系统超载。 为了解决这个问题,可以创建一个中间层来分担主服务器的复制工作。中间层的服务器是最上层服务器的从服务器,又是最下层服务器的主服务器。
哨兵
Sentinel的作用
Master 状态监测
如果Master 异常,则会进行Master-slave 转换,将其中一个Slave作为Master,将之前的Master作为Slave
Master-Slave切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换
Sentinel的工作方式
每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令
如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。
如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。
当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线
在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令
当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次
若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。
若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。
主从同步
工作原理
Redis的主从结构可以采用一主多从或者级联结构,Redis主从复制可以根据是否是全量分为全量同步和增量同步。
全量同步
Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。
步骤:
从服务器连接主服务器,发送SYNC命令;
主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令
增量同步
Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。 增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。
主从同步策略
主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。
注意点
如果多个Slave断线了,需要重启的时候,因为只要Slave启动,就会发送sync请求和主机全量同步,当多个同时出现的时候,可能会导致Master IO剧增宕机。
分片
最简单的是范围分片,例如用户 id 从 0 ~ 1000 的存储到实例 R0 中,用户 id 从 1001 ~ 2000 的存储到实例 R1中,等等。但是这样需要维护一张映射范围表,维护操作代价高。
哈希分片
使用 CRC32 哈希函数将键转换为一个数字,再对实例数量求模就能知道存储的实例。
客户端分片
客户端使用一致性哈希等算法决定应当分布到哪个节点。
代理分片
将客户端的请求发送到代理上,由代理转发到正确的节点上。
服务器分片
Redis Cluster。
pipline技术
为什么会出现Pipeline
Redis本身是基于Request/Response协议的,正常情况下,客户端发送一个命令,等待Redis应答,Redis在接收到命令,处理后应答。在这种情况下,如果同时需要执行大量的命令,那就是等待上一条命令应答后再执行,这中间不仅仅多了RTT(Round Time Trip),而且还频繁的调用系统IO,发送网络请求。如下图。为了提升效率,这时候Pipeline出现了,它允许客户端可以一次发送多条命令,而不等待上一条命令执行的结果,这和网络的Nagel算法有点像(TCP_NODELAY选项)。不仅减少了RTT,同时也减少了IO调用次数(IO调用涉及到用户态到内核态之间的切换)。
实现原理
要支持Pipeline,其实既要服务端的支持,也要客户端支持。对于服务端来说,所需要的是能够处理一个客户端通过同一个TCP连接发来的多个命令,可以理解为,这里将多个命令切分,和处理单个命令一样(之前老生常谈的黏包现象),Redis就是这样处理的。而客户端,则是要将多个命令缓存起来,缓冲区满了就发送,然后再写缓冲,最后才处理Redis的应答,如Jedis。
性能提升
Pipeline减少了RTT,也减少了IO调用次数(IO调用涉及到用户态到内核态之间的切换)
Redis的Pipeline和Transaction不同,Transaction会存储客户端的命令,最后一次性执行,而Pipeline则是处理一条,响应一条,但是这里却有一点,就是客户端会并不会调用read去读取socket里面的缓冲数据,这也就造就了,如果Redis应答的数据填满了该接收缓冲(SO_RECVBUF),那么客户端会通过ACK,WIN=0(接收窗口)来控制服务端不能再发送数据,那样子,数据就会缓冲在Redis的客户端应答列表里面。所以需要注意控制Pipeline的大小。
Amazon DynamoDB
Memcached
Microsoft Azure Cosmos DB
Hazelcast
文档数据库
MongoDB
Couchbase
CouchDB
搜索引擎数据库
Elasticsearch
Splunk
Solr
MarkLogic
Sphinx
分布式数据库
Cassandra
HBase
Datastax Enterprise
Accumulo
图形数据库
Neo4j
核心概念
Nodes(节点)
1.节点包含多个标签和属性,就像是一个地铁站。
2.一个节点就是一条数据。
Relations(关系)
1.关系是用来连接两个节点的,也可以包含多个标签和属性,就像是地铁站之间的线路。
2.一个关系也是一条数据。
3.关系包括进和出两种方向。
Properties(属性)
类似于关系型数据库里面的字段,不用事先定义,可以动态添加。
Labels(标签)
表示节点或者关系的类型,可以有多个,使查询更加方便和高效。
使用场景
1.社交网络
2.基于图的搜索
3.推荐引擎
4.企业基础设施及网络架构
1.在创建节点的时候就已经把关系给建立起来,避免了在复杂查询场景下的处理
插入慢,为了提供较快的查询速度在创建节点和边的时候需要保存一些额外的信息。
2.由于底层直接以图的形式存储节点和关系,在查询的时候可以使时间复杂度保持在常数级别。
3.基于JVM实现
4.提供一套易于理解的查询语言Cypher以及内置的可视化UI
5.很好的支持ACID,有事务机制
6.数据的插入,查询操作很直观,不用再像之前要考虑各个表之间的关系。
7.图搜索和图遍历方法便于操作,速度较快。
缺点
超大节点问题。当一个节点的边非常多的时候,对于这个节点的操作将变得非常慢(之前官方的说法是会修复,但是目前的状态,并未尽如人意。)
常规的提升数据库速度方法是多分配内存,但是根据Neo4j的官方文档,其并不能直接设置数据库的内存占用量,需要计算后为其预留内存。
设计架构
对外接口及部署形式
Arangodb
特性
多数据模型
方便的查询
支持类似 SQL 的查询语法 AQL,或者通过 REST 以及其他查询
Ruby 和 JS 扩展
没有语言范围限制,你可以从前台到后台都使用同一种语言
高性能以及低空间占用
ArangoDB 比其他 NoSQL 都要快,同时占用的空间更小
简单易用
可以在几秒内启动并且使用,同时可以通过图形界面来管理你的 ArangoDB
开源且免费
ArangoDB 遵守 Apache 协议
多os支持
ArangoDB支持Windows、Linux和OSX等操作系统,还支持树莓派。
复制
ArangoDB支持主从集群
空间利用率高
跟其它文档型数据库相比,ArangoDB占用的存储空间更少,因为ArangoDB是模式自由的元数据模式。
Foxx - 构建自己的API
用JavaScript和ArangoDB构建应用,Foxx运行在DB内部,可快速访问数据。
适用场景
内容管理
电子商务系统
企业组织架构管理
欺诈检测
身份与权限管理
物联网
知识图谱
物流系统
基础设施运维和管理
实时推荐引擎
社交网络
交通管理系统
版本管理系统
工作流管理系统
数据库模型
Document 文档
可以在文档中存储海量数据(文件大小默认最大值为32MB,但可以根据实际需要进行配置)。ArangoDB功能强大,应用范围广泛,可用于查询和处理诸如JOINs、辅助索引或ACID事物之类的文档。您还可以在JOIN连接上实现水平扩展。
key/value 键/值
每个document文档里均有唯一的键和与其对应的值(键/值对)。如果您在document文件中存储一个值,那么ArangoDB可用作经典的、高度可扩展的键/值对存储,例如用户在电子商务平台上将商品临时存储在购物车里或物联网应用程序中的传感数据等。
Graph 图
ArangoDB包含了graph图形存储的完整功能集。例如模式匹配、最短路径、完全遍历等。与当前许多主流的图形处理方法相比,ArangoDB可以快速执行图形查询。
数据库模型图谱
较Neo4j
1.ArangoDB数据库这些边和顶点都包含复杂数据(嵌套属性)
2.ArangoDB数据库所有的graph函数均被深入集成至我们的查询语言AQL中。
ArangoDB还支持对graph图搭建数据库集群。
优点
查询方便
可以根据需要去添加自己需要的字段,为了获取用户的不同信息,不像关系型数据库中,要对多表进行关联查询。仅需要根据id取出相应的value就可以完成查询。
适应性强
适用于SNS(Social Networking Services)中,例如facebook,微博。系统的升级,功能的增加,往往意味着数据结构巨大变动,这一点关系型数据库难以应付,需要新的结构化数据存储。由于不可能用一种数据结构化存储应付所有的新的需求,因此,非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合。
只适合存储一些较为简单的数据,对于需要进行较复杂查询的数据,关系型数据库显的更为合适。不适合持久存储海量数据
关系型数据库
Oracle
Microsoft SQL Server
MySQL
PostgreSQL
DB2
Microsoft Access
SQLite
Teradata
MariaDB(MySQL的一个分支)
SAP
容易理解
二维表结构是非常贴近逻辑世界的一个概念,关系模型相对网状、层次等其他模型来说更容易理解
方便使用
通用的SQL语言使得操作关系型数据库
方便维护
丰富的完整性(实体完整性、参照完整性和用户定义的完整性)大大减低了数据冗余和数据不一致的概率
io瓶颈
网站的用户并发性非常高,往往达到每秒上万次读写请求,对于传统关系型数据库来说,硬盘I/O是一个很大的瓶颈
效率问题
网站每天产生的数据量是巨大的,对于关系型数据库来说,在一张包含海量数据的表中查询,效率是非常低的
负载和迁移开销
在基于web的结构当中,数据库是最难进行横向扩展的,当一个应用系统的用户量和访问量与日俱增的时候,数据库却没有办法像web server和app server那样简单的通过添加更多的硬件和服务节点来扩展性能和负载能力。当需要对数据库系统进行升级和扩展时,往往需要停机维护和数据迁移。
性能问题
在关系型数据库中,导致性能欠佳的最主要原因是多表的关联查询,以及复杂的数据分析类型的复杂SQL报表查询。为了保证数据库的ACID特性,必须尽量按照其要求的范式进行设计,关系型数据库中的表都是存储一个格式化的数据结构。
数据库分类对比
成本对比
Nosql数据库简单易部署,基本都是开源软件,不需要像使用Oracle那样花费大量成本购买使用,相比关系型数据库价格便宜。
查询速度对比
Nosql数据库将数据存储于缓存之中,而且不需要经过SQL层的解析,关系型数据库将数据存储在硬盘中,自然查询速度远不及Nosql数据库。
存储数据的格式对比
扩展性对比
关系型数据库有类似join这样的多表查询机制的限制导致扩展很艰难。Nosql基于键值对,数据之间没有耦合性,所以非常容易水平扩展。
持久存储对比
Nosql不使用于持久存储,海量数据的持久存储,还是需要关系型数据库6.数据一致性:非关系型数据库一般强调的是数据最终一致性,不像关系型数据库一样强调数据的强一致性,从非关系型数据库中读到的有可能还是处于一个中间态的数据,Nosql不提供对事务的处理。
数据库范式
第一范式
确保每列保持原子性
第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。
第二范式
确保表中的每列都和主键相关
第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
第三范式
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
数据库特性
原子性(Atomicity)
事务包含的所有操作要么全部成功,要么全部失败回滚。失败回滚的操作事务,将不能对事物有任何影响。
一致性(Consistency)
事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
隔离性(Isolation)
多个用户并发访问数据库时,比如同时访问一张表,数据库每一个用户开启的事务,不能被其他事务所做的操作干扰,多个并发事务之间,应当相互隔离。
持久性(Durability)
事务的操作,一旦提交,对于数据库中数据的改变是永久性的,即使数据库发生故障也不能丢失已提交事务所完成的改变。
数据库事务隔离级别
可重复读 REPEATABLE READ
默认的隔离级别。该级别解决了READ UNCOMMITTED隔离级别导致的问题。会导致幻读。(InnoDB和Falcon存储引擎通过多版本并发控制机制解决了幻读问题。)
读已提交 READ COMMITTED
大多数数据库系统的默认隔离级别(但是不是MySQL的默认隔离级别),满足了隔离的早先简单定义:一个事务开始时,只能“看见”已经提交事务所做的改变,一个事务从开始到提交前,所做的任何数据改变都是不可见的,除非已经提交。这种隔离级别也支持所谓的“不可重复读”。这意味着用户运行同一个语句两次,看到的结果是不同的。
读未提交 READ UNCOMMITTED
在这个隔离级别,所有事务都可以“看到”未提交事务的执行结果。在这种级别上,可能会产生很多问题,除非用户真的知道自己在做什么,并有很好的理由选择这样做。本隔离级别很少用于实际应用,因为它的性能也不必其他性能好多少,而别的级别还有其他更多的优点。读取未提交数据,也被称为“脏读”
串行读 SERIALIZABLE
最高隔离级别。它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简而言之,SERIALIZABLE是在每个读的数据行上加锁。在这个级别,可能导致大量的超时Timeout和锁竞争Lock Contention现象,实际应用中很少使用到这个级别,但如果用户的应用为了数据的稳定性,需要强制减少并发的话,也可以选择这种隔离级别。
数据库锁
锁机制划分
共享锁
由读表操作加上的锁,加锁后其他用户只能获取该表或行的共享锁,不能获取排它锁,也就是说只能读不能写
排它锁
由写表操作加上的锁,加锁后其他用户不能获取该表或行的任何锁,典型是mysql事务
锁范围划分
表锁(整表加锁)
表级共享锁
表级排它锁
行锁(整行加锁)
行级共享锁
行级排它锁
0 条评论
回复 删除
下一页