阿里面经

一、分布式锁问题:
1、B的锁被A给释放了
 场景:A、B两个线程来尝试给key myLock加锁,A线程先拿到锁(假如锁3秒后过期),业务未执行完成,B获取到锁,A释放锁(此时A锁因为过期时间已经释放,实际释放的是B锁)
 解决方案:在每个线程加锁时要带上自己独有的value值来标识,只释放指定value的key,否则就会出现释放锁混乱的场景
2、锁过期了,业务还没执行完
 解决方案:锁自动续期,redisson客户端,redisson在加锁成功后,会注册一个定时任务监听这个锁,每隔10秒就去查看这个锁,如果还持有锁,就对过期时间进行续期。默认过期时间30秒。这个机制也被叫做:“看门狗”,watchDog
3、redis主从复制的坑
redis cluster集群环境下,A客户端加锁(根据路由选择一台master),加锁成功后,master会把key异步复制给slave节点,如果此时master节点宕机,为保证集群可用性,会进行主备切换
,slave变为了redis master。B客户端在新的master节点上加锁成功,而A客户端也以为自己还是成功加了锁的。
此时就会导致同一时间内多个客户端对一个分布式锁完成了加锁,导致各种脏数据的产生。
 解决方案,目前看还没有什么根治的方法,只能尽量保证机器的稳定性,减少发生此事件的概率。
 

二、MySQL数据同步的一致性问题

参考:https://youzhixueyuan.com/database-master-slave-synchronization.html

1.半同步复制

办法就是等主从同步完成之后,等主库上的写请求再返回,这就是常说的“半同步复制”

MySQL半同步复制

MySQL的Replication默认是一个异步复制的过程,从MySQL5.5开始,MySQL以插件的形式支持半同步复制,我先谈下异步复制,这样可以更好的理解半同步复制。

1)异步复制

MySQL默认的复制是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从库上。

2)半同步复制

介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay
log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。

 

半同步复制原理:

  •  事务在主库写完binlog后需要从库返回一个已接受,才放回给客户端
  •  mysql5.5版本以后,以插件的形式存在,需要单独安装
  •  确保事务提交后binlog至少传输到一个从库
  •  不保证从库应用完成这个事务的binlog
  •  性能有一定的降低
  •  网络异常或从库宕机,卡主库,直到超时或从库恢复

该方案优点:

利用数据库原生功能,比较简单

该方案缺点:

主库的写请求时延会增长,吞吐量会降低

 

 

2.数据库中间件

 

流程:

1)所有的读写都走数据库中间件,通常情况下,写请求路由到主库,读请求路由到从库

2)记录所有路由到写库的key,在主从同步时间窗口内(假设是500ms),如果有读请求访问中间件,此时有可能从库还是旧数据,就把这个key上的读请求路由到主库。

3)在主从同步时间过完后,对应key的读请求继续路由到从库。

相关的中间件有:

1)canal:是阿里巴巴旗下的一款开源项目,纯Java开发,基于数据库增量日志解析,提供增量数据订阅&消费,目前主要支持了MySQL。

2)otter:也是阿里开源的一个分布式数据库同步系统,尤其是在跨机房数据库同步方面,有很强大的功能。它是基于数据库增量日志解析,实时将数据同步到本机房或跨机房的mysql/oracle数据库。

两者的区别在于:

otter目前嵌入式依赖canal,部署为同一个jvm,目前设计为不产生Relay Log。

otter目前允许自定义同步逻辑,解决各类需求。

该方案优点

能保证绝对一致

该方案缺点:

数据库中间件的成本较高

你可能感兴趣的:(面试)