分布式系统学习

发布时间:2022-07-03 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了分布式系统学习脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

集群环境下不能使用 jvm 级别的锁,而是需要使用 分布式锁

去一个指定的地方获取锁

分布式系统思路

  1. MySQL 方案
  2. redis 方案
  3. ZK 方案

1、MySQL 方案。不能重复插入有唯一约束的数据。PK、UK

mysql 可抗 10w QPS,关键看配置

实际中用的不多,中小型公司使用

https://help.aliyun.COM/document_detail/109378.htML

分布式系统学习

2、Redis 方案

加锁:SETNX key value

放锁:del key

一步一步简单实现:

使用 redis 简单实现分布式锁

使用 setnx 操作

​ SETNX(key, value) :如果存在则返回false,如果不存在则放入则 true

​ 类似乐观锁

利用了 redis 单线程的特点

fun() {
	result = setnx(key, value);
	if (result == false) return;//没拿到则返回
	拿到则执行操作.

	delete(key);
}

出现的问题:

  1. 程序抛异常:使用 try-finally 最终删除 key
  2. 系统宕机、进程被 kill:设置超时时间 expire,expire+setnx 的原子操作

设置超时时间。小型规模应用默认 10s 业务可以处理完

try {
	redis.setIfAbseat(key, 10, value);
}finally{
	redis.delete(key)
}

如果是高并发情况,可能会出现超过10s的情况,会出现严重错误。当前线程删除其他线程的 lock

继续完善:

try {
	redis.setIfAbsent(key, 10, uuid);
} finally {
    if(redis.get(key).equals(uuid)) {//此处有原子问题
        redis.delete(key)
    }
}

思考:10s是否够用?可能不够用,设置成30s?是否够用?

解决方法:锁续命,使用一个附加线程定时检查剩余时间,如果还持有锁则增加超时时间。直到业务处理完其他线程可以获得锁。

如果从头开始写,很容易出现bug。

Redis 单节点故障

使用集群:一主,二从,三哨兵

主从存在的问题:

服务拿到锁后主节点挂了,数据还没同步到从节点,

从节点选举为主节点后,加锁成功,导致两个线程拿到一把锁,导致超卖

解决方案:red lock 红锁

使用 5 台 redis(无主从之分),服务需要拿到一以上的(>=3)的锁时才算加锁成功

尽量不使用偶数台 redis。

  1. 挂了一台没有加锁的怎么办,不对获取锁的业务线程产生影响,可以当他还是启动的

  2. 挂了一台加锁的(正在使用的)怎么办?延迟启动,如果挂了又立马启动,可能会导致其他线程拿到一半以上的锁,破坏了互斥条件,导致超卖。

    延迟启动: 至少等到加锁的业务线程结束后再启动挂掉的 redis

JVM 中 STW 导致 Redis 锁释放怎么办

STW 过程中 “看门狗”(即守护线程)不去续期,导致锁失效。此时别的线程拿到锁,同时操作产生问题

  1. 鸵鸟策略,不考虑这种情况,因为出现的概率极低
  2. 使用 ZK + MySQL 乐观锁 ZK key 的序号做 MySQL 的 version 字段

实际:好多公司只用一台 Redis

总结

  1. 单台服务器,使用 JVM 锁
  2. 多台服务器,分布式锁
    1. 使用 MySQL
    2. 使用 Redis
      1. 单台 Redis
      2. 主从 Redis(出现单点故障)
      3. 红锁 Red Lock
        1. 换掉 Redis:使用 ZK + MySQL 乐观锁
        2. 换掉 JVM

脚本宝典总结

以上是脚本宝典为你收集整理的分布式系统学习全部内容,希望文章能够帮你解决分布式系统学习所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。