数据库
数据库
█ 1.数据库事务四大特性
什么是事务
事务由一组DML语句组成。
事务的特点:要么都成功,要么都失败
Redis中的事务的本质:将一组操作放在队列中,一次性执行
redis不是真正的事务,是一种事务的模拟。

1)原子性,要么执行,要么不执行
2)隔离性,所有操作全部执行完以前其它会话不能看到过程
3)一致性,事务前后,数据总额一致
4)持久性,一旦事务提交,对数据的改变就是永久的
█ 2.数据库隔离级别
由低到高分别为Read uncommitted 、Read committed<默认> 、Repeatable read 、Serializable<效率差> 。
█ 3.脏读 不可查重复读 幻读
1)脏读:指一个事务中访问到了另外一个事务未提交的数据
2)不可重复读:一个事务查询同一条记录2次,得到的结果不一致。
3)幻读:一个事务查询2次,得到的记录条数不一致。
█ 4.解决脏读
(1)什么是幻读
在一次事务里面,多次查询之后,结果集的个数不一致的情况叫做幻读。而多出来或者少的哪一行被叫做 幻行
表现:一个事务(同一个read view)在前后两次查询同一范围的时候,后一次查询看到了前一次查询没有看到的行。两点需要说明:
1、在可重复读隔离级别下,普通查询是快照读,是不会看到别的事务插入的数据的,幻读只在当前读下才会出现。
2、幻读专指新插入的行,读到原本存在行的更新结果不算。因为当前读的作用就是能读到所有已经提交记录的最新值。
(2)幻读产生的原因
行锁只能锁住行,即使把所有的行记录都上锁,也阻止不了新插入的记录。
(3)如何解决幻读?
将两行记录间的空隙加上锁,阻止新记录的插入;这个锁称为间隙锁。
间隙锁与间隙锁之间没有冲突关系。跟间隙锁存在冲突关系的,是往这个间隙中插入一个记录这个操作。
█ 5.数据库三范式
| 级别 | 概念 |
|---|---|
| 1NF | 属性不可分 列 原子性 |
| 2NF | 非主键属性,完全依赖于主键属性 满足第一范式 |
| 3NF | 非主键属性无传递依赖 |
█ 6.数据库锁
| 锁 | 概念 |
|---|---|
| 乐观锁 | 自己实现的锁,认为数据一般不会冲突,实现方式:版本号+时间戳 |
| 悲观锁 | 改数据就上锁 独占 排他特性 |
| b共享锁 S锁 | 只读数据操作, 非独占 加 HOLDLOCK |
| b排它锁 X锁 | 一个事务,只能写,加了这个锁,其他事务不能再加任何锁for update |
| b行锁 | 作用于数据行 |
| b表锁 | 作于用表 |
█ 7.关系型数据库和非关系型数据库区别
关系型数据库 MySQL SQLserver Oracle
优点
1、容易理解:二维表结构;
2、使用方便:通用的SQL语言使得操作关系型数据库非常方便;
3、易于维护:丰富的完整性,减低了数据冗余和数据不一致的概率;
4、支持SQL,可用于复杂的查询。
5、支持事务
缺点
1、读写性能比较差,维护一致性困难;
2、固定的表结构,灵便度不好;
3、高并发读写时,硬盘I/O存在瓶颈;不支持海量数据的高效率读写;
4、可扩展性不足
非关系型数据库 MongoDB HBase Elasticsearch
1、使用键值对存储数据;
2、分布式;
优点
1)格式灵活:数据存储格式非常多样,应用领域广泛,而关系型数据库则只适用基础的关系模型。
2)性能优越:NOSQL是根据键值对的,不用历经SQL层的分析,因此 性能非常高。
3)可扩展性:基于键值对,数据之间耦合度极低,因此容易水平扩展。
4)低成本:非关系型数据库部署简易,且大部分可以开源使用。
缺点
1)不支持sql,学习和运用成本比较高;
2)无事务处理机制;
3)数据结构导致复杂查询不容易实现。
7.1 关系型与非关系型数据库的区别:
1)成本:Nosql数据库易部署;
2)查询速率:Nosql数据库将数据储存于缓存当中,不用历经SQL层的分析;关系型数据库将数据储存在电脑硬盘中,查询速率远不如Nosql数据库。
3)储存格式:Nosql的储存文件格式是key,value方式、文本文档方式、照片方式这些,能储存的对象种类灵活;关系数据库则只适用基础类型。
4)可扩展性:关系型数据库有join那样的多表查询机制限定造成拓展性较差。Nosql依据键值对,数据中间沒有耦合度,因此容易水平拓展。
5)数据一致性:非关系型数据库注重最终一致性;关系型数据库注重数据整个生命周期的强一致性。
6)事务处理:SQL数据库支持事务原子性粒度控制,且方便进行事务回滚;NoSQL也支持事务处理,但可靠性不足,其价值在于可扩展性和大数据量处理。
█ 8.最左匹配原则
最左匹配原则是针对索引的
举例来说:两个字段(name,age)建立联合索引,如果where age=12这样的话,是没有利用到索引的,
这里我们可以简单的理解为先是对name字段的值排序,然后对age的数据排序,如果直接查age的话,这时就没有利用到索引了,
查询条件where name=‘xxx’ and age=xx 这时的话,就利用到索引了,
where age=xx and name=‘xxx’ 正常的原则来讲是不会利用到的,但是优化器会进行优化,把位置交换下。这个sql也能利用到索引了。
█ 9.索引 B+树
○ 9.1 B+树的实现
多路搜索树
1)有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。
2)所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
3)所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素
4)B+树的搜索与 B 树也基本相同,区别是 B+树只有达到叶子结点才命中(B 树可以在非叶子结点命中),其性能也等价于在关键字全集做一次二分查找;
5)所有关键字都出现在叶子结点的链表中(即数据只能在叶子节点【也叫稠密索引】),且链表中的关键字(数据)
恰好是有序的。
6)非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层
○ 9.2为什么使用B+树:
索引查找过程中就要产生磁盘I/O消耗,主要看IO次数,和磁盘存取原理有关。
根据B-Tree的定义,可知检索一次最多需要访问h个节点。
数据库系统的设计者巧妙利用了磁盘预读原理,
将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入
○ 9.3 索引的底层实现(B+树,为何不采用红黑树,B树)重点
| 树 | 区别 |
|---|---|
| 红黑树 | 增加,删除,红黑树会进行频繁的调整,来保证红黑树的性质,浪费时间 |
| B树也就是B-树 | B树,查询性能不稳定,查询结果高度不致,每个结点保存指向真实数据的指针,相比B+树每一层每屋存储的元素更多,显得更高一点。 |
| B+树 | B+树相比较于另外两种树,显得更矮更宽,查询层次更浅 |
█ 10.树
○ 10.1 B树 2-3树:
B树:Balanced
1)B 树通过重新组织节点, 降低了树的高度.
2)文件系统及数据库系统的设计者利用了磁盘预读原理,将一个节点的大小设为等于一个页(页得大小通常为4k), 这样每个节点只需要一次 I/O 就可以完全载入
3)将树的度 M 设置为 1024,在 600 亿个元素中最多只需要 4 次 I/O 操作就可以读取到想要的元素,B 树(B+)广泛应用于文件存储系统以及数据库系统中
B树的特点
1)B 树的阶:节点的最多子节点个数。比如 2-3 树的阶是 3,2-3-4 树的阶是 4;
2)B-树的搜索,从根结点开始,对结点内的关键字(有序)序列进行二分查找;
3)关键字集合分布在整颗树中, 即叶子节点和非叶子节点都存放数据.
2-3树:
1)2-3 树的所有叶子节点都在同一层.(只要是 B 树都满足这个条件)
2)有两个子节点的节点叫二节点,二节点要么没有子节点,要么有两个子节点.
3)有三个子节点的节点叫三节点,三节点要么没有子节点,要么有三个子节点
4)当按照规则插入一个数到某个节点时,不能满足上面三个要求,就需要拆,先向上拆,如果上层满,则拆本层, 拆后仍然需要满足上面 3 个条件。
5)对于三节点的子树的值大小仍然遵守(BST 二叉排序树)的规则
○ 10.2 B+ 多路搜索树
1)有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。
2)所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
3)所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素
4)B+树的搜索与 B 树也基本相同,区别是 B+树只有达到叶子结点才命中(B 树可以在非叶子结点命中),其性能也等价于在关键字全集做一次二分查找;
5)所有关键字都出现在叶子结点的链表中(即数据只能在叶子节点【也叫稠密索引】),且链表中的关键字(数据)
恰好是有序的。
6)非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层
○ 10.3 B*树
在 B+树的非根和非叶子结点再增加指向兄弟的指针。
1)B树定义了非叶子结点关键字个数至少为(2/3)M,即块的最低使用率为 2/3,而 B+树的块的最低使用率为的 1/2。
2)从第 1 个特点我们可以看出,B*树分配新结点的概率比 B+树要低,空间使用率更高
○ 10.4 红黑树
特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。
红黑树的特性:
(1)每个节点或者是黑色,或者是红色。
(2)根节点是黑色。
(3)每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
(4)如果一个节点是红色的,则它的子节点必须是黑色的。
(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
注意:
(01) 特性(3)中的叶子节点,是只为空(NIL或null)的节点。
(02) 特性(5),确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接近平衡的二叉树。
应用:
主要是用它来存储有序的数据,它的时间复杂度是O(lgn),效率非常之高。
例如,Java集合中的TreeSet和TreeMap,C++ STL中的set、map,以及Linux虚拟内存的管理,都是通过红黑树去实现的。
○ 10.5 霍夫曼树
又称为最优二叉树,其主要作用在于数据压缩和编码长度的优化。
给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为霍夫曼树(Huffman Tree)。
█ 11.Redis命令
Redis中的事务的本质:将一组操作放在队列中,一次性执行
redis不是真正的事务,是一种事务的模拟。
开启事务:命令:multi
127.0.0.1:6379> set tom 1000
OK
127.0.0.1:6379> set ticket 1
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby tom 500
QUEUED
127.0.0.1:6379> decr ticket
QUEUED
在提交之前从另一个窗口把票买了
127.0.0.1:6379> exec
1) (integer) 500
2) (integer) -1

