目录
分布式锁
实现方式
分布式锁场景如何选择Redis和zookeeper
用InterProcessMutex实现分布式锁
zookeeper实现注册中心
分布式锁
实现方式
- 数据库唯一索引
- Redis的setnx
- Zookeeper创建临时节点及监听机制
- Zookeeper创建临时有序节点
分布式锁场景如何选择Redis和zookeeper
一致性:
- ZooKeeper是一个分布式协调服务,它保证了强一致性。这意味着在ZooKeeper中创建的节点的状态是全局可见的,并且所有节点都将在相同的时间看到相同的数据。这种一致性可以确保分布式锁的可靠性。
- Redis是一个支持分布式的缓存和数据存储,但其一致性较弱。Redis的主从复制模式可能会导致一些短暂的不一致,这可能影响分布式锁的可靠性。
性能:
- Redis通常被认为是一个高性能的内存数据库,适用于需要快速读写操作的场景。如果你的系统对性能要求较高,而且可以容忍一些短暂的不一致,那么使用Redis可能是个不错的选择。
- ZooKeeper的性能可能不如Redis那么高,因为它的设计目标更侧重于提供强一致性和可靠性。
部署和维护:
- Redis相对较简单,容易部署和维护。你只需要关注Redis节点的可用性和性能。
- ZooKeeper需要维护一个ZooKeeper集群,确保其正常运行可能需要更多的配置和管理。
用InterProcessMutex实现分布式锁
1. 引入curator依赖
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.1.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
2. java代码
public class CuratorLock {
private final static String CLUSTER_CONNECT_STR="192.168.6.128:2181,192.168.6.128:2182,192.168.6.128:2183";
private static CuratorFramework client= CuratorFrameworkFactory.builder().connectString(CLUSTER_CONNECT_STR)
.retryPolicy(new ExponentialBackoffRetry(100,1)).build();
static {
client.start();
}
private static final InterProcessMutex lock = new InterProcessMutex(client,"/curator_lock");
public static void main(String[] args) throws Exception {
int count = 0;
// 加锁
lock.acquire();
try {
// 执行业务逻辑
count++;
} finally {
// 解锁
lock.release();
}
}
}
zookeeper实现注册中心
1. 引入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>21</java.version>
<spring-boot.version>3.2.1</spring-boot.version>
<spring-cloud.version>2023.0.0</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- zookeeper client -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.8.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2. 修改配置application.yml
spring:
cloud:
zookeeper:
connect-string: 192.168.6.128:2181,192.168.6.128:2182,192.168.6.128:2183
discovery:
instance-host: 127.0.0.1
application:
name: user-service
server:
port: 8081
3. 整合feign
@FeignClient(name = "order-service")
public interface OrderFeign {
@GetMapping("/order/findById")
String findOrder(@RequestParam("id") String id);
}
@RequestMapping("/user")
@RestController
public class UserController {
@Autowired
private OrderFeign orderFeign;
@GetMapping("/findOrder")
public String findOrder() {
return orderFeign.findOrder("5");
}
}
4. zookeeper会生成对应应用节点
5. 访问接口, 验证User服务调Order服务