>

关系型数据库

非关系型数据库

  • 底层和上层数据库组件概况
  • 查询优化过程概况
  • 事务和缓冲池管理概况

数据模型

数据模型主要用来描述数据!上边已经说了,当我们想在计算机上存储现实事物的数据时,需要先抽象成概念模型。将概念模型转换成DBMS支持的数据模型,就可以把事物存储到计算机中!

数据模型一般由三个部分组成:

  • 数据结构(对象与对象之间的关系)
  • 数据操作(增删改查)
  • 完整性约束(限定数据是有一定规则的,比如:年龄不能为负数)

数据模型也经历了一个发展阶段:

①:层次模型,是一种树型(层次)结构来组织数据的数据模型。
②:网状模型, 是用有向图结构来组织数据的数据模型
③:关系模型,是一种用二维表格结构表示数据及数据之间联系的数据模型。

高级术语
1、存储引擎 、事务、复合索引、连接池、备份、恢复
2、主从复制、行锁定、表锁定、慢查询、二进制日志、临时表、内容分发、同步、数据库分区、分库、分表、水平拆分、垂直拆分

数据库系统概念 事务
事务:原子性、一致性、隔离性、持久性:ACID特性
原子性与持久性的实现
影子副本,在副本中更新事务,db__pointer指向更新过的副本即可实现事务原子性提交
并发执行
并发:提高吞吐量和资源利用率,减少等待时间
冲突存在等价串行化执行顺序,则冲突可串行化
调度视图等价于一个串行调度,即视图可串行化
冲突串行化顺序可由拓扑排序获得
并发控制
基于锁协议
共享锁:事务获得数据项上共享锁后可读不可写
排它锁:事务获得数据项上排它锁后可读又可写
事务T申请对数据项Q加M型锁时,并发控制管理器授权加锁的条件
不存在数据项Q上持有与M型锁冲突的锁的事务
不存在等待对数据项Q加锁且先于T申请加锁的事务
两阶段封锁协议
增长阶段:只能加锁不能释放锁
缩减阶段:只能解锁不能加锁
最后加锁位置:即封锁点,根据封锁点排序(串行化顺序)避免发生死锁
严格两阶段封锁:任一事务失败,级联回滚
强两阶段封锁:事务提交之前不能释放任何锁

数据存储

MySQL 索引使用的注意事项参考:

mysql 索引使用技巧及注意事项

说说反模式设计参考:

每个程序员要注意的 9 种反模式

说说分库与分表设计

分表与分库使用场景以及设计方式

分库与分表带来的分布式困境与应对之策

服务端指南 数据存储篇 | MySQL(09) 分库与分表带来的分布式困境与应对之策

说说 SQL 优化之道

sql 优化的几种方法

MySQL 遇到的死锁问题
参考: Mysql 并发时经典常见的死锁原因及解决方法

存储引擎的 InnoDB 与 MyISAM
InnoDB 支持事务,MyISAM 不支持,这一点是非常之重要。事务是一种高级的处理方式,如在一些列增删改中只要哪个出错还可以回滚还原,而 MyISAM 就不可以了。
MyISAM 适合查询以及插入为主的应用,InnoDB 适合频繁修改以及涉及到安全性较高的应用
InnoDB 支持外键,MyISAM 不支持
从 MySQL5.5.5 以后,InnoDB 是默认引擎
InnoDB 不支持 FULLTEXT 类型的索引
InnoDB 中不保存表的行数,如 select count() from table时,InnoDB需要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count()语句包含 where 条件时 MyISAM 也需要扫描整个表
对于自增长的字段,InnoDB 中必须包含只有该字段的索引,但是在 MyISAM 表中可以和其他字段一起建立联合索引
清空整个表时,InnoDB 是一行一行的删除,效率非常慢。MyISAM 则会重建表
InnoDB 支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like ‘%lee%’ 参考:
MySQL 存储引擎之 MyIsam 和 Innodb 总结性梳理

数据库索引的原理
参考: http://blog.csdn.net/suifeng3051/article/details/52669644

为什么要用 B-tree

鉴于 B-tree 具有良好的定位特性,其常被用于对检索时间要求苛刻的场合,

例如:

1、B-tree 索引是数据库中存取和查找文件(称为记录或键值)的一种方法。

2、硬盘中的结点也是 B-tree 结构的。与内存相比,硬盘必须花成倍的时间来存取一个数据元素,这是因为硬盘的机械部件读写数据的速度远远赶不上纯电子媒体的内存。与一个结点两个分支的二元树相比,B-tree 利用多个分支(称为子树)的结点,减少获取记录时所经历的结点数,从而达到节省存取时间的目的。

聚集索引与非聚集索引的区别

参考:快速理解聚集索引和非聚集索引

limit 20000 加载很慢怎么解决