Redis传统五大数据类型的落地应用
1.string || 2.list || 3.hash || 4.set || 5.zset(sorted set)
还有其他的数据类型:
bitmap || HyperLogLog 统计 || GEO || stream
Redis的命令不区分大小写,但是key区分大小写
○ 11.1 string: 点赞
命令:set K1 v1 /// keys * /// help /// help @string 查string类型
mset k1 v1 k2 v2 k3 v3 /// mget k1 k2 k3
**递增数字 ** INCR key /// incr intems:001
增加指定的整数 INCRBY key increment
递减数值 DECR key
减少指定的整数 DECRBY key decrement
获取字符串长度 STRLEN key
![]()
![]()
![]()
分布式锁:
![]()
○ 11.2 hash 购物车
对应java是
![]()
![]()
![]()
○ 11.3 list 订阅号
![]()
![]()
订阅号:
![]()
○ 11.4 set 抽奖/朋友圈点赞
无序不重复,数字不写是1
![]()
![]()
![]()
![]()
![]()
![]()
![]()
○ 11.5 zset 热搜排序
![]()
![]()
![]()
█ 12.Redis 6379
Redis中的事务的本质:将一组操作放在队列中,一次性执行
redis不是真正的事务,是一种事务的模拟。
开启事务:命令:multi
127.0.0.1:6379> set tom 1000
OK
127.0.0.1:6379> set ticket 1
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby tom 500
QUEUED
127.0.0.1:6379> decr ticket
QUEUED
在提交之前从另一个窗口把票买了
127.0.0.1:6379> exec
1) (integer) 500
2) (integer) -1

