介绍
在以前,服务基本上都是处于一个进程中,在同一进程中的不同线程要访问和操作同一个资源,可以使用编程语言提供的同步锁机制;但现在那些庞大的服务都已经被服务化和分布式化了,这样需要操作一个资源的可能就是一个个服务进程了,因为是进程和进程的关系,进程之间的编程语言也有可能不一样,导致之前在同一进程中可以使用的同步锁机制就失效了。
如果这个共享在服务间的资源提供的所有操作都是原子操作,而且各个服务也不会进行原子操作的组合使用(当然这是不可能的),那其实要不要锁资源都无所谓,毕竟所有操作都是原子性的。这里要说这个原子操作的组合使用,为何会出现问题呢?其实显而易见,在两个原子操作之间,如果没有锁机制,就有可能别的服务插入进来,导致资源出现不一致。
这里又要解释一下什么是原子操作?其实就是从一个操作执行开始,到这个操作执行结束,都不会出现第三者插入进来执行别的操作的情况。
比如x+1这个操作是否是原子性的呢?可以说是的,它的确是原子性的因为它只有一步,别人没办法插入进来;
但是如果是x=x+1呢?这个就不是原子性的了,x=x+1中包含了两步操作:一个是x+1,一个是把x+1的结果赋值给x,两部操作,中间就容易有人插入。
所以要保证原子性,可以从两点入手,其一就是保证你的操作只有一步(很不现实);其二,保证你在进行多步操作期间,不会有人插足。
所以才会出现锁这种东西,将自己要进行操作的资源锁定起来,其他人想来操作都会失败,这样就能保证操作的原子性。
以前可以使用编程语言提供的线程间的锁机制,但现在是进程和进程间存在抢占资源的情况,就必须要有进程和进程之间的锁机制了,这个就是分布式锁。
而Redis可以提供这种分布式锁的能力。当然除了Redis外,还有其他的三方件可以提供这种能力,比如zookeeper。
在Redis中,可以使用setnx命令和del命令来获取锁和释放锁。
set name value命令是创建一个string的键值对,而setnx name value是如果name不存在,则创建这个键值对,否则不创建。通过这个命令,相当于多个服务去抢着创建自己的锁,先到先得,后到的就只能等了。而使用del 命令删除掉这个锁之后,其他服务就可以再次尝试创建自己的锁。
演示
下面准备使用三个服务来进行演示,其中一个服务提供一个资源增删改查的接口,另外两个服务来调用这些接口操作资源,同时通过使用Redis分布式锁机制,来保证操作的原子性。
第一个服务是提供了资源操作接口的服务,服务的创建可以参考这篇博文,使用SpringBoot快速搭建一个微服务,并提供restful风格的接口:
https://www.cnblogs.com/wuyizuokan/p/11117294.html