天天看點

redis實戰_Redis實戰(11)-哈希Hash應用場景實戰之系統資料字典實時觸發緩存

前文我們已經介紹并實戰了Redis的資料類型哈希Hash的相關指令行及其對應的Java單元測試的實戰代碼,本文我們将以實際項目中典型的應用場景"系統資料字典子產品的實時觸發存儲"為案例,學以緻用,一起踐行哈希Hash在實際項目下的實戰應用,感受感受其在實際業務場景下的作用!

在前文我們已經簡單介紹了Redis的資料類型~哈希Hash的底層存儲結構,很顯然,哈希Hash跟其他的資料結構還是有諸多不同之處的。其他的據結構幾乎都是:Key-Value的存儲,而Hash則是:Key – [Field-Value] 的存儲,也就是說其他資料結構的Value一般是确切的值,而Hash的Value是一系列的鍵值對,通常我們是這樣子稱呼Hash的存儲的:大Key為實際的Key,小Key為Field,而具體的取值為Field對應的值。如下圖所示:

redis實戰_Redis實戰(11)-哈希Hash應用場景實戰之系統資料字典實時觸發緩存

說實在的,它的作用還是很強大的,特别是在存儲"同種對象類型"的資料清單時哈希Hash更能展現其優勢,除此之外,其最大的、直覺上的作用便是"減少了緩存Key的數量",而這主要還得得益于哈希Hash底層存儲資料時的存儲方式,如上圖所示!

接下來,我們便以實際項目開發中典型、常見的應用場景"系統資料字典實時觸發緩存存儲"為案例一起來踐行哈希Hash的作用。

對于"資料字典子產品",相信很多小夥伴都有所聽聞過,毫不誇張地講,幾乎每個項目都會有一個獨立的功能子產品,用于管理項目中各個業務子產品經常出現的"通用化、共性的、需要配置起來的東西",這些通用化的東西我們可以稱之為"資料字典",對于這些東西我們一般會單獨開辟一個獨立的功能子產品,如"資料字典子產品"進行單獨維護管理!

對于上面這個解釋,可能有些小夥伴有點懵,下面我們舉個栗子吧,比如經常可以見到的資料字典:"性别Sex~其取值可以有:男=1;女=0;未知=2";比如"支付狀态PayStatus~其取值可以有:1=未支付;2=已支付;3=已取消支付;4=已退款…";再比如"訂單稽核狀态ReviewStatus~1=已儲存/未稽核;2=已稽核;3=稽核成功;4=稽核失敗…"等等可以将其配置在"資料字典功能子產品"中将其維護起來,如下圖所示:

redis實戰_Redis實戰(11)-哈希Hash應用場景實戰之系統資料字典實時觸發緩存

看到上面這張圖,有些機靈的小夥伴可能會立即聯想到哈希Hash的底層存儲結構(本文開篇的那張圖),會發現驚人的相似,就拿"性别Sex"這一資料字典為例,它的取值為"Female-女性"、"Male-男性",這不就相當于哈希Hash的底層存儲結構嗎~Key=Sex,Field-Value對包含兩隊,分别是:Field=Female ~ Value=女性;Field=Male ~ Value=男性。

了解了這種資料關聯以及存儲之後,在後文的實戰中你就會發現代碼很容易了解,并且在實戰過後你或許會發出驚歎:"原來如此!"

除此之外,還有一種現象需要跟小夥伴分享分享,那就是"資料字典功能子產品"一旦配置好了某個"資料字典"之後,我們基本上會在好幾個月内都不會去重新修改它了,即有點"一勞永逸"的感覺!基于這個前提,我們可以将前端發起的請求實時通路資料庫DB的"資料字典" 優化為 基于緩存Redis的哈希Hash進行存儲與通路,并且這種存儲是"實時"的,那我們就開始吧!

(1)同樣的道理,工欲善其事,必先利其器,我們首先需要建立一個資料庫表sys_config用于存儲管理者添加的資料字典,其DDL如下所示:

CREATE TABLE `sys_config` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `type` varchar(100) CHARACTER SET utf8mb4 NOT NULL COMMENT '字典類型',  `name` varchar(100) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '字典名稱',  `code` varchar(100) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '選項編碼',  `value` varchar(100) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '選項取值',  `order_by` int(11) DEFAULT '1' COMMENT '排序',  `is_active` tinyint(4) DEFAULT '1' COMMENT '是否有效(1=是;0=否)',  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間',  PRIMARY KEY (`id`),  UNIQUE KEY `idx_type_code` (`type`,`code`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='字典配置表';
           

采用Mybatis的逆向工程生成該資料庫表的實體類Entity、Mapper操作接口及其對應的用于操作動态SQL的Mapper.xml,在這裡我們隻貼出SysConfigMapper接口中一個相當重要的方法吧:

//查詢目前資料字典表中所有可用的-已激活的資料字典清單List selectActiveConfigs();
           