LIMIT n 等价于 LIMIT 0,n

此题总结一下就是让 limit 走索引去查询,例如:order by 索引字段,或者 limit 前面根 where 条件走索引字段等等。

参考: MYSQL 分页 limit 速度太慢优化方法

选择合适的分布式主键方案

参考:分布式系统唯一 ID 生成方案汇总

选择合适的数据存储方案
关系型数据库 MySQL
MySQL 是一个最流行的关系型数据库,在互联网产品中应用比较广泛。一般情况下,MySQL 数据库是选择的第一方案,基本上有 80% ~ 90% 的场景都是基于 MySQL 数据库的。因为,需要关系型数据库进行管理,此外,业务存在许多事务性的操作,需要保证事务的强一致性。同时,可能还存在一些复杂的 SQL 的查询。值得注意的是,前期尽量减少表的联合查询,便于后期数据量增大的情况下,做数据库的分库分表。

内存数据库 Redis
随着数据量的增长,MySQL 已经满足不了大型互联网类应用的需求。因此,Redis 基于内存存储数据,可以极大的提高查询性能,对产品在架构上很好的补充。例如,为了提高服务端接口的访问速度,尽可能将读频率高的热点数据存放在 Redis 中。这个是非常典型的以空间换时间的策略,使用更多的内存换取 CPU 资源,通过增加系统的内存消耗,来加快程序的运行速度。

在某些场景下,可以充分的利用 Redis 的特性,大大提高效率。这些场景包括缓存,会话缓存,时效性,访问频率,计数器,社交列表,记录用户判定信息,交集、并集和差集,热门列表与排行榜,最新动态等。

使用 Redis 做缓存的时候,需要考虑数据不一致与脏读、缓存更新机制、缓存可用性、缓存服务降级、缓存穿透、缓存预热等缓存使用问题。

文档数据库 MongoDB
MongoDB 是对传统关系型数据库的补充,它非常适合高伸缩性的场景,它是可扩展性的表结构。基于这点,可以将预期范围内,表结构可能会不断扩展的 MySQL 表结构,通过 MongoDB 来存储,这就可以保证表结构的扩展性。

此外,日志系统数据量特别大,如果用 MongoDB 数据库存储这些数据,利用分片集群支持海量数据,同时使用聚集分析和 MapReduce 的能力,是个很好的选择。

MongoDB 还适合存储大尺寸的数据,GridFS 存储方案就是基于 MongoDB 的分布式文件存储系统。

列族数据库 HBase
HBase 适合海量数据的存储与高性能实时查询,它是运行于 HDFS 文件系统之上,并且作为 MapReduce 分布式处理的目标数据库,以支撑离线分析型应用。在数据仓库、数据集市、商业智能等领域发挥了越来越多的作用,在数以千计的企业中支撑着大量的大数据分析场景的应用。

全文搜索引擎 ElasticSearch
在一般情况下,关系型数据库的模糊查询,都是通过 like 的方式进行查询。其中, like “value%” 可以使用索引,但是对于 like “%value%” 这样的方式,执行全表查询,这在数据量小的表,不存在性能问题,但是对于海量数据,全表扫描是非常可怕的事情。ElasticSearch 作为一个建立在全文搜索引擎 Apache Lucene 基础上的实时的分布式搜索和分析引擎,适用于处理实时搜索应用场景。此外,使用 ElasticSearch 全文搜索引擎,还可以支持多词条查询、匹配度与权重、自动联想、拼写纠错等高级功能。因此,可以使用 ElasticSearch 作为关系型数据库全文搜索的功能补充,将要进行全文搜索的数据缓存一份到 ElasticSearch 上,达到处理复杂的业务与提高查询速度的目的。

ElasticSearch 不仅仅适用于搜索场景,还非常适合日志处理与分析的场景。著名的 ELK 日志处理方案,由 ElasticSearch、Logstash 和 Kibana 三个组件组成,包括了日志收集、聚合、多维度查询、可视化显示等。

ObjectId 规则参考:

MongoDB 学习笔记~ObjectId 主键的设计

mongodb 中的_id 的 ObjectId 的生成规则

聊聊 MongoDB 使用场景参考: 什么场景应该用 MongoDB ?

倒排索引

参考: 什么是倒排索引?

聊聊 ElasticSearch 使用场景
在一般情况下,关系型数据库的模糊查询,都是通过 like 的方式进行查询。其中, like “value%” 可以使用索引,但是对于 like “%value%” 这样的方式,执行全表查询,这在数据量小的表,不存在性能问题,但是对于海量数据,全表扫描是非常可怕的事情。ElasticSearch 作为一个建立在全文搜索引擎 Apache Lucene 基础上的实时的分布式搜索和分析引擎,适用于处理实时搜索应用场景。此外,使用 ElasticSearch 全文搜索引擎,还可以支持多词条查询、匹配度与权重、自动联想、拼写纠错等高级功能。因此,可以使用 ElasticSearch 作为关系型数据库全文搜索的功能补充,将要进行全文搜索的数据缓存一份到 ElasticSearch 上,达到处理复杂的业务与提高查询速度的目的。