○ 12.1 Redis锁机制(简单的锁)
Redis锁机制(简单的锁):执行事务操作的时候,如果监视的值发生变化,则提交失败。
命令 watch
举例:买票
127.0.0.1:6379> set tom 1000
OK
127.0.0.1:6379> set ticket 1
OK
127.0.0.1:6379> watch ticket 监视
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby tom 500
QUEUED
127.0.0.1:6379> decr ticket 两个窗口去强
QUEUED
127.0.0.1:6379> exec 执行
(nil)
127.0.0.1:6379> get tom
"1000"
127.0.0.1:6379> get ticket
"0"
打印出nil代表操作没有执行,或者操作执行失败。
○ 12.2 分布式锁实现方案
jvm层面的加锁,单机版的锁
分布式微服务架构,拆分之后各个微服务之间为了避免冲突和数据故障而加入的锁,分布式锁。
Redis做分布式锁
取消单机锁,Redis分布式锁setnx,只加了锁,没有释放锁,出异常可能无法释放,必须要在finally释放锁
宕机了,没有走到finally,没有解锁,这个key没有被删除,需要有lockKey的过期时间设定
1.过期时间 2.要setnx+过期必须同一行
只能自己删自己的锁
○ 12.3 Redis消息机制:消息系统
(1)消息的类型:
(*)Queue消息:队列(点对点) 张三发给李四,只有李四收到。消息可以是字符串,也可以是对象。
(*)Topic消息:主题(广播、群发):发布消息、订阅消息
(2)常见的消息系统:
Redis:只支持Topic消息
Kafka:只支持Topic消息,需要zookeeper支持。
JMS:Java Messaging Service。Java消息服务标准,支持Queue,也支持Topic。
产品:Weblogic
(3)Redis的消息机制
命令:publish 发布消息
subscribe 订阅消息
psubscribe 订阅消息 可以使用通配符来订阅消息
○ 12.4 Redis 持久化 RDB快照|AOF日志
本质:备份和恢复
弥补memcached不足
(1)RDB快照:默认
(*)一种快照,就是一种备份。每隔一段时间,会把内存中的数据,保存到硬盘上的文件。产生rdb文件。
当内存数据崩溃,重新启动redis时,会读这个文件
注意:每隔一段时间生成
(*)RDB生成策略
配置文件:
147 save 900 1 在900秒内,如果有1个key发生变化,就执行rdb
148 save 300 10 在300秒内,如果有10个key发生变化,就执行rdb
149 save 60 10000 在60秒内,如果有10000个key发生变化,就执行rdb
save 时间(秒) 数字(key变化个数)
从下往上看
(*)RDB优点和缺点:
优点:快,恢复速度快
缺点:在两次rdb之间,可能会造成数据丢失。因为没隔一段时间做一个快照。
解决:AOF
(*)其他参数
164 stop-writes-on-bgsave-error yes
当后台写进程出错的时候,禁止写入新的数据
bgsave 手动触发RDB命令
170 rdbcompression yes
是否压缩 如果看中性能,选择no
压缩会节约空间,但会影响备份和恢复性能。
182 dbfilename dump.rdb
192 dir ./
(2)AOF日志:操作记录日志
客户端在操作redis时,把所有客户端的操作记录到文件中,如果发生崩溃,把操作完全恢复一遍,就恢复了数据
(*)默认是禁用的。需要修改参数,来启动。
509 appendonly yes 启动aof
(*)AOF记录日志策略
538 # appendfsync always 每个操作都记录日志:优点 安全。缺点:慢。
539 appendfsync everysec
540 # appendfsync no 由操作系统来决定记录日志的方式。不会用得到
默认是每秒记录一次日志
(*)AOF的日志重写
举例:假如每个操作都记录到aof日志中
set money 0
incr money
incr money
incr money
.....自增100次
如果每个操作都记录日志的话,会记录101条日志。这是没有必要的
最终的结果 money 100
进行日志重写:
上面的101条删除,添加一条 set money 100
这句话效果和上面101条效果一样。
./redis-benchmark -n 100000 模拟10万次redis操作
aof参数设置:
561 no-appendfsync-on-rewrite no
执行重写的时候,不写入新的日志
581 auto-aof-rewrite-min-size 64mb
执行重写的aof文件大小。超过64M就触发重写
(3)当RDB和aof同时存在时,我优先执行哪个恢复?
504 # If the AOF is enabled on startup Redis will load the AOF, that is the file
505 # with the better durability guarantees.
如果aof开启,优先使用aof
○ 12.5 Redis的主从复制
1、Redis主从复制集群:有多个Redis实例
作用:
(1)主从备份,方式主节点down机
主节点写入数据,从节点读取数据。
(2)任务分离,分摊主节点压力。读写分离。
不同系统,读写压力不同。
微博、朋友圈
(3)读写分离:主节点写数据,从节点读取数据。
主从复制架构:
1、星型模型
2、线性模型
优缺点:
星型结构:
优点:效率高,两个slave地位一样,可以直接从主节点读取数据
缺点:实现HA比较困难。主节点挂了,把一个slave变成主,其他的slave再去连他。
提供哨兵机制来解决这个问题。
线性模型:
优点:HA简单。 HA高可用
缺点:效率不如星型模型高。
生产使用星型模型多。
搭建:
1023 ./bin/redis-cli shutdown
1024 ps -ef | grep redis
1025 ll
1026 cd conf/
1027 ll
1028 cp redis.conf redis6379.conf
1029 cp redis.conf redis6380.conf
1030 cp redis.conf redis6381.conf
主节点:
147 #save 900 1
148 #save 300 10
149 #save 60 10000
509 appendonly no
从节点:
50 port 6380
182 dbfilename dump6380.rdb
211 slaveof 192.168.109.133 6379
514 appendfilename "appendonly6380.aof"
./redis-cli -p 6380
127.0.0.1:6380> set tom 1000
(error) READONLY You can't write against a read only slave.
注意:一次启动从节点的个数不要太多,因为如果有太多从节点,会给主节点增加很多同步压力。
○ 12.6 Redis 哨兵
单点故障。
Redis 2.4之后,有哨兵
正常情况下,哨兵就是监控master状态。接收master心跳。
如果接收不到心跳,认为master死掉。进行HA切换。
redis-sentinel 哨兵
从安装目录下拷贝sentinel配置文件
53 sentinel monitor mymaster 192.168.109.133 6379 1
1代表一个哨兵
1723:X 23 Nov 05:33:52.337 # +try-failover master mymaster 192.168.109.133 6379
1723:X 23 Nov 05:33:52.428 # +selected-slave slave 192.168.109.133:6380 192.168.109.133 6380 @ mymaster 192.168.109.133 6379
1723:X 23 Nov 05:33:54.561 # +switch-master mymaster 192.168.109.133 6379 192.168.109.133 6380
1723:X 23 Nov 05:33:54.562 * +slave slave 192.168.109.133:6381 192.168.109.133 6381 @ mymaster 192.168.109.133 6380
○ 12.7 生产中 Redis内存设置:
config 文件 maxmemory 默认是没有配置或者0,是最大的,64位系统不限制内存大小,字节。
生产配 设置内存为 最大物理内存的3/4
如何配置、修改Redis内存大小
1)修改文件配置config maxmemory
2)运行中动态修改
redis-server /myredis/redis.conf
redis-cli
config get maxmemory
config set maxmemory 1
info memory
SHUTDOWN
○ 12.8 内存满,Redis清理内存 Redis缓存过期淘汰策略
OOM
Redis缓存过期淘汰策略
1)定时删除:立即删除对cpu造成压力,用处理器性能换取存储空间(拿时间换空间)
2)惰性删除:到达过期时间,不处理,再次访问时,如果不过期,返回数据,如果过期,删除。。。对内存不友好,过期但是没有被访问,就会占空间。
3)定期删除:每个一段时间执行一次删除过期键操作,限制删除操作的时长 评率 减少对CPU时间的影响。。。随机抽取策略。。。抽样key,依旧有没有访问到的。
Redis缓存淘汰策略:
LRU 最近最少使用 最近最少使用,是一种常用的页面置换算法。选择最近最久未使用的数据予以淘汰。
LFU 最近最不频繁使用
![]()
![]()
1)config:maxmemory-policy allkeys-lru
2)命令 :
config set maxmemory-policy allkeys-lru
config get maxmemory-policy
info memory
○ 12.9 RedisLRU了解过吗
Least Recently Used 最近最少使用,是一种常用的页面置换算法。选择最近最久未使用的数据予以淘汰。
LRU的算法核心是 哈希链表 extends LinkedHashMap<K,V>

浙公网安备 33010602011771号