From c0bd15de8634c84dedd53e276f36061aeb354e03 Mon Sep 17 00:00:00 2001 From: liruyu Date: Thu, 14 Oct 2021 11:08:27 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=96=B0=E5=A2=9ERedis=E6=89=A9=E5=B1=95?= =?UTF-8?q?=E6=96=B9=E6=A1=88=202.=E6=96=B0=E5=A2=9ERedis=E9=94=81?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E7=9A=848=E5=A4=A7=E9=97=AE=E9=A2=98=203.?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=95=B0=E6=8D=AE=E5=BA=93=E4=BA=8B=E5=8A=A1?= =?UTF-8?q?=E9=9A=94=E7=A6=BB=E7=BA=A7=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Database.md | 42 +++++---- Middleware.md | 106 +++++++++++++++++++++++ Solution.md | 77 ++++++++++++++++ images/Solution/Redis释放锁流程.jpg | Bin 0 -> 26132 bytes 4 files changed, 209 insertions(+), 16 deletions(-) create mode 100644 images/Solution/Redis释放锁流程.jpg diff --git a/Database.md b/Database.md index 5a936c4..9c5148d 100644 --- a/Database.md +++ b/Database.md @@ -1141,7 +1141,7 @@ InnoDB实现回滚靠的是undo log。当事务对数据库进行修改时,Inn **一致性是指事务执行结束后,数据库的完整性约束没有被破坏,事务执行的前后都是合法的数据状态。** -数据库的完整性约束包括但不限于:实体完整性(如行的主键存在且唯一)、列完整性(如字段的类型、大小、长度要符合要求)、外键约束、用户自定义完整性(如转账前后,两个账户余额的和应该不变)。 +数据库的完整性约束包括但不限于:实体完整性(如行的主键存在且唯一)、列完整性(如字段的类型、大小、长度要符合要求)、外键约束、用户自定义完整性(如转账前后,两个账户余额的和应该不变)。假如A账户给B账户转10块钱,不管成功与否,A和B的总金额是不变的。 @@ -1167,7 +1167,7 @@ InnoDB实现回滚靠的是undo log。当事务对数据库进行修改时,Inn 隔离性追求的是并发情形下事务之间互不干扰。主要分为两个方面: -**① 锁机制保证隔离性**:(一个事务)写操作对(另一个事务)写操作的影响 +**① 加锁机制保证隔离性**:(一个事务)写操作对(另一个事务)写操作的影响 事务在修改数据之前,需要先获得相应的锁;获得锁之后,事务便可以修改数据;该事务操作期间,这部分数据是锁定的,其它事务如果需要修改数据,需要等待当前事务提交或回滚后释放锁。 @@ -1234,10 +1234,20 @@ MVCC全称Multi-Version Concurrency Control,即多版本的并发控制协议 在事务的并发操作中,不做隔离操作则可能会出现 **脏读、不可重复读、幻读** 问题: -- **脏读**:**事务A中读到了事务B中未提交的更新数据内容**。然后B回滚操作,那么A读取到的数据是脏数据 -- **不可重复读**:**事务A读到事务B已经提交后的数据**。即事务A多次读取同一数据时,返回结果不一致 -- **幻读**:事物A执行select后,事物B**增或删**了一条数据,事务A再执行同一条SQL后发现多或少了一条数据 -- **第一类丢失更新:** A事务撤销事务时,覆盖了B事务提交的事务(现代关系型数据库中已经不会发生) +- **脏读**:**指一个事务读取到了另一个未提交事务修改过的数据** + + 事务A中读到了事务B中未提交的更新数据内容,然后B回滚操作,那么A读取到的数据是脏数据。 + +- **不可重复读**:**同一个事务内,前后多次读取,读取到的数据内容不一致** + + 事务A读到事务B已经提交后的数据,即事务A多次读取同一数据时,返回结果不一致。 + +- **幻读**:**指一个事务先根据某些搜索条件查询出一些记录,在该事务未提交时,另一个事务写入了一些符合那些搜索条件的记录(如insert、delete、update),再次查询出的结果则出现不一致** + + 事物A执行select后,事物B增或删了一条数据,事务A再执行同一条SQL后发现多或少了一条数据。 + +- **第一类丢失更新:** A事务撤销事务时,覆盖了B事务提交的事务(现代关系型数据库中已经不会发生) + - **第二类丢失更新:** A事务提交事务时,覆盖了B事务提交的事务(是不可重复读的特殊情况) **小结**:不可重复读的和幻读很容易混淆,**不可重复读**侧重于**修改**,**幻读**侧重于**新增或删除**。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表。查看 `mysql` 事务隔离级别:`show variables like 'tx_iso%';`。 @@ -1257,11 +1267,11 @@ MVCC全称Multi-Version Concurrency Control,即多版本的并发控制协议 ### Read Uncommitted(读未提交) -**即读取到了其它事务未提交的内容(可能会被回滚)**。在该隔离级别,**所有事务都可以看到其他未提交事务的执行结果**。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为**脏读(Dirty Read)**。 +只限制了两个数据**不能同时修改**,但即使事务未提交也会**读取到其它事务未提交的内容(可能会被回滚)**。会有**脏读、重复读、幻读**的问题,读取未提交的数据,也被称之为**脏读(Dirty Read)**。 **特点**:最低级别,任何情况都无法保证 -**读未提交的数据库锁情况** +**数据库锁情况** - 读取数据:**未加锁,每次都读到最新数据,性能最好** - 写入数据:**只对数据增加行级共享锁,写完释放** @@ -1270,13 +1280,13 @@ MVCC全称Multi-Version Concurrency Control,即多版本的并发控制协议 ### Read Committed(读已提交) -**即读取到了其它事务已提交的内容**。一个事务只能看见已经提交事务所做的改变。这种隔离级别也支持所谓的**不可重复读(Nonrepeatable Read)**,因为同一事务的其他实例在该实例处理期间可能会有新的commit,所以同一select可能返回不同结果。 +当前事务只能读取到其它事务**已提交**的数据。因同一事务的其它实例在该实例处理期间可能会有新的commit,所以同一select可能返回不同结果,这就是所谓的**不可重复读(Nonrepeatable Read)**。该隔离级别**解决了脏读**问题,但还是会存在**重复读、幻读**问题。 **特点**:避免脏读 -**脏读解决方案:基于乐观锁理论的MVCC(多版本并发控)实现** +**脏读解决方案**:基于乐观锁理论的MVCC(多版本并发控)实现 -**读已提交的数据库锁情况** +**数据库锁情况** - 读取数据:**加行级共享锁(读到时才加锁),读完后立即释放** - 写入数据:**在更新时的瞬间对其加行级排它锁,直到事务结束才释放** @@ -1285,15 +1295,15 @@ MVCC全称Multi-Version Concurrency Control,即多版本的并发控制协议 ### Repeatable Read(可重复读) -**它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行**。但会导致**幻读 (Phantom Read)**问题。 +限制了读取数据时**不可以进行修改**,所以**解决了不能重复读**的问题。但是读取范围数据的时候,是可以插入或删除数据,所以还会存在**幻读(Phantom Read)**问题。 **幻读** 是户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当该用户再读取该范围的数据行时,会发现有新的“幻影” 行。 **特点**:避免脏读、不可重复读。MySQL默认事务隔离级别 -**不可重复读解决方案:基于乐观锁理论的MVCC(多版本并发控)实现** +**不可重复读解决方案**:基于乐观锁理论的MVCC(多版本并发控)实现 -**可重复读的数据库锁情况** +**数据库锁情况** - 读取数据:**开始读取的瞬间对其增加行级共享锁,直到事务结束才释放** - 写入数据:**开始更新的瞬间对其增加行级排他锁,直到事务结束才释放** @@ -1302,11 +1312,11 @@ MVCC全称Multi-Version Concurrency Control,即多版本的并发控制协议 ### Serializable(可串行化) -**指一个事务在执行过程中完全看不到其他事务对数据库所做的更新**。当两个事务同时操作数据库中相同数据时,如果第一个事务已经在访问该数据,第二个事务只能停下来等待,必须等到第一个事务结束后才能恢复运行。因此这两个事务实际上是串行化方式运行。 +所有事务都是进行**串行化顺序**执行的。可以避免**脏读**、**不可重复读**与**幻读**所有并发问题。但该事务隔离级别下,事务执行很耗性能。 **特点**:避免脏读、不可重复读、幻读 -**可序列化的数据库锁情况** +**数据库锁情况** - 读取数据:**先对其加表级共享锁 ,直到事务结束才释放** - 写入数据:**先对其加表级排他锁 ,直到事务结束才释放** diff --git a/Middleware.md b/Middleware.md index d375244..561bbca 100644 --- a/Middleware.md +++ b/Middleware.md @@ -1260,6 +1260,112 @@ cluster_stats_messages_received:3021 +## 拓展方案 + +### 分区(Partitioning) + +指在面临**单机**的**存储空间**瓶颈时,即将全部数据分散在多个Redis实例中,每个实例不需要关联,可以是完全独立的。 + + + +**使用方式** + +- 客户端处理 + 和传统的数据库分库分表一样,可以从**key**入手,先进行计算,找到对应数据存储的实例在进行操作。 + - **范围角度**,比如orderId:1~orderId:1000放入实例1,orderId:1001~orderId:2000放入实例2 + - **哈希计算**,就像我们的**hashmap**一样,用hash函数加上位运算或者取模,高级玩法还有一致性Hash等操作,找到对应的实例进行操作 +- 使用代理中间件 + 我们可以开发独立的代理中间件,屏蔽掉处理数据分片的逻辑,独立运行。当然Redis也有优秀的代理中间件,譬如Twemproxy,或者codis,可以结合场景选择是否使用 + + + +**缺点** + +- **无缘多key操作**,key都不一定在一个实例上,那么多key操作或者多key事务自然是不支持 +- **维护成本**,由于每个实例在物理和逻辑上,都属于单独的一个节点,缺乏统一管理 +- **灵活性有限**,范围分片还好,比如hash+MOD这种方式,如果想**动态**调整Redis实例的数量,就要考虑大量数据迁移 + + + +### 主从(Master-Slave) + +分区暂时能解决**单点**无法容纳的**数据量问题**,但是一个Key还是只在一个实例上。主从则将数据从**主节点**同步到**从节点**,然后可做**读写分离**,将读流量均摊在各个从节点,可靠性也能提高。**主从**(Master-Slave)也就是复制(Replication)方式。 + + + +**使用方式** + +- 作为主节点的Redis实例,并不要求配置任何参数,只需要正常启动 +- 作为从节点的实例,使用配置文件或命令方式`REPLICAOF 主节点Host 主节点port`即可完成主从配置 + + + +**缺点** + +- slave节点都是**只读**的,如果**写流量**大的场景,就有些力不从心 +- **故障转移**不友好,主节点挂掉后,写处理就无处安放,需要**手工**的设定新的主节点,如使用`REPLICAOF no one` 晋升为主节点,再梳理其他slave节点的新主配置,相对来说比较麻烦 + + + +### 哨兵(Sentinel) + +**主从**的手工故障转移,肯定让人很难接受,自然就出现了高可用方案-**哨兵**(Sentinel)。我们可以在主从架构不变的场景,直接加入**Redis Sentinel**,对节点进行**监控**,来完成自动的**故障发现**与**转移**。并且还能够充当**配置提供者**,提供主节点的信息,就算发生了故障转移,也能提供正确的地址。 + + + +**使用方式** + +**Sentinel**的最小配置,一行即可: + +```properties +sentinel monitor <主节点别名> <主节点host> <主节点端口> <票数> +``` + +只需要配置master即可,然后用``redis-sentinel <配置文件>`` 命令即可启用。哨兵数量建议在三个以上且为奇数。 + + + +**使用场景问题** + +- 故障转移期间短暂的不可用,但其实官网的例子也给出了`parallel-syncs`参数来指定并行的同步实例数量,以免全部实例都在同步出现整体不可用的情况,相对来说要比手工的故障转移更加方便 +- 分区逻辑需要自定义处理,虽然解决了主从下的高可用问题,但是Sentinel并没有提供分区解决方案,还需开发者考虑如何建设 +- 既然是还是主从,如果异常的写流量搞垮了主节点,那么自动的“故障转移”会不会变成自动“灾难传递”,即slave提升为Master之后挂掉,又进行提升又被挂掉 + + + +### 集群(Cluster) + +**Cluster**在分区管理上,使用了“**哈希槽**”(hash slot)这么一个概念,一共有**16384**个槽位,每个实例负责一部分**槽**,通过`CRC16(key)&16383`这样的公式,计算出来key所对应的槽位。 + + + +**使用方式** + +配置文件 + +```properties +cluster-enabled yes +cluster-config-file "redis-node.conf" +``` + +启动命令 + +```bash +redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 \ +127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \ +--cluster-replicas 1 +``` + + + +**存在问题** + +- 虽然是对分区良好支持,但也有一些分区的老问题。如如果不在同一个“槽”的数据,是没法使用类似mset的**多键操作** +- 在select命令页有提到, 集群模式下只能使用一个库,虽然平时一般也是这么用的,但是要了解一下 +- 运维上也要谨慎,俗话说得好,“**使用越简单底层越复杂**”,启动搭建是很方便,使用时面对带宽消耗,数据倾斜等等具体问题时,还需人工介入,或者研究合适的配置参数 + + + ## 常见问题 **题目**:保证Redis 中的 20w 数据都是热点数据 说明是 被频繁访问的数据,并且要保证Redis的内存能够存放20w数据,要计算出Redis内存的大小。 diff --git a/Solution.md b/Solution.md index a21f6de..22c141d 100644 --- a/Solution.md +++ b/Solution.md @@ -2045,6 +2045,83 @@ public void unlock() { ## Redis +https://mp.weixin.qq.com/s?__biz=MzAwMDg2OTAxNg==&mid=2652055114&idx=1&sn=f4d73fa2e294d633224f4d94a0667e70&chksm=8105d1bdb67258ab458389bd23d8e0211d34835f9da3745a0e6c244ec943911220db0c011665&mpshare=1&scene=23&srcid=1014HUmkIFVfi7rEQQ6bmuqH&sharer_sharetime=1634173594040&sharer_shareid=0f9991a2eb945ab493c13ed9bfb8bf4b%23rd + +### 分布式锁的问题 + +#### 非原子操作 + +`加锁操作`和后面的`设置超时时间`是分开的,并`非原子操作`。解决方案: + +- **set命令** +- **LUA脚本** + + + +#### 忘了释放锁 + +在redis中还有`set`命令是原子操作,加锁和设置超时时间,一个命令就能轻松搞定。 + +```java +String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime); +if ("OK".equals(result)) { + return true; +} +return false; +``` + +其中: + +- `lockKey`:锁的标识 +- `requestId`:请求id +- `NX`:只在键不存在时,才对键进行设置操作 +- `PX`:设置键的过期时间为 millisecond 毫秒 +- `expireTime`:过期时 + +使用`set`命令加锁,表面上看起来没有问题。但如果仔细想想,加锁之后,每次都要达到了超时时间才释放锁,会不会有点不合理?加锁后,如果不及时释放锁,会有很多问题。分布式锁更合理的流程如下: + +![Redis释放锁流程](images/Solution/Redis释放锁流程.jpg) + +释放锁的伪代码如下: + +```java +try{ + String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime); + if ("OK".equals(result)) { + return true; + } + return false; +} finally { + unlock(lockKey); +} +``` + + + +#### 释放了别人的锁 + + + +#### 大量失败请求 + + + +#### 锁重入问题 + + + +#### 锁竞争问题 + + + +#### 锁超时问题 + + + +#### 主从复制的问题 + + + ### LUA+SETNX+EXPIRE 先用`setnx`来抢锁,如果抢到之后,再用`expire`给锁设置一个过期时间,防止锁忘记了释放。 diff --git a/images/Solution/Redis释放锁流程.jpg b/images/Solution/Redis释放锁流程.jpg new file mode 100644 index 0000000000000000000000000000000000000000..43e167ffd237f321095b9cc1052bc98fb2b0606c GIT binary patch literal 26132 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