????????說到redis大家都不陌生,其中包括:共有16個(gè)數(shù)據(jù)庫,默認(rèn)為第0個(gè)數(shù)據(jù)庫;數(shù)據(jù)以key-value鍵值的形式存儲;數(shù)據(jù)類型包括String、List、Hash、Set等,其中最常用的是字符串;是單線程的、基于內(nèi)存的,主要受內(nèi)存和網(wǎng)絡(luò)帶寬的影響… 這些都是基于Redis的基礎(chǔ)理論知識儲備。接下來我會通過開發(fā)中的StringRedisTemplate對象作為切入點(diǎn),說一說Redis在開發(fā)中的那些事兒。
1. jedis還是lettuce?
????????兩者都是redis的客戶端,對redis操作進(jìn)行了封裝。其中l(wèi)ettuce是內(nèi)部使用netty進(jìn)行網(wǎng)絡(luò)通信,性能很強(qiáng),jedis已經(jīng)停止更新了。lettuce相對于jedis在性能方面更為出色,jedis在單個(gè)線程中是線程安全的,功能上更加豐富,支持的數(shù)據(jù)類型更多。無論Springboot2.0以后默認(rèn)使用lettuce作為操作redis的客戶端,選擇jedis還是lettuce,都需要根據(jù)具體的業(yè)務(wù)需求和場景進(jìn)行評估和測試,以確定最適合的工具庫。兩者的分別使用如下:
pom依賴
jedis
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
lettuce
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
yaml配置
jedis
spring:
redis:
host: localhost
password:
port: 6379
timeout: 10s # 連接超時(shí)時(shí)間
jedis:
pool:
max-active: 1000 # 連接池最大連接數(shù)(使用負(fù)值表示沒有限制)
max-wait: -1 # 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒有限制)
max-idle: 10 # 連接池中的最大空閑連接
min-idle: 5 # 連接池中的最小空閑連接
lettuce
spring:
redis:
host: localhost
password:
port: 6379
timeout: 10s # 連接超時(shí)時(shí)間
lettuce:
pool:
max-active: 1000 # 連接池最大連接數(shù)(使用負(fù)值表示沒有限制)
max-wait: -1 # 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒有限制)
max-idle: 10 # 連接池中的最大空閑連接
min-idle: 5 # 連接池中的最小空閑連接
2. 字符串緩存
應(yīng)用場景1:基礎(chǔ)緩存
????????對于redis有90%的使用場景都是基于String作為基礎(chǔ)緩存使用的,對于經(jīng)常使用的并且修改頻率較低的數(shù)據(jù)存儲在Redis緩存中,可以大大提高系統(tǒng)性能和響應(yīng)速度,避免頻繁地從數(shù)據(jù)庫或其他后端服務(wù)讀取數(shù)據(jù)。對象、集合等數(shù)據(jù)也可以通JSON序列化成字符串進(jìn)行存儲,大大提升了系統(tǒng)的并發(fā)性能,節(jié)省系統(tǒng)資源的消耗。
存字符串、對象、集合到緩存中,redisTemplate.opsForValue().set(key, value)
//存普通字符串
redisTemplate.opsForValue().set("testKey", "123456");
//存某對象
Person person = getPerson(); //TODO 獲取到某個(gè)實(shí)例對象
redisTemplate.opsForValue().set("testObj", JSON.toJSONString(person));
//存某集合
List<Person> persons = getPersonList(); //TODO 獲取到某個(gè)實(shí)例集合
redisTemplate.opsForValue().set("testList", JSON.toJSONString(persons));
存入緩存中,有時(shí)效性,超時(shí)之后緩存自動刪除,redisTemplate.opsForValue().set(key, value, time)
//設(shè)置登錄token,30分鐘有效(第3個(gè)參數(shù)支持:天、小時(shí)、分鐘、秒等)
redisTemplate.opsForValue().set("token", "123456", Duration.ofMinutes(30));
從緩存中讀取數(shù)據(jù),數(shù)據(jù)為字符串,可按實(shí)際存入的值進(jìn)行序列化,redisTemplate.opsForValue().get(key)
//從緩存中獲取某對象
String s1 = redisTemplate.opsForValue().get("testObj");
Person person = JSON.parseObject(s1, Person.class);
//從緩存中獲取某集合
String s2 = redisTemplate.opsForValue().get("testList");
List<Person> persons = JSON.parseArray(s2, Person.class);
獲取緩存剩余時(shí)間,redisTemplate.getExpire(key)
//返回值為long值,單位是秒,如果是-1時(shí)代表的是永久保存
Long expire = redisTemplate.getExpire("testKey");
重置緩存時(shí)間,redisTemplate.expire(key, time, timeUnit)
//重置時(shí)間為2天
redisTemplate.expire("testKey", 2, TimeUnit.DAYS);
判斷是否存在,redisTemplate.hasKey(key)
Boolean b = redisTemplate.hasKey("testKey");
模糊匹配獲取所有的key值,redisTemplate.keys(“*”);
//獲取所有的key值
Set<String> keys = redisTemplate.keys("*");
//獲取所有的testKey*模糊的key值
Set<String> keys = redisTemplate.keys("testKey*");
刪除緩存,redisTemplate.delete(key)
redisTemplate.delete("testKey");
只是列了部分,還有multiSet、getRange、increment等方法都很實(shí)用
應(yīng)用場景2:重復(fù)提交驗(yàn)證
????????相同請求短時(shí)間內(nèi)請求多次過濾,尤其是用于重要表單信息提交、秒殺請求的應(yīng)用場景。在每次接收到請求時(shí),生成一個(gè)唯一的請求標(biāo)識(例如,可以使用請求的URL和參數(shù)進(jìn)行哈希計(jì)算),在Redis中使用請求標(biāo)識作為Key,將其存入到緩存中,設(shè)置一個(gè)合適的時(shí)間自動清理緩存中的過期請求標(biāo)識,避免占用過多內(nèi)存。這樣就可以實(shí)現(xiàn)用Redis有效地進(jìn)行接口重復(fù)請求的驗(yàn)證。
以下為請求重復(fù)驗(yàn)證工具類實(shí)例代碼文章來源:http://www.zghlxwxcb.cn/news/detail-745414.html
@Component
public class RequestValidator {
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 重復(fù)請求方法
* @param requestId 請求標(biāo)識
* @param validSecond 有效時(shí)間(單位:秒)
* @return true重復(fù) / false不重復(fù)
*/
public boolean isDuplicateRequest(String requestId, Long validSecond) {
String s = redisTemplate.opsForValue().get(requestId);
//緩存中取值不為空,證明是重復(fù)請求
if (StringUtils.isNotEmpty(s)) {
return true;
}
//緩存中取值為空,證明非重復(fù)請求,把請求標(biāo)識放入到緩存中
redisTemplate.opsForValue().set(requestId, "DUPLICATE_REQUEST", Duration.ofSeconds(validSecond));
return false;
}
}
3. List緩存
應(yīng)用場景:高并發(fā)場景
????????opsForList提供了一組簡單而直觀的方法來操作列表類型的數(shù)據(jù),如leftPushAll、rightPushAll等,這使得批量存儲變得非常方便,并且代碼更易讀,可以很好地支持高并發(fā)的場景。Redis的列表是按照插入的順序進(jìn)行存儲的,利用leftPushAll或rightPushAll方法進(jìn)行批量存儲時(shí),元素會按照給定的順序依次插入到列表中,可以確保存儲的順序是可控的。雖然opsForList提供了方便的批量存儲操作,但在實(shí)際使用時(shí)仍需考慮內(nèi)存消耗、網(wǎng)絡(luò)傳輸?shù)纫蛩?,存儲?shù)據(jù)過大如果來不及消費(fèi),就會造成系統(tǒng)內(nèi)存溢出導(dǎo)致服務(wù)器崩潰,存在數(shù)據(jù)丟失的風(fēng)險(xiǎn)。
? 具體怎么使用,在之前的文章中有介紹,在這里Java高并發(fā)之Redis批量提交數(shù)據(jù)庫文章來源地址http://www.zghlxwxcb.cn/news/detail-745414.html
到了這里,關(guān)于Redis那些事兒(一)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!