MySQL與Redis實現二級緩存的方法介紹(代碼示例)

本篇文章給大家帶來的內容是關于mysqlredis實現二級緩存的方法介紹(代碼示例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

redis簡介

  • redis 是完全開源免費的,遵守bsd協議,是一個高性能的key-value數據庫

  • Redis 與其他 key – value 緩存產品有以下三個特點:

    • Redis支持數據的持久化,可以將內存中的數據保存在磁盤中,重啟的時候可以再次加載進行使用

    • Redis不僅僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲

    • Redis支持數據的備份,即master-slave模式的數據備份

優勢

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

  • 豐富的數據類型 – Redis支持二進制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 數據類型操作

  • 原子 – Redis的所有操作都是原子性的,意思就是要么成功執行要么失敗完全不執行。單個操作是原子性的。多個操作也支持事務,即原子性,通過MULTI和EXEC指令包起來

下載與安裝

  • 下載并解壓縮

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

mv?redis-5.0.3?/usr/local/
  • 進入到文件夾中并編譯測試

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

sudo?make?install
  • 啟動redis

redis-server

若出現以下畫面則表示redis數據庫已經啟動了:
jpg

mysql與redis做二級緩存

  • 對于訪問量比較大的數據我們為了能夠更快的獲取到數據需要對數據庫中獲取的數據進行數據緩存。

  • 在項目當中使用Redis緩存流程

    數據緩存應該考慮同步問題:如果對數據進行了緩存,當查詢數據時,如果緩存中有數據則直接返回緩存數據不會查詢數據庫,當數據庫數據改變的時候就有可能出現數據庫不一致的問題。可以考慮在每次修改數據庫的時候同時將對應的緩存數據刪除,這樣重新查詢的時候就會查詢數據庫并緩存

  1. 查詢時先從緩存當中查詢

  2. 緩存當中如果沒有數據再從數據庫查詢,并將數據保存進緩存當中

  3. 如果緩存中查詢到了數據直接返回,不再需要查詢數據庫

步驟實現
  • 創建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,?//最大空閑鏈接數,表示即使沒有redis鏈接事依然可以保持N個空閑鏈接,而不被清除 ????????MaxActive:???3,?//最大激活連接數,表示同時最多有多少個鏈接 ????????IdleTimeout:?240?*?time.Second,//最大空閑鏈接等待時間,超過此時間,空閑將被關閉 ????????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)?
  • 創建main.go文件實現二級緩存

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("不能識別其他命令") ????????} ????????fmt.Println() ????} }  func?getAll()??{ ????//從連接池當中獲取鏈接 ????conn?:=?redigo_pool.Pool.Get() ????//先查看redis中是否有數據 ????//conn,_?:=redis.Dial("tcp","localhost:6379") ????defer?conn.Close() ????values,?_?:=?redis.Values(conn.Do("lrange",?"mlist",0,-1))  ????if?len(values)?>?0?{ ????????//如果有數據 ????????fmt.Println("從redis獲取數據") ????????//從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?反序列化出錯") ????????????}else?{ ????????????????fmt.Printf("name?=?%sn",p.Name) ????????????} ????????} ????}else?{ ????????fmt.Println("從mysql中獲取")  ????????//查詢數據庫 ????????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) ????????????//?設置過期時間 ????????????conn.Do("EXPIRE",p.Id,60*5) ????????????if?err1?!=?nil?||?err2?!=?nil?{ ????????????????fmt.Println("寫入失敗") ????????????}else?{ ????????????????fmt.Println("寫入成功") ????????????} ????????} ????????conn.Do("EXPIRE","mlist",60*5) ????} }

? 版權聲明
THE END
喜歡就支持一下吧
點贊5 分享