补充代码内容和说明

This commit is contained in:
李文浚 2020-04-03 17:10:44 +08:00 committed by anruence
parent bc02008d37
commit d73c25af48

View File

@ -21,7 +21,7 @@
1.一个进程中的多个线程,多个线程并发访问同一个资源的时候,如何解决线程安全问题。 1.一个进程中的多个线程,多个线程并发访问同一个资源的时候,如何解决线程安全问题。
2.一个分布式架构系统中的两个模块同时去访问一个文件对文件进行读写操作 2.一个分布式架构系统中的两个模块同时去访问一个文件对文件进行读写操作
3.多个应用对同一条数据做修改的时候,如何保证数据的安全性 3.多个应用对同一条数据做修改的时候,如何保证数据的安全性
但一个进程中,我们可以用到synchronized、lock之类的同步操作去解决,但是对于分布式架构下多进程的情况下, 一个进程中,我们可以用到synchronized、lock之类的同步操作去解决,但是对于分布式架构下多进程的情况下,
如何做到跨进程的锁。就需要借助一些第三方手段来完成 如何做到跨进程的锁。就需要借助一些第三方手段来完成
**设计一个分布式所需要解决的问题,分布式锁解决方案(数据库方案)** **设计一个分布式所需要解决的问题,分布式锁解决方案(数据库方案)**
@ -51,7 +51,7 @@
1.锁没有失效时间,一旦解锁操作失败,就会导致锁记录一直在数据库中,其他线程无法再获得到锁 1.锁没有失效时间,一旦解锁操作失败,就会导致锁记录一直在数据库中,其他线程无法再获得到锁
2.锁是非阻塞的,数据的insert操作,一旦插入失败就会直接报错。没有获得锁的线程并不会进入排队队列 2.锁是非阻塞的,数据的insert操作,一旦插入失败就会直接报错。没有获得锁的线程并不会进入排队队列
要想再次获得锁就要再次触发获得锁操作 要想再次获得锁就要再次触发获得锁操作
3.锁是非重入的,同一个线程在没有释放锁之前无法再次获得该锁 3.锁是非重入的,同一个线程在没有释放锁之前无法再次获得该锁(要解决这个问题可以在表中多加一列用于记录线程名称,通过判断这个列来实现重入)
**ZK方案** **ZK方案**
@ -143,7 +143,30 @@
2. 执行EVALSHA命令时Redis会根据提供的摘要从脚本缓存中查找对应的脚本内容 2. 执行EVALSHA命令时Redis会根据提供的摘要从脚本缓存中查找对应的脚本内容
如果找到了就执行脚本,否则返回“NOSCRIPT No matching script,Please use EVAL” 如果找到了就执行脚本,否则返回“NOSCRIPT No matching script,Please use EVAL”
**Redis2.6以后)--lua脚本运行限制** 演示流程:
```shell
# 计算出脚本的sha1用于后续验证
127.0.0.1:6379> SCRIPT LOAD "return 'hello moto'"
"232fd51614574cf0867b83d384a5e898cfd24e5a"
# 判断脚本存在
127.0.0.1:6379> SCRIPT EXISTS 232fd51614574cf0867b83d384a5e898cfd24e5a
1) (integer) 1
# 清空所有脚本
127.0.0.1:6379> SCRIPT FLUSH
OK
# 判断脚本不存在
127.0.0.1:6379> SCRIPT EXISTS 232fd51614574cf0867b83d384a5e898cfd24e5a
1) (integer) 0
# 直接运行脚本redis会自动进行缓存
127.0.0.1:6379> EVAL "return 'hello moto'" 0
"hello moto"
# 根据缓存中的sha1来直接运行脚本
127.0.0.1:6379> EVALSHA 232fd51614574cf0867b83d384a5e898cfd24e5a 0
"hello moto"
```
**Redis2.6以后)--lua脚本运行限制**
redis的脚本执行是原子的,即脚本执行期间Redis不会执行其他命令 redis的脚本执行是原子的,即脚本执行期间Redis不会执行其他命令
所有的命令必须等待脚本执行完以后才能执行。为了防止某个脚本执行时间过程导致Redis无法提供服务 所有的命令必须等待脚本执行完以后才能执行。为了防止某个脚本执行时间过程导致Redis无法提供服务
@ -173,3 +196,30 @@
lua脚本一致存在于redis 中可以 限制每秒钟的请求数实现限流! lua脚本一致存在于redis 中可以 限制每秒钟的请求数实现限流!
这里提供一种基于zset的信号量实现方式
- zset的成员为uuid唯一代表某一个线程分数是当前的时间戳
- 限制zset中给的成员数量来实现限流
- 根据zset的分值时间戳按大小进行排序移除某一范围的成员实现超时移除处理
假定zset的名字为`xhlZset`,获取信号量:
```
// 被动触发超时处理将已经超时的信号量移除出zset
zremrangebyscore xhlZset -inf now-timeout
// 如果信号量的数量没有超出限制
if zcard xhlZset < limit {
// 添加记录uuid以及当前时间戳now
zadd xhlZset now uuid
return 1
}
return 0
```
释放信号量
```
zrem xhlZset uuid
```