import java.util.Stack;
public class MathUtils {
private static char[] charSet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
/**
* 将10进制转化为62进制
*
* @param number
* @return
*/
public static String _10_to_62(long number) {
Long rest = Math.abs(number);
Stack<Character> stack = new Stack<Character>();
StringBuilder result = new StringBuilder(0);
while (rest != 0) {
stack.add(charSet[new Long((rest - (rest / 62) * 62)).intValue()]);
rest = rest / 62;
}
for (; !stack.isEmpty(); ) {
result.append(stack.pop());
}
String finalResult = result.toString();
// 补0
// if (result.length() < 6) {
// finalResult = "000000" + result.toString();
// finalResult = finalResult.substring(finalResult.length() - 6);
// }
return finalResult;
}
/**
* 将62进制转换成10进制数
*
* @param ident62
* @return
*/
private static String convertBase62ToDecimal(String ident62) {
int decimal = 0;
int base = 62;
int keisu = 0;
int cnt = 0;
byte ident[] = ident62.getBytes();
for (int i = ident.length - 1; i >= 0; i--) {
int num = 0;
if (ident[i] > 48 && ident[i] <= 57) {
num = ident[i] - 48;
} else if (ident[i] >= 65 && ident[i] <= 90) {
num = ident[i] - 65 + 10;
} else if (ident[i] >= 97 && ident[i] <= 122) {
num = ident[i] - 97 + 10 + 26;
}
keisu = (int) java.lang.Math.pow((double) base, (double) cnt);
decimal += num * keisu;
cnt++;
}
return String.format("%08d", decimal);
}
}
使用 _10_to_62 方法传入一个数字就可以生成一个有序的字符串(传入的数字递增就可以实现无限不重复)
常用于生成短链接
生成短链思路
使用redis 集合(Set)储存生成的短链(短链池),每次使用一条就POP出来,数据库记录生成短链的最大值(_10_to_62 方法传入的数字的最大值), 定时检查redis 的短链池少于多少条就再往短链池中添加数据(_10_to_62 方法传入的数字由数据库记录最大值递增)
短链生产代码
import com.xxx.service.ShortUrlDataSupportService;
import com.xxx.utils.MathUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
@EnableScheduling
@Slf4j
public class RedisKeyPoolGenerateTasks {
@Autowired
ShortUrlDataSupportService redisDao;
// 短链池的缓存名
private static final String REDIS_POOL_KEY = "DWZ:URLPOOL";
/**
* 定时任务 5分钟执行一次
*/
@Scheduled(fixedDelay = 5000)
public void poolKeyCheckTask() {
//短链池 小于10万条短链
while (redisDao.getSize(REDIS_POOL_KEY) < 10000000) {
// 每次生成10万条短链
generatePoolKeys(100000);
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void generatePoolKeys(long count) {
// 获取数据库保存的短链最大值
Long maxNum = shortUrlPoolConfigMapper.readPoolMaxNum();
long toNum = maxNum + count;
List<String> addToRedis = new ArrayList<>();
for (long begin = maxNum + 1; begin < toNum;
begin++) {
// 每 1000条保存一次
if (begin % 1000 == 0) {
// 更新数据库保存的短链最大值
shortUrlPoolConfigMapper.updatePoolMaxNum(begin);
redisDao.add(REDIS_POOL_KEY, addToRedis);
addToRedis = new ArrayList<>();
log.info("import to pool, current no is {}", begin);
}
addToRedis.add(MathUtils._10_to_62(begin));
}
// 更新数据库保存的短链最大值
shortUrlPoolConfigMapper.updatePoolMaxNum(toNum);
// 将短链插入redis
redisDao.add(REDIS_POOL_KEY, addToRedis);
}
}
redisDao 类
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Component
public class ShortUrlDataSupportService {
@Resource( name= "DwzPool")
private RedisTemplate<String, Object> dwzPoolRedisTemplate;
@Resource( name = "SeqGenerator")
RedisTemplate seqRedisTemplate;
/**
* 新增一个 sadd
*
* @param key
* @param value
*/
public void add(String key, String value) {
dwzPoolRedisTemplate.opsForSet().add(key, value);
}
/**
* 新增一个 sadd
*
* @param key
* @param values
*/
public void add(String key, List<String> values) {
dwzPoolRedisTemplate.opsForSet().add(key, values.toArray());
}
/**
* 随机取一个
*
* @param key
*/
public String getOne(String key) {
return (String)dwzPoolRedisTemplate.opsForSet().pop(key);
}
/**
* 随机取一个
*
* @param key
*/
public long getSize(String key) {
return dwzPoolRedisTemplate.opsForSet().size(key);
}
/**
* @Description: 获取自增长值
* @param key key
* @return
*/
public Long getIncr(String key) {
RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, seqRedisTemplate.getConnectionFactory());
Long increment = entityIdCounter.getAndIncrement();
entityIdCounter.persist();
return increment;
}
/**
* @Description: 初始化自增长值
* @param key key
* @param value 当前值
*/
public void setIncr(String key, int value) {
RedisAtomicLong counter = new RedisAtomicLong(key, seqRedisTemplate.getConnectionFactory());
counter.set(value);
counter.expire(0, TimeUnit.SECONDS);
}
}
Q.E.D.