mirror of
https://github.com/qiurunze123/miaosha.git
synced 2023-11-19 22:41:03 +08:00
补充代码内容和说明
This commit is contained in:
parent
bc02008d37
commit
d73c25af48
|
@ -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,6 +143,29 @@
|
||||||
2. 执行EVALSHA命令时Redis会根据提供的摘要从脚本缓存中查找对应的脚本内容
|
2. 执行EVALSHA命令时Redis会根据提供的摘要从脚本缓存中查找对应的脚本内容
|
||||||
如果找到了就执行脚本,否则返回“NOSCRIPT No matching script,Please use EVAL”
|
如果找到了就执行脚本,否则返回“NOSCRIPT No matching script,Please use EVAL”
|
||||||
|
|
||||||
|
演示流程:
|
||||||
|
|
||||||
|
```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"
|
||||||
|
```
|
||||||
|
|
||||||
**Redis(2.6以后)--lua脚本运行限制**
|
**Redis(2.6以后)--lua脚本运行限制**
|
||||||
|
|
||||||
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
|
||||||
|
```
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user