上一篇 Redis三部曲(一)介紹了Laravel中Predis的幾種基本數(shù)據(jù)類(lèi)型的使用和Redis的概念,但是就算會(huì)寫(xiě)了,然而緩存什么時(shí)候使用呢???
下面就結(jié)合上一篇的內(nèi)容給大家說(shuō)說(shuō)Predis的一些組合用法,隊(duì)列如何配合STRING類(lèi)型或者HASH類(lèi)型來(lái)組合使用,甚至把非關(guān)系變成和MySQl一樣成為關(guān)系型的。
隊(duì)列與哈希的組合使用 - 實(shí)現(xiàn)數(shù)據(jù)關(guān)系化
思路:利用隊(duì)列里的值來(lái)做需要取數(shù)據(jù)的唯一索引,利用哈希的key的后綴名做原型數(shù)據(jù)的唯一索引
隊(duì)列和哈希的組合使用優(yōu)勢(shì)是,取出來(lái)可以直接使用,劣勢(shì)在于內(nèi)存占用相比較字符串而言要大
-
實(shí)例:因?yàn)镽edis只能存數(shù)組而我們實(shí)例為了方便直接用DB類(lèi)來(lái)寫(xiě)的,如果是ORM可以直接返回?cái)?shù)組的
/** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { // $where = ['status'=>'1']; $obj = \DB::table('data_admin_login')->where($where)->get(); $array = $this->objectToArray($obj); dd($array); }
打印的數(shù)據(jù)如下:
-
接下來(lái) 我們要把從數(shù)據(jù)庫(kù)取出來(lái)的數(shù)據(jù)存入Redis,用什么樣的方法存,用什么樣的方法取,這些東西都得考慮好;下面實(shí)例如下:
/** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { // $where = ['status'=>'1']; $obj = \DB::table('data_admin_login')->where($where)->get(); $array = $this->objectToArray($obj); // 定義Redis的key $listKey = 'LIST:TEST:ADMIN'; $hashKey = 'HASH:TEST:ADMIN:'; // 遍歷時(shí)寫(xiě)入Redis list為索引 hash為數(shù)據(jù) foreach($array as $v){ \Redis::rpush($listKey,$v['guid']); \Redis::hMset($hashKey.$v['guid'],$v); } return '緩存寫(xiě)入成功'; }
-
查看下redis里面的情況
- 第一個(gè) 查看所有key 發(fā)現(xiàn)有1個(gè)隊(duì)列和16個(gè)哈希
- 第二個(gè) 取LIST:TEST:ADMIN 整個(gè)隊(duì)列 發(fā)現(xiàn)有16個(gè) 唯一識(shí)別ID的數(shù)據(jù)(而且順序和從數(shù)據(jù)庫(kù)取出來(lái)的順序是一樣的)
-
第三個(gè)取出其中一個(gè)哈希查看數(shù)據(jù)
可以看出來(lái) 我們想要的數(shù)據(jù)已經(jīng)存入了redis中,接下來(lái),如果我想通過(guò)redis直接獲取MySQL中管理員的列表數(shù)據(jù)怎么使用呢?
/** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { // // 定義Redis的key $listKey = 'LIST:TEST:ADMIN'; $hashKey = 'HASH:TEST:ADMIN:'; // 取出admin隊(duì)列的唯一識(shí)別id數(shù)組 $list = \Redis::lrange($listKey,0,-1); $array = null; foreach($list as $v){ // 取出哈希里的數(shù)據(jù)寫(xiě)入大數(shù)組中 $array[] = \Redis::hGetall($hashKey.$v); } dd($array); }
我們來(lái)看看打印的結(jié)果
這樣取出來(lái)的數(shù)據(jù)是不是一樣可以遍歷到模版上?
-
-
最后來(lái)完整的做一個(gè)例子
思路:我們的目的是從redis里面取出想要輸出到模版上的數(shù)據(jù),但是redis大家也知道,只是緩存服務(wù)器重啟了,就沒(méi)了(除非做磁盤(pán)持久化),但是我要做的是如果Redis里面沒(méi)有我要從MySQL里面取,取到了然后寫(xiě)入Redis,保證對(duì)MySQL的請(qǐng)求大大減少。
/** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { // // 定義Redis的key $listKey = 'LIST:TEST:ADMIN'; $hashKey = 'HASH:TEST:ADMIN:'; // 查看key是否存在? if(empty(\Redis::exists($listKey))){ // 如果Redis不存在 讀數(shù)據(jù)庫(kù)然后寫(xiě)入redis $where = ['status'=>'1']; $obj = \DB::table('data_admin_login')->where($where)->get(); $array = $this->objectToArray($obj); // 遍歷時(shí)寫(xiě)入Redis list為索引 hash為數(shù)據(jù) foreach($array as $v){ \Redis::rpush($listKey,$v['guid']); \Redis::hMset($hashKey.$v['guid'],$v); } return $array; } // 如果redis存在 直接讀redis的數(shù)據(jù) // 取出admin隊(duì)列的唯一識(shí)別id數(shù)組 $list = \Redis::lrange($listKey,0,-1); $array = null; foreach($list as $v){ $array[] = \Redis::hGetall($hashKey.$v); } return $array; }
不管我把redis的key手動(dòng)刪除還是redis的key存在 我們輸出的都是這個(gè)(這是我的瀏覽器插件json-handle的效果)
刪除redis的key 效果依舊
-
那么肯定有人又要問(wèn)了 你這只是在讀數(shù)據(jù)庫(kù) 如果我增 刪 改 后 redis不同步了哇
是這樣的,所以一般我們?cè)趯?shí)際商業(yè)項(xiàng)目中 做一個(gè)大型的redis數(shù)據(jù)隔離都需要把mysql的增刪改 綁上同步的redis操作,這樣下來(lái),我每次讀redis既大大的提升了性能,也保障了數(shù)據(jù)的同步性
-
下面拿添加做一個(gè)實(shí)例,如何MySQL與redis數(shù)據(jù)同步
-
restfulApi 添加方法
/** * Show the form for creating a new resource. * * @return \Illuminate\Http\Response */ public function create() { // // 定義Redis的key $listKey = 'LIST:TEST:ADMIN'; $hashKey = 'HASH:TEST:ADMIN:'; $data = [ 'guid'=> '12341234123412341234123412341234', 'email'=> 'adminadmin@163.com', 'password'=> '111dcfeb6d42b320d9b885f1b8fa498a', 'status'=> '1', 'sroce'=> '0', 'addtime'=> time(), 'logintime'=> '', 'ip'=> '' ]; $temp = \DB::table('data_admin_login')->insert($data); if($temp){ \Redis::rpush($listKey,$data['guid']); \Redis::hMset($hashKey.$data['guid'],$data); return '寫(xiě)入成功'; } return '寫(xiě)入失敗'; }
頁(yè)面響應(yīng):寫(xiě)入成功
-
redis查看一下有沒(méi)有同步寫(xiě)入
我們發(fā)現(xiàn)數(shù)據(jù)同步進(jìn)入了redis
index方法代碼不變 再請(qǐng)求一次 數(shù)據(jù)也明顯同步了
-
-
-
以上講的就是最基本的redis隔離技術(shù),當(dāng)然為了提現(xiàn)的簡(jiǎn)單點(diǎn),直接都寫(xiě)在控制器里面了,并沒(méi)有做過(guò)多的分層調(diào)用,RedisKey也沒(méi)有做配置話,而是反復(fù)在用;實(shí)際項(xiàng)目中Redis是可以單獨(dú)做一個(gè)模塊的,架構(gòu)的層級(jí)分化明確了也可以大大的提升Redis的復(fù)用性;當(dāng)然這些只是建議和思路,主要還是看當(dāng)前每個(gè)人手頭的架構(gòu)為主。
-
其他組合關(guān)系型方法
至于其他的關(guān)系型的組合方法就在下面簡(jiǎn)要做做介紹了,純手碼寫(xiě)得也挺累,望大家體諒。。
-
隊(duì)列和字符串類(lèi)型
隊(duì)列和字符串類(lèi)型一樣可以把數(shù)據(jù)關(guān)系型
思路:同樣的list存索引的key(ID或唯一識(shí)別ID),字符串存json字符串,字符串的key同樣后綴加唯一識(shí)別ID來(lái)進(jìn)行區(qū)分。當(dāng)需要輸出到頁(yè)面上的時(shí)候json_decode過(guò)來(lái)就行了
隊(duì)列和字符串的優(yōu)點(diǎn)是存儲(chǔ)的空間小,劣勢(shì)在于存的時(shí)候要解析成字符串,取的時(shí)候要解析為數(shù)組或?qū)ο?/p>
-
集合和字符串類(lèi)型
集合和字符串類(lèi)型一樣可以把數(shù)據(jù)關(guān)系型
思路:大家應(yīng)該都知道 redis集合有有序集合和無(wú)序集合之分,在有些場(chǎng)景中,其實(shí)用集合的形勢(shì)反而更靈活(多維度集合控制),比如 關(guān)注我的人、我關(guān)注的人、同時(shí)互相關(guān)注的、QQ中的'可能認(rèn)識(shí)的人'、異步寫(xiě)入時(shí)分區(qū)間等等等...
-
集合和哈希類(lèi)型(第三部實(shí)戰(zhàn)將用這個(gè))
思路其實(shí)就是和上面差不多,也就是存儲(chǔ)方便,消耗內(nèi)存相比較而言較大。
-
本篇基本都是參照倡哥博客而來(lái),因?yàn)楣P者也是看著博客學(xué)會(huì)的,所以直接拿來(lái)分享給大家,若有需要?dú)g迎轉(zhuǎn)載,但是務(wù)必注明來(lái)源,否則后果自負(fù)(丟丟哥不會(huì)饒了你哦)
第三篇將會(huì)是筆者根據(jù)自己最近的實(shí)戰(zhàn)經(jīng)驗(yàn),感想而來(lái)的,純自己手碼,歡迎拍磚!當(dāng)然還是歡迎轉(zhuǎn)載,請(qǐng)注明來(lái)源
博客地址:http://blog8090.com