- 通过 Redis 分发 ID 号段实现分布式生成
- 通过 Hashid 算法实现固定长度的 62 位编码的 ID 字符串,可用于短链 Key 的生成
import org.hashids.Hashids;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
@Service
public class SignalSenderService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Value("${signal.sender.hash.id.salt:N7Y16ioS}")
private String hashIdSalt;
private final Hashids hashids = new Hashids(hashIdSalt, 6);
private static final String SIGNAL_SENDER_INCR_KEY = "signal.sender.incr.key";
@Value("${signal.sender.range.batch:10000}")
private int rangBatch;
private AtomicLong current;
private Long end = 0L;
@PostConstruct
public void init() {
this.range();
}
public List<String> getBase62Id(Integer num) {
if (Objects.isNull(num) || num < 1) {
return Collections.emptyList();
}
List<String> result = new ArrayList<>(num);
for (int i = 0; i < num; i++) {
result.add(this.getBase62Id());
}
return result;
}
public String getBase62Id() {
return this.encode(this.getId());
}
public List<Long> getId(Integer num) {
if (Objects.isNull(num) || num < 1) {
return Collections.emptyList();
}
List<Long> result = new ArrayList<>(num);
for (int i = 0; i < num; i++) {
result.add(this.getId());
}
return result;
}
public synchronized Long getId() {
while (true) {
long result = current.getAndIncrement();
if (result > end) {
this.range();
} else {
return result;
}
}
}
private synchronized void range() {
if (Objects.nonNull(this.current) && this.current.get() <= this.end) {
return;
}
this.end = redisTemplate.opsForValue().increment(SIGNAL_SENDER_INCR_KEY, rangBatch);
this.current = new AtomicLong(this.end - rangBatch + 1);
}
public String encode(Long id) {
return this.hashids.encode(id);
}
public Long decode(String key) {
return hashids.decode(key)[0];
}
}