在分布式场景下,我们不同的业务功能放在不同的服务器上,而这些不同的业务可能会去操作同一个数据库资源,如果这时候大并发进来,就可能会出现同时操作共享资源的情况,为了避免这种情况发生,我们想到的是加锁,如果这时候是在各自服务器的代码实现上加本地锁能够解决这种问题吗?
答案当然是不能,来分析一下上述场景:
整个系统的业务1、业务2、业务3放在不同的服务器上构成了分布式场景,这三个业务底层都会去操作同一个数据库,现在对这三个业务的代码实现上加上本地锁,即synchronized、ReentrantLock等,此时100个并发请求进入这个系统,假设到达这三个服务器的请求量分别为30、30、40,由于三个业务是在不同的服务器上,所以对于它们而言使用本地锁锁住的不会是同一个对象,因此能进入业务1的请求只有1条,进入业务2的请求也有1条,同理进入业务3的请求也是1条,最终数据库会同时接收到3条访问请求,出现了同时操作共享资源的情况。
分布式锁是怎么解决这种问题的呢?就好比在这三个业务外边放一把大锁,这把锁也就脱离了“本地”的概念,三个服务器都可以去这个公共的地方抢这把锁,谁抢到了这把锁谁就可以去执行业务操作数据库,其他业务只能等待。
二、redis为什么可以实现分布式锁?
上面所提到的公共的地方可以用redis代替,也就是说所有的服务器都连接上同一个redis,redis是一个缓存数据库,我们通过往这个缓存中存取标记的手段达到锁的获取和释放的效果,说到这里就不得不引出这个关键的命令了:set NX,它是一个原子性的命令,它能保证如果缓存中如果没有这个key时才会对其进行设置,如果