關(guān)注我,精彩文章第一時(shí)間推送給你
這里需求是創(chuàng)建每日的流水號(hào),例如:每向數(shù)據(jù)庫(kù)中添加一條數(shù)據(jù),其編號(hào)設(shè)置為yyyyMMdd0001昂儒、yyyyMMdd0002這樣的格式沟使,日期加后四位為當(dāng)日流水號(hào)委可,也就是當(dāng)日第幾個(gè)添加的數(shù)據(jù)。
- 為什么考慮使用redis呢腊嗡?
額着倾、redis的特性就不介紹了,反正本文也不是介紹redis怎么使用的...
簡(jiǎn)而言之燕少,為了顯示自己用過(guò)redis而用卡者,哈哈哈
- 這里docker啟動(dòng)redis遇到一個(gè)問(wèn)題,記錄一下
#創(chuàng)建容器的時(shí)候報(bào)錯(cuò)WARNING: IPv4 forwarding is disabled. Networking will not work.
#這個(gè)錯(cuò)導(dǎo)致連接不上redis客们,但是在容器內(nèi)部docker exec -it redis bash redis-cli能夠使用
#我啟動(dòng)redis容器的命令
docker run -d --privileged=true --restart=always -p 6379:6379 -v /usr/docker/redis/data:/data --name redis redis:latest redis-server --appendonly yes
#解決辦法
vim /usr/lib/sysctl.d/00-system.conf
#添加下面這行
net.ipv4.ip_forward=1
#重啟network
systemctl restart network
#刪除錯(cuò)誤的重啟重新執(zhí)行啟動(dòng)redis的命令
docker stop redis
docker rm redis
- 創(chuàng)建一個(gè)spring boot項(xiàng)目崇决,在pom.xml中引入如下依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--因?yàn)镾pringboot 2.0 中redis客戶端使用了Lettue, 其依賴于commons-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
- 配置application.yml連接redis
spring:
redis:
host: 192.168.16.128
port: 6379
# 連接超時(shí)時(shí)間(記得添加單位材诽,Duration)
timeout: 10000ms
# Redis默認(rèn)情況下有16個(gè)分片,這里配置具體使用的分片
# database: 0
lettuce:
pool:
# 連接池最大連接數(shù)(使用負(fù)值表示沒(méi)有限制) 默認(rèn) 8
max-active: 8
# 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒(méi)有限制) 默認(rèn) -1
max-wait: -1ms
# 連接池中的最大空閑連接 默認(rèn) 8
max-idle: 8
# 連接池中的最小空閑連接 默認(rèn) 0
min-idle: 0
- 創(chuàng)建redis操作類恒傻,這里主要利用的redis自增操作
@Component
@Slf4j
public class RedisCacheTemplate {
@Resource
private RedisTemplate<String, Object> redisTemplate;
/**
* @Title: incr
* @Description: 獲取redis自增序號(hào)
* @param key redis的 key值
* @param delta 自增的增量
* @return
*/
public long incr(String key, long delta, long time) {
try {
long l = redisTemplate.opsForValue().increment(key, delta);
if (time > 0) {
expire(key, time);
}
return l;
} catch (Exception e) {
log.error("redis獲取" + key + "失敗", e);
return -1;
}
}
/**
* @Title: expire
* @Description: 設(shè)置過(guò)期時(shí)間
* @param key
* @param time
* @return
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
log.error("redis設(shè)置" + key + "過(guò)期時(shí)間失敗", e);
return false;
}
}
}
- 把獲取到的redis自增的序號(hào)格式化成指定格式0001/0002/...
public class SequenceUtil {
private static final int DEFAULT_LENGTH = 3;
/**
* 將傳入的數(shù) seq 格式化成 length 位脸侥,不夠前邊補(bǔ) 0
* 如果 length < 3 則按照 3 算
* @param seq
* @param length
* @return
*/
public static String getSequence(long seq, int length) {
String str = String.valueOf(seq);
int len = str.length();
length = Math.max(length, DEFAULT_LENGTH);
if (len >= length) {
return str;
}
int rest = length - len;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < rest; i++) {
sb.append('0');
}
sb.append(str);
return sb.toString();
}
}
- 測(cè)試獲取到的yyyyMMdd0001格式的每日流水號(hào)
@SpringBootTest
@Slf4j
class DemoRedisApplicationTests {
private static final String SERIAL_NUM= "redis:serialNumber:";
@Autowired
private RedisCacheTemplate redisCacheTemplate;
@Test
void contextLoads() {
String currentDate = new SimpleDateFormat("yyyyMMdd").format(new Date());
String key = SERIAL_NUM + currentDate;
long incr = redisCacheTemplate.incr(key, 1, 86400);
//移位運(yùn)算符<<,左移幾位相當(dāng)于乘以2的幾次方, 1 << 2 = 4
String code = SequenceUtil.getSequence(incr, 1 << 2);
log.info(currentDate + code);
}
}
解釋一下:用redis:serialNumber:20200409這個(gè)作為redis的key去查找自增值盈厘,每次執(zhí)行加1
redis中的key-value將是這樣:
key value
redis:serialNumber:20200409 0001
redis:serialNumber:20200409 0002
...
直到下一天key變成了redis:serialNumber:20200410,value則會(huì)從0001開(kāi)始遞增
又因?yàn)槲以O(shè)置了redis的過(guò)期時(shí)間是86400秒 = 1天睁枕,所以過(guò)期的數(shù)據(jù)會(huì)自動(dòng)刪除
- 看一下控制臺(tái)的log日志
- 在執(zhí)行一次