Redis實(shí)戰(zhàn)(2)-數(shù)據(jù)結(jié)構(gòu)之字符串String實(shí)戰(zhàn)之存儲(chǔ)對(duì)象

作者: 修羅debug
版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 by-sa 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明。



摘要:在Redis眾多數(shù)據(jù)結(jié)構(gòu)當(dāng)中,字符串String可以說是其中比較常見、應(yīng)用比較頻繁的一種了,本文我們將介紹數(shù)據(jù)類型~字符串String 在命令行的簡(jiǎn)單使用及其在實(shí)際業(yè)務(wù)場(chǎng)景中的應(yīng)用與代碼實(shí)戰(zhàn),其中應(yīng)用場(chǎng)景為“存儲(chǔ)前端門戶網(wǎng)站的商品詳情信息”,從而減少數(shù)據(jù)庫DB的訪問頻率,提高接口的響應(yīng)速率!

內(nèi)容:緩存中間件Redis擁有多種豐富的數(shù)據(jù)結(jié)構(gòu),字符串String就是其中比較常見而且應(yīng)用相當(dāng)廣泛的一種,下面我們將基于前文整合搭建的SpringBoot2.0+Redis的項(xiàng)目為奠基,從兩個(gè)方面進(jìn)行介紹,即簡(jiǎn)單的命令行實(shí)際的應(yīng)用場(chǎng)景+代碼實(shí)戰(zhàn)!

(一)Redis命令行界面實(shí)操“數(shù)據(jù)類型String”

(1)由于Debug本地機(jī)子是windows系統(tǒng),故而為了可以在本地windows操作系統(tǒng)的機(jī)子使用Redis命令行,我們需要前往github下載一個(gè)windows版的redis綠色安裝工具包(如果是mac或者linux,則直接跳過此步驟),為了方便大家下載,我就直接提供地址給大家下載了(鏈接:https://pan.baidu.com/s/1o30jZZ9Rb5ZzR2iulQF9JA 提取碼:isj0)

下載完成之后,解壓到?jīng)]有中文名稱的磁盤目錄下,如下圖所示:


其中,最主要的文件當(dāng)屬redis-server.exe、redis-cli.exe以及另外兩個(gè)用于數(shù)據(jù)持久化的rdb和aof文件,雙擊redis-server.exe,成功出現(xiàn)如下的界面即代表redis已經(jīng)成功在你本地運(yùn)行起來了:


(2)下面,我們寫兩個(gè)簡(jiǎn)單的命令(即如何往Redis存入一個(gè)Key,以及如何從Redis中獲取該Key對(duì)應(yīng)的值),簡(jiǎn)單的感受一下字符串String在Redis命令行界面下的操作,如下圖所示:


是不是感覺很簡(jiǎn)單???哈哈,本來就是如此!除此之外,還可以在RedisDesktopManager工具查看該Key的具體值!下面我進(jìn)入重頭戲,即如何將Redis的這些特性應(yīng)用到實(shí)際的項(xiàng)目、實(shí)際的業(yè)務(wù)場(chǎng)景中去呢!


(二)String典型應(yīng)用場(chǎng)景代碼實(shí)戰(zhàn)

(1)業(yè)務(wù)場(chǎng)景介紹:下面我們以“訪問前端門戶網(wǎng)站商品信息”為業(yè)務(wù)場(chǎng)景,在后端管理平臺(tái)添加“熱門商品信息”時(shí)也順便將其塞入緩存Redis中,之后前端門戶網(wǎng)站在獲取該商品詳情時(shí)直接走緩存Redis查詢,而不走數(shù)據(jù)庫DB查詢,在某種情況下(比如雙11、雙12的熱銷商品),可以緩解數(shù)據(jù)庫的訪問壓力,降低DB的負(fù)載!

(2)我們首先開發(fā)一個(gè)Controller,用于添加熱門商品信息、并將其塞入緩存Redis中,除此之外,還開發(fā)了前端門戶網(wǎng)站訪問該熱門商品詳情信息的請(qǐng)求方法,其完整的源碼如下所示:

/**
* 字符串String實(shí)戰(zhàn)-商品詳情存儲(chǔ)
* @Author:debug (SteadyJack)
* @Link: weixin-> debug0868 qq-> 1948831260
* @Date: 2019/10/29 20:58
**/
@RestController
@RequestMapping("string")
public class StringController {

private static final Logger log= LoggerFactory.getLogger(StringController.class);

@Autowired
private StringService stringService;

//添加熱門商品
@RequestMapping(value = "put",method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
public BaseResponse put(@RequestBody @Validated Item item, BindingResult result){
if (result.hasErrors()){
return new BaseResponse(StatusCode.InvalidParams);
}
BaseResponse response=new BaseResponse(StatusCode.Success);
try {
log.info("--商品信息:{}",item);

stringService.addItem(item);
}catch (Exception e){
log.error("--字符串String實(shí)戰(zhàn)-商品詳情存儲(chǔ)-添加-發(fā)生異常:",e.fillInStackTrace());
response=new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());
}
return response;
}

//獲取熱門商品詳情
@RequestMapping(value = "get",method = RequestMethod.GET)
public BaseResponse get(@RequestParam Integer id){
BaseResponse response=new BaseResponse(StatusCode.Success);
try {
response.setData(stringService.getItem(id));

}catch (Exception e){
log.error("--字符串String實(shí)戰(zhàn)-商品詳情存儲(chǔ)-添加-發(fā)生異常:",e.fillInStackTrace());
response=new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());
}
return response;
}
}

(3)其中,stringService 顧名思義,即為實(shí)現(xiàn)業(yè)務(wù)邏輯的真正實(shí)現(xiàn)類!其完整源代碼如下所示:  

/**
* @Author:debug (SteadyJack)
* @Link: weixin-> debug0868 qq-> 1948831260
* @Date: 2019/10/29 21:05
**/
@Service
public class StringService {

private static final Logger log= LoggerFactory.getLogger(StringService.class);

@Autowired
private ItemMapper itemMapper;

@Autowired
private StringRedisService redisService;

@Autowired
private ObjectMapper objectMapper;


//添加商品
@Transactional(rollbackFor = Exception.class)
public Integer addItem(Item item) throws Exception{
item.setCreateTime(new Date());
item.setId(null);
itemMapper.insertSelective(item);
Integer id=item.getId();

//保證緩存-數(shù)據(jù)庫雙寫的一致性
if (id>0){
redisService.put(id.toString(),objectMapper.writeValueAsString(item));
}
return id;
}

//獲取商品
public Item getItem(Integer id) throws Exception{
Item item=null;
if (id!=null){
if (redisService.exist(id.toString())){
String result=redisService.get(id.toString()).toString();
log.info("---string數(shù)據(jù)類型,從緩存中取出來的value:{}",result);
if (StrUtil.isNotBlank(result)){
item=objectMapper.readValue(result,Item.class);
}
}else{
log.info("---string數(shù)據(jù)類型,從數(shù)據(jù)庫查詢:id={}",id);

item=itemMapper.selectByPrimaryKey(id);
if (item!=null){
redisService.put(id.toString(),objectMapper.writeValueAsString(item));
}
}
}
return item;
}
}

值得一提的是:

A.我們?cè)?“將熱門商品添加進(jìn)數(shù)據(jù)庫后 也往緩存中間件Redis塞了一份”,為了保證“雙寫一致性”,我們的做法是:“先保證成功數(shù)據(jù)庫,之后再往緩存Redis塞一份!”

B.“商品信息”是一個(gè)實(shí)體對(duì)象,為了能將該實(shí)體對(duì)象信息塞入Redis的String類型中,我們需要將其“序列化”,采用的Jackson的序列化機(jī)制,將該實(shí)體對(duì)象序列化為“Json格式的字符串”!

C. 在“獲取熱門商品詳情”時(shí),我們當(dāng)然是根據(jù)Key直接進(jìn)行獲取,但由于其結(jié)果是String類型的Json格式字符串常量值,故而我們需要將其“反序列化”,即同樣也是采用Jackson的反序列化機(jī)制,將其映射到一個(gè)Item實(shí)體對(duì)象中即可

(4)至此,我們的擼碼環(huán)節(jié)就全部完成了,最后,我們基于Postman進(jìn)行自測(cè)吧:

A.首先當(dāng)然是添加一個(gè)熱銷商品,商品信息為:

{
"code": "book50010",
"name": "分布式中間件實(shí)戰(zhàn)(Java版)"
}

發(fā)起Http請(qǐng)求以及得到的響應(yīng)信息如下圖所示:


采用Navicat查看數(shù)據(jù)庫中相應(yīng)表的信息記錄,如下圖所示:


B.最后,當(dāng)然在Postman是模擬“前端門戶網(wǎng)站”發(fā)起“獲取熱銷商品詳情”的請(qǐng)求啦,如下圖所示:


除此之外,還可以在RedisDesktopManager中查看該商品存儲(chǔ)在緩存中間件Redis的詳情:


好了,本篇文章我們就介紹到這里了,建議各位小伙伴一定要照著文章提供的樣例代碼擼一擼,只有擼過才能知道這玩意是咋用的,否則就成了“空談?wù)摺?!?duì)Redis相關(guān)技術(shù)棧以及實(shí)際應(yīng)用場(chǎng)景實(shí)戰(zhàn)感興趣的小伙伴可以前往Debug搭建的技術(shù)社區(qū)的課程中心進(jìn)行學(xué)習(xí)觀看:https://www.fightjava.com/web/index/course/detail/12 !

其他相關(guān)的技術(shù),感興趣的小伙伴可以關(guān)注底部Debug的技術(shù)公眾號(hào),或者加Debug的微信,拉你進(jìn)“微信版”的真正技術(shù)交流群!一起學(xué)習(xí)、共同成長(zhǎng)!

補(bǔ)充:

1、本文涉及到的相關(guān)的源代碼可以到此地址,check出來進(jìn)行查看學(xué)習(xí):

https://gitee.com/steadyjack/SpringBootRedis

2、目前Debug已將本文所涉及的內(nèi)容整理錄制成視頻教程,感興趣的小伙伴可以前往觀看學(xué)習(xí):https://www.fightjava.com/web/index/course/detail/12

3、關(guān)注一下Debug的技術(shù)微信公眾號(hào),最新的技術(shù)文章、課程以及技術(shù)專欄將會(huì)第一時(shí)間在公眾號(hào)發(fā)布哦!