缓存使用

Redis 有哪些类型
Redis 支持五种数据类型:

string(字符串),hash(哈希),list(列表),set(集合)及 zset(sorted set:有序集合)。

参考: Redis 数据类型

Redis 内部结构参考:

redis 内部数据结构深入浅出

聊聊 Redis 使用场景随着数据量的增长,MySQL 已经满足不了大型互联网类应用的需求。因此,Redis 基于内存存储数据,可以极大的提高查询性能,对产品在架构上很好的补充。例如,为了提高服务端接口的访问速度,尽可能将读频率高的热点数据存放在 Redis 中。这个是非常典型的以空间换时间的策略,使用更多的内存换取 CPU 资源,通过增加系统的内存消耗,来加快程序的运行速度。

在某些场景下,可以充分的利用 Redis 的特性,大大提高效率。这些场景包括缓存,会话缓存,时效性,访问频率,计数器,社交列表,记录用户判定信息,交集、并集和差集,热门列表与排行榜,最新动态等。

使用 Redis 做缓存的时候,需要考虑数据不一致与脏读、缓存更新机制、缓存可用性、缓存服务降级、缓存穿透、缓存预热等缓存使用问题。

Redis 持久化机制参考: redis 的持久化和缓存机制

Redis 如何实现持久化参考: Redis 如何实现持久化

Redis 集群方案与实现参考: redis 集群主流架构方案分析

Redis 为什么是单线程的

单纯的网络 IO 来说,量大到一定程度之后,多线程的确有优势——但并不是单纯的多线程,而是每个线程自己有自己的 epoll 这样的模型,也就是多线程和 multiplexing 混合。 一般这个开头我们都会跟一个“但是”。

但是。 还要考虑 Redis 操作的对象。它操作的对象是内存中的数据结构。如果在多线程中操作,那就需要为这些对象加锁。最终来说,多线程性能有提高,但是每个线程的效率严重下降了。而且程序的逻辑严重复杂化。

要知道 Redis 的数据结构并不全是简单的 Key-Value,还有列表,hash,map 等等复杂的结构,这些结构有可能会进行很细粒度的操作,比如在很长的列表后面添加一个元素,在 hash 当中添加或者删除一个对象,等等。这些操作还可以合成MULTI/EXEC 的组。这样一个操作中可能就需要加非常多的锁,导致的结果是同步开销大大增加。这还带来一个恶果就是吞吐量虽然增大,但是响应延迟可能会增加。

Redis 在权衡之后的选择是用单线程,突出自己功能的灵活性。在单线程基础上任何原子操作都可以几乎无代价地实现,多么复杂的数据结构都可以轻松运用,甚至可以使用 Lua 脚本这样的功能。对于多线程来说这需要高得多的代价。

并不是所有的 KV 数据库或者内存数据库都应该用单线程,比如 ZooKeeper 就是多线程的,最终还是看作者自己的意愿和取舍。单线程的威力实际上非常强大,每核心效率也非常高,在今天的虚拟化环境当中可以充分利用云化环境来提高资源利用率。多线程自然是可以比单线程有更高的性能上限,但是在今天的计算环境中,即使是单机多线程的上限也往往不能满足需要了,需要进一步摸索的是多服务器集群化的方案,这些方案中多线程的技术照样是用不上的,所以单线程、多进程的集群不失为一个时髦的解决方案。

缓存奔溃
参考: Redis 持久化

缓存降级

服务降级的目的,是为了防止 Redis 服务故障,导致数据库跟着一起发生雪崩问题。因此,对于不重要的缓存数据,可以采取服务降级策略,例如一个比较常见的做法就是,Redis 出现问题,不去数据库查询,而是直接返回默认值给用户。

使用缓存的合理性问题参考: Redis 实战(一) 使用缓存合理性

消息队列

消息队列的使用场景主要解决应用耦合,异步消息,流量削锋等问题

消息队列使用的四种场景介绍

消息的重发补偿解决思路

参考: JMS 消息传送机制

消息的幂等性解决思路

参考: MQ 之如何做到消息幂等

消息的堆积解决思路

参考: Sun Java System Message Queue 3.7 UR1 管理指南

自己如何实现消息队列

参考:自己动手实现消息队列之 JMS

如何保证消息的有序

参考: 消息队列的 exclusive consumer 功能是如何保证消息有序和防止脑裂的

原文:https://blog.csdn.net/ganquanzhong/article/details/86185185