其對應的動态SQL實作如下所示:

SELECT     FROM sys_config    WHERE is_active = 1    ORDER BY type, order_by ASC  
           

(2)緊接着,我們建立一個HashController,用于"新增資料字典"、"擷取緩存中所有的資料字典"以及"擷取特定編碼的資料字典取值清單",其完整的源代碼如下所示:

/**資料類型Hash散列-減少key存儲、類似于map-可以通過鍵取得其 “值” (可以對象清單...) * @Author:debug (SteadyJack) **/@[email protected]("hash")public class HashController extends AbstractController {    @Autowired    private HashService hashService;    //新增資料字典    @RequestMapping(value = "put",method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)    public BaseResponse put(@RequestBody @Validated SysConfig config, BindingResult result){        String checkRes= ValidatorUtil.checkResult(result);        if (StrUtil.isNotBlank(checkRes)){            return new BaseResponse(StatusCode.Fail.getCode(),checkRes);        }        BaseResponse response=new BaseResponse(StatusCode.Success);        try {            hashService.addSysConfig(config);        }catch (Exception e){            response=new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());        }        return response;    }    //擷取緩存中所有的資料字典    @RequestMapping(value = "get",method = RequestMethod.GET)    public BaseResponse get(){        BaseResponse response=new BaseResponse(StatusCode.Success);        try {            response.setData(hashService.getAll());        }catch (Exception e){            response=new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());        }        return response;    }    //擷取緩存中某個特定編碼下資料字典的取值清單    @RequestMapping(value = "get/type",method = RequestMethod.GET)    public BaseResponse getType(@RequestParam String type){        BaseResponse response=new BaseResponse(StatusCode.Success);        try {            response.setData(hashService.getByType(type));        }catch (Exception e){            response=new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());        }        return response;    }}
           

(3)其中,hashService下那幾個方法的實作邏輯即為真正要做的事情,其完整源代碼如下所示:

/**hash資料類型-service * @Author:debug (SteadyJack) * @Link: weixin-> debug0868 qq-> 1948831260 * @Date: 2019/10/31 21:07 **/@Servicepublic class HashService {    private static final Logger log= LoggerFactory.getLogger(HashService.class);    @Autowired    private SysConfigMapper sysConfigMapper;    @Autowired    private HashRedisService hashRedisService;    //TODO:添加資料字典及其對應的選項(field-value)    @Transactional(rollbackFor = Exception.class)    public Integer addSysConfig(SysConfig config) throws Exception{        int res=sysConfigMapper.insertSelective(config);        if (res>0){            //TODO:實時觸發資料字典的hash存儲            hashRedisService.cacheConfigMap();        }        return config.getId();    }    //TODO:取出緩存中所有的資料字典清單    public Map> getAll() throws Exception{        return hashRedisService.getAllCacheConfig();    }    //TODO:取出緩存中特定的資料字典清單    public List getByType(final String type) throws Exception{        return hashRedisService.getCacheConfigByType(type);    }}
           

(4)而hashService中實作資料字典的實時存取又是交給了HashRedisService相應的方法邏輯進行處理,其對應的完整源代碼如下所示:

至此,我們已經完成了哈希Hash典型應用場景"系統資料字典的實時存取"的代碼實戰了,相應的代碼的含義我們也在代碼中做了相應的注釋!如果有疑問的地方,各位小夥伴可以加Debug的聯系方式進行交流(代碼中就有我的交流聯系方式哦!),下面我們基于Postman進行一波測試吧!

A.首先是往資料庫中已有的某個資料字典添加某些具體的取值清單(Field-Value),如下3張圖所示:

redis實戰_Redis實戰(11)-哈希Hash應用場景實戰之系統資料字典實時觸發緩存
redis實戰_Redis實戰(11)-哈希Hash應用場景實戰之系統資料字典實時觸發緩存
redis實戰_Redis實戰(11)-哈希Hash應用場景實戰之系統資料字典實時觸發緩存

B.最後是往資料庫中添加一個全新的資料字典及其對應的取值清單(Field-Value),如下3張圖所示:

redis實戰_Redis實戰(11)-哈希Hash應用場景實戰之系統資料字典實時觸發緩存
redis實戰_Redis實戰(11)-哈希Hash應用場景實戰之系統資料字典實時觸發緩存
redis實戰_Redis實戰(11)-哈希Hash應用場景實戰之系統資料字典實時觸發緩存

好了,本篇文章我們就介紹到這裡了,建議各位小夥伴一定要照着文章提供的樣例代碼撸一撸,隻有撸過才能知道這玩意是咋用的,否則就成了"空談者"!

對Redis相關技術棧以及實際應用場景實戰感興趣的小夥伴可以前往Debug搭建的技術社群的課程中心進行學習觀看:http://www.fightjava.com/web/index/course/detail/12!

其他相關的技術,感興趣的小夥伴可以私信Debug。

繼續閱讀