前言
前面也说了,
学习Netty的基础,那就是Nio,昨天我们简单的过了一下BIO,这是我们Java IO的基础,在JDK1.4之前的主要的io方式。
今天开始,我们就开始把NIO的一些东西了解清楚,之后才是Netty ,
因为我们的Netty是基础NIO的一个框架嘛,下面就来详细说说。
一、背景
我们日常在电商网站购物时经常会遇到一些高并发的场景,例如电商 App 上经常出现的秒杀活动、限量优惠券抢购,还有我们去哪儿网的火车票抢票系统等,这些场景有一个共同特点就是访问量激增,虽然在系统设计时会通过限流、异步、排队等方式优化,但整体的并发还是平时的数倍以上,为了避免并发问题,防止库存超卖,给用户提供一个良好的购物体验,这些系统中都会用到锁的机制。
对于单进程的并发场景,可以使用编程语言及相应的类库提供的锁,如 Java 中的 synchronized 语法以及 ReentrantLock 类等,避免并发问题。
如果在分布式场景中,实现不同客户端的线程对代码和资源的同步访问,保证在多线程下处理共享数据的安全性,就需要用到分布式锁技术。
那么何为分布式锁呢?分布式锁是控制分布式系统或不同系统之间共同访问共享资源的一种锁实现,如果不同的系统或同一个系统的不同主机之间共享了某个资源时,往往需要互斥来防止彼此干扰保证一致性。
一个相对安全的分布式锁,一般需要具备以下特征:
- 互斥性。互斥是锁的基本特征,同一时刻锁只能被一个线程持有,执行临界区操作。
- 超时释放。通过超时释放,可以避免死锁,防止不必要的线程等待和资源浪费,类似于 MySQL 的 InnoDB 引擎中的 innodblockwait_timeout 参数配置。
- 可重入性。一个线程在持有锁的情况可以对其再次请求加锁,防止锁在线程执行完临界区操作之前释放。
- 高性能和高可用。加锁和释放锁的过程性能开销要尽可能的低,同时也要保证高可用,防止分布式锁意外失效。
可以看出实现分布式锁,并不是锁住资源就可以了,还需要满足一些额外的特征,避免出现死锁、锁失效等问题。
二、分布式锁的实现方式
目前实现分布式锁的方式有很多,常见的主要有:
- Memcached 分布式锁
利用 Memcached 的 add 命令。此命令是原子性操作,只有在 key 不存在的情况下,才能 add 成功,也就意味着线程得到了锁。
- Zookeeper 分布式锁
利用 Zookeeper 的顺序临时节点,来实现分布式锁和等待队列。ZooKeeper 作为一个专门为分布式应用提供方案的