数据库
数据库优化
优化层次
1、语句上的优化:
尽量不使用多表查询,不要频繁的使用各种神奇的统计查询(建议使用子查询代替)
2、数据库优化只能体现在查询上
数据不应该进行物理删除,而要进行逻辑删除,为了保证索引不被重新创建
空间换时间,时间换空间
3、如果存在多个 RPC 业务端时,可以考虑进行垂直拆分库,只能按照功能进行拆分,需要接口技术支持
4、分库也无法解决问题的时候,就需要考虑数据库的水平拆分
5、如果需要保证强大的查询性能,那么就需要再次引入搜索引擎进行分词处理
NoSQL 使用场景
NoSQL 可以实现文档存储(BSON,JSON)、缓存存储、图像缓存(图像搜索)
缓存型 Redis
- 用于实现:购物车,短信验证码
- 消息队列: Redis、RabbitMQ、Kafka
- 优点:实现每秒近乎 10W 次的读写处理
分布式数据库
WEB 端 视图层 控制层 业务层 数据层 数据库服务器
WEB 端 视图层 控制层 RPC端 业务层 数据层 数据库服务器
RPC 端将业务分离出来,WEB 端实现业务整合
数据库设计
Spring 事务传播属性(Propagation):
-
REQUIRED(默认属性)如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。
-
MANDATORY 支持当前事务,如果当前没有事务,就抛出异常。
-
NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
-
NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
-
REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
-
SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
-
NESTED 支持当前事务,新增 Savepoint 点,与当前事务同步提交或回滚。
数据库拆分:
- 水平拆分
- 垂直拆分
缓存
- 生成静态文件
- 使用内存作为缓存
- 使用缓存数据库 Redis/Memcached
内存缓存组件:
- oscache 页面上使用 eg: jsp
- ehcache 框架中出现 eg: Hibernate、MyBatis
缓存本质 = 减少物理磁盘读取时间
缓存与数据库同步
缓存的内容 99%情况下和数据都不是同步的
乐观锁和悲观锁
悲观锁:事务提交或回滚之前该数据都不允许更新
select * from 表名 for update
乐观锁:(不推荐使用)多加一个字段列:版本号 version
-- 允许更新 update 表名 set name = "Tom", version = version+1 where id = 1 and version=0 -- 不允许更新 update 表名 set name = "Tom", version = version+1 where id = 1 and version=0
数据缓存
分布式的核心本质:
一台电脑上完成的功能交给多台电脑去做
所有 CPU 可以处理的数据都要先加载到内存中
- 需要缓存的数据:热点操作
- 清理缓存数据的时机:常用算法: LRU、FIFO
- 缓存同步:缓存数据只会采用只读模式
缓存实现:
- 文件缓存: 避免文件内容动态生成
- 内存缓存 OSCache(jsp 页面) EhCache
- 缓存数据库 Memcached Redis
缓存数据丢失
Zookeeper
数据库更新监听
误区:
- 触发器:只能够在数据库层次上存在
- 定时数据监测:会额外增加数据库负荷
解决:在业务层加 AOP 处理将更新消息发布到更新队列
数据库连接池实现原理
对象数组和连接状态
ConcurrentHashMap
数据库事务控制
数据库划分:
关系型数据库
NoSQL 数据库
ACID 原则:
- 原子性(Atomicity,或称不可分割性)
- 一致性(Consistency)
- 隔离性(Isolation,又称独立性)
- 持久性(Durability)
原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括
- 读未提交(Read uncommitted)
- 读提交(read committed)
- 可重复读(repeatable read)
- 串行化(Serializable)
持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
开发中常见的事务处理:
- JDBC 事务处理: commit()/rollback()/setAutoCommit()
- 容器控制事务 使用 jta 组件,一般不用
- Spring 事务控制
事务处理核心思想:
所有操作要么一起成功,要么一起失败
数据源
数据库的数据源设置 DataSource,主要目的是为了解决数据库的频繁打开与关闭带来的性能损耗
数据源:不进行重复打开与关闭,以及控制连接人数
数据源配置主要的两种模式
- 容器配置 Tomcat WebLogic WAS
- 程序配置 (优先)Spring 中使用 C3p0
随机取得数据库数据
算法:
- count()取得数据量个数
- Random.nextInt()
- id 不存在再生成一个