内容摘自黑马
1. 加入依赖: zookeeper的java客户端
<!-- curator ZK 客户端 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
2. 配置文件
自己随便弄个位置, 可以放在application.yml, 也可以放在其它配置文件等
# zk host地址
zk.host=192.168.220.145:2181
# zk自增存储node
zk.sequence-path=/heima-leadnews/sequence/
3. 枚举类封装
public enum ZkSequenceEnum {
AP_LIKES,AP_READ_BEHAVIOR,AP_COLLECTION,AP_USER_FOLLOW,AP_USER_FAN
}
4. 序列封装
public class ZkSequence {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(500, 3);
DistributedAtomicLong distAtomicLong;
public ZkSequence(String sequenceName, CuratorFramework client){
distAtomicLong = new DistributedAtomicLong(client,sequenceName,retryPolicy);
}
/**
* 生成序列
* @return
* @throws Exception
*/
public Long sequence() throws Exception{
AtomicValue<Long> sequence = this.distAtomicLong.increment();
if(sequence.succeeded()){
return sequence.postValue();
}else{
return null;
}
}
}
5. Client封装
@Setter
@Getter
public class ZookeeperClient {
private static Logger logger = LoggerFactory.getLogger(ZookeeperClient.class);
private String host;
private String sequencePath;
// 重试休眠时间
private final int SLEEP_TIME_MS = 1000;
// 最大重试1000次
private final int MAX_RETRIES = 1000;
//会话超时时间
private final int SESSION_TIMEOUT = 30 * 1000;
//连接超时时间
private final int CONNECTION_TIMEOUT = 3 * 1000;
//创建连接实例
private CuratorFramework client = null;
// 序列化集合
private Map<String, ZkSequence> zkSequence = Maps.newConcurrentMap();
public ZookeeperClient(String host,String sequencePath){
this.host = host;
this.sequencePath = sequencePath;
}
@PostConstruct
public void init() throws Exception{
this.client = CuratorFrameworkFactory.builder()
.connectString(this.getHost())
.connectionTimeoutMs(CONNECTION_TIMEOUT)
.sessionTimeoutMs(SESSION_TIMEOUT)
.retryPolicy(new ExponentialBackoffRetry(SLEEP_TIME_MS, MAX_RETRIES)).build();
this.client.start();
this.initZkSequence();
}
public void initZkSequence(){
ZkSequenceEnum[] list = ZkSequenceEnum.values();
for (int i = 0; i < list.length; i++) {
String name = list[i].name();
String path = this.sequencePath+name;
ZkSequence seq = new ZkSequence(path,this.client);
zkSequence.put(name,seq);
}
}
/**
* 生成SEQ
* @param name
* @return
* @throws Exception
*/
public Long sequence(ZkSequenceEnum name){
try {
ZkSequence seq = zkSequence.get(name.name());
if (seq != null) {
return seq.sequence();
}
}catch (Exception e){
logger.error("获取[{}]Sequence错误:{}",name,e);
}
return null;
}
}
6. config封装
/**
* 自动化配置核心数据库的连接配置
*/
@Setter
@Getter
@Configuration
@ConfigurationProperties(prefix="zk")
@PropertySource("classpath:zookeeper.properties")
public class ZkConfig {
String host;
String sequencePath;
/**
* 这是最快的数据库连接池
* @return
*/
@Bean
public ZookeeperClient zookeeperClient(){
return new ZookeeperClient(this.host,this.sequencePath);
}
}
7. Sequences封装
@Component
public class Sequences {
@Autowired
private ZookeeperClient client;
public Long sequenceApLikes(){
return this.client.sequence(ZkSequenceEnum.AP_LIKES);
}
public Long sequenceApReadBehavior(){
return this.client.sequence(ZkSequenceEnum.AP_READ_BEHAVIOR);
}
public Long sequenceApCollection(){
return this.client.sequence(ZkSequenceEnum.AP_COLLECTION);
}
public Long sequenceApUserFollow(){return this.client.sequence(ZkSequenceEnum.AP_USER_FOLLOW);}
public Long sequenceApUserFan(){return this.client.sequence(ZkSequenceEnum.AP_USER_FAN);}
}
8. 使用方法
// 第一步,注入Sequences
@Autowired
private Sequences sequences;
// 第二步,在方法中调用生成
alb.setId(sequences.sequenceApCollection());
9 扩展
如后期需要新增ZkSequence自增表,可参考以下操作步骤,快速实现:
-
在ZkSequenceEnum中定义对应的枚举项,规范要求枚举项与物理表名一致且大写
-
在Sequences中定义对应的调用方法,规范要求方法由sequence前缀+驼峰表名组成