MySQL與Redis實(shí)現(xiàn)二級(jí)緩存的方法介紹(代碼示例)

本篇文章給大家?guī)?lái)的內(nèi)容是關(guān)于mysqlredis實(shí)現(xiàn)二級(jí)緩存的方法介紹(代碼示例),有一定的參考價(jià)值,有需要的朋友可以參考一下,希望對(duì)你有所幫助。

redis簡(jiǎn)介

  • redis 是完全開(kāi)源免費(fèi)的,遵守bsd協(xié)議,是一個(gè)高性能的key-value數(shù)據(jù)庫(kù)

  • Redis 與其他 key – value 緩存產(chǎn)品有以下三個(gè)特點(diǎn):

    • Redis支持?jǐn)?shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保存在磁盤中,重啟的時(shí)候可以再次加載進(jìn)行使用

    • Redis不僅僅支持簡(jiǎn)單的key-value類型的數(shù)據(jù),同時(shí)還提供list,set,zset,hash等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)

    • Redis支持?jǐn)?shù)據(jù)的備份,即master-slave模式的數(shù)據(jù)備份

優(yōu)勢(shì)

  • 性能極高 – Redis能讀的速度是110000次/s,寫的速度是81000次/s

  • 豐富的數(shù)據(jù)類型 – Redis支持二進(jìn)制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 數(shù)據(jù)類型操作

  • 原子 – Redis的所有操作都是原子性的,意思就是要么成功執(zhí)行要么失敗完全不執(zhí)行。單個(gè)操作是原子性的。多個(gè)操作也支持事務(wù),即原子性,通過(guò)MULTI和EXEC指令包起來(lái)

下載與安裝

  • 下載并解壓縮

wget?http://download.redis.io/releases/redis-5.0.3.tar.gz tar?xzf?redis-5.0.3.tar.gz
  • 將文件夾移動(dòng)到/usr/local/中

mv?redis-5.0.3?/usr/local/
  • 進(jìn)入到文件夾中并編譯測(cè)試

cd?/usr/local/redis-5.0.3 sudo?make?test
  • 編譯安裝

sudo?make?install
  • 啟動(dòng)redis

redis-server

若出現(xiàn)以下畫面則表示redis數(shù)據(jù)庫(kù)已經(jīng)啟動(dòng)了:
jpg

mysql與redis做二級(jí)緩存

  • 對(duì)于訪問(wèn)量比較大的數(shù)據(jù)我們?yōu)榱四軌蚋斓墨@取到數(shù)據(jù)需要對(duì)數(shù)據(jù)庫(kù)中獲取的數(shù)據(jù)進(jìn)行數(shù)據(jù)緩存。

  • 在項(xiàng)目當(dāng)中使用Redis緩存流程

    數(shù)據(jù)緩存應(yīng)該考慮同步問(wèn)題:如果對(duì)數(shù)據(jù)進(jìn)行了緩存,當(dāng)查詢數(shù)據(jù)時(shí),如果緩存中有數(shù)據(jù)則直接返回緩存數(shù)據(jù)不會(huì)查詢數(shù)據(jù)庫(kù),當(dāng)數(shù)據(jù)庫(kù)數(shù)據(jù)改變的時(shí)候就有可能出現(xiàn)數(shù)據(jù)庫(kù)不一致的問(wèn)題。可以考慮在每次修改數(shù)據(jù)庫(kù)的時(shí)候同時(shí)將對(duì)應(yīng)的緩存數(shù)據(jù)刪除,這樣重新查詢的時(shí)候就會(huì)查詢數(shù)據(jù)庫(kù)并緩存

  1. 查詢時(shí)先從緩存當(dāng)中查詢

  2. 緩存當(dāng)中如果沒(méi)有數(shù)據(jù)再?gòu)臄?shù)據(jù)庫(kù)查詢,并將數(shù)據(jù)保存進(jìn)緩存當(dāng)中

  3. 如果緩存中查詢到了數(shù)據(jù)直接返回,不再需要查詢數(shù)據(jù)庫(kù)

步驟實(shí)現(xiàn)
  • 創(chuàng)建redisPool.go文件用于連接池的初始化

package?redigo_pool  import?( ????"flag" ????"github.com/garyburd/redigo/redis" ????"time" ) var?( ????Pool?*redis.Pool ????RedisServer???=?flag.String("redisServer",?":6379",?"") ???? ) func?init()?{ ????Pool?=?&redis.Pool{ ????????MaxIdle:?????3,?//最大空閑鏈接數(shù),表示即使沒(méi)有redis鏈接事依然可以保持N個(gè)空閑鏈接,而不被清除 ????????MaxActive:???3,?//最大激活連接數(shù),表示同時(shí)最多有多少個(gè)鏈接 ????????IdleTimeout:?240?*?time.Second,//最大空閑鏈接等待時(shí)間,超過(guò)此時(shí)間,空閑將被關(guān)閉 ????????Dial:?func()?(redis.Conn,?error)?{ ????????????c,?err?:=?redis.Dial("tcp",?*RedisServer) ????????????if?err?!=?nil?{ ????????????????return?nil,?err ????????????} ????????????return?c,?err ????????}, ????????TestOnBorrow:?func(c?redis.Conn,?t?time.Time)?error?{ ????????????if?time.Since(t)?
  • 創(chuàng)建main.go文件實(shí)現(xiàn)二級(jí)緩存

package?main  import?( ????"database/sql" ????"encoding/json" ????"fmt" ????"github.com/garyburd/redigo/redis" ????_?"github.com/go-sql-driver/mysql" ????"strconv" ????"web/redis/redigo_pool" ????_?"web/redis/redigo_pool" )  type?Person?struct?{ ????Id?int?`db:"id"` ????Name?string?`db:"name"` ????Age?int?`db:"age"` ????Rmb?int?`db:"rmb"` }  func?main()?{ ????var?cmd?string ????for{ ????????fmt.Println("輸入命令") ????????fmt.Scan(&cmd) ????????switch?cmd?{ ????????case?"getall": ????????????getAll() ????????default: ????????????fmt.Println("不能識(shí)別其他命令") ????????} ????????fmt.Println() ????} }  func?getAll()??{ ????//從連接池當(dāng)中獲取鏈接 ????conn?:=?redigo_pool.Pool.Get() ????//先查看redis中是否有數(shù)據(jù) ????//conn,_?:=redis.Dial("tcp","localhost:6379") ????defer?conn.Close() ????values,?_?:=?redis.Values(conn.Do("lrange",?"mlist",0,-1))  ????if?len(values)?>?0?{ ????????//如果有數(shù)據(jù) ????????fmt.Println("從redis獲取數(shù)據(jù)") ????????//從redis中直接獲取 ????????for?_,key?:=?range?values{ ????????????pid?:=string(key.([]byte)) ????????????id?,_:=?strconv.Atoi(pid) ????????????results,_?:=?redis.Bytes(conn.Do("GET",id)) ????????????var?p?Person ????????????err?:=?json.Unmarshal(results,&p) ????????????if?err?!=?nil?{ ????????????????fmt.Println("json?反序列化出錯(cuò)") ????????????}else?{ ????????????????fmt.Printf("name?=?%sn",p.Name) ????????????} ????????} ????}else?{ ????????fmt.Println("從mysql中獲取")  ????????//查詢數(shù)據(jù)庫(kù) ????????db,_?:=?sql.Open("mysql","root:Szt930708@tcp(localhost:3306)/mydb") ????????defer?db.Close()  ????????var?persons?[]Person  ????????rows,_?:=?db.Query("select?id,name,age,rmb?from?person") ????????for?rows.Next()??{ ????????????var?id?int ????????????var?name?string ????????????var?age?int ????????????var?rmb?int ????????????rows.Scan(&id,&name,&age,&rmb) ????????????per?:=?Person{id,name,age,rmb} ????????????persons?=?append(persons,per)  ????????} ????????//寫入到redis中:將person以hash的方式寫入到redis中 ????????for?_,p?:=?range?persons{  ????????????p_byte,_?:=?json.Marshal(p) ????????????_,err1?:=?conn.Do("SETNX",p.Id,p_byte) ????????????_,err2?:=?conn.Do("lpush","mlist",p.Id) ????????????//?設(shè)置過(guò)期時(shí)間 ????????????conn.Do("EXPIRE",p.Id,60*5) ????????????if?err1?!=?nil?||?err2?!=?nil?{ ????????????????fmt.Println("寫入失敗") ????????????}else?{ ????????????????fmt.Println("寫入成功") ????????????} ????????} ????????conn.Do("EXPIRE","mlist",60*5) ????} }

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊5 分享