蝦米係NoSQL
NoSQL(Not Only SQL)是對不同於傳統的關聯式資料庫的資料庫管理系統的統稱。 允許部分資料使用SQL系統儲存,而其他資料允許使用NOSQL系統儲存。 其數據儲存可以不需要固定的表格模式以及中介資料(metadata),也經常會避免使用SQL的JOIN操作,一般有水平可延伸性的特徵。
以前接觸過的db都是RDBMS,像是informix(上古時代...),MSSQL,ORACLE,MYSQL等等,
因為可以join特性,所以可以做出n階層的資料結構,一個table不夠用就再多開一個table來join就好
NoSQL的優勢:
彈性:NoSQL 資料庫整體而言提供促進更快速及更能反覆開發的彈性結構描述。具彈性的資料模型讓 NoSQL 資料庫成為半結構和非結構式資料的理想資料庫。
可擴展性:NoSQL 資料庫一般的設計都能透過硬體的分散式叢集來向外擴展,而不必藉由增加昂貴和重量級的伺服器來進行垂直擴展。有些雲端供應商背後將這些操作處理成全受管服務。
高效能:NoSQL 資料庫針對特定資料模型加以優化,並且存取比使用關聯式資料庫達到相同功能的更高效能模式。
高功能性:NoSQL 資料庫提供專為各別資料模型而建造的高功能 API 和資料。
這邊有很詳細的說明 NoSQL
Redis 是一個 in-memory 的 key-value database,常用於需要cache資料的情境,這樣子可以減輕rdbms db的loading
例如像寫了一件api可以撈出火車時刻表的資料,但是這個資料需要join四個table,單次執行需要超過1s的時間,可是這個火車時刻表的資料當天的異動性很低,如果有人發現這個api很吃db資源,只要狂打api就可以輕鬆吃光db資源,再強大的db也禁不起這樣子的操作。
在這種情境下,是不是可以先把query出來的資料塞到某個地方,api打過來時先判斷有沒有cache,沒cache時再去撈db,撈完db再塞到cache裡面。
照這樣子的邏輯,基本上一天只會一次api是真的去撈db,後續api都直接從cache裡面撈資料來出來,對db的loading與api的效能來說都是很效的改善
$ docker run -itd --name redis-test -p 6379:6379 redis
執行成功後可以在docker的dashboard上面看到新增了一個叫redis-test的container在運行
Redigo目前星星數7.8k,go-redis目前9.8k,所以就選擇go-redis為主要的執行套件
go get -u github.com/go-redis/redis/v8
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
)
func main() {
//go-redis使用context當執行參數
var ctx = context.Background()
//連線redis
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
})
//確認redis是否還健在
_, err := rdb.Ping(ctx).Result()
if err != nil {
fmt.Println("redis ping err:", err)
}
//塞值,第四個參數是ttl的值,0時就永遠不會失效
err = rdb.Set(ctx, "GG", "ininder", 0).Err()
if err != nil {
panic(err)
}
//取值
val, err := rdb.Get(ctx, "GG").Result()
if err != nil {
panic(err)
}
fmt.Println("GG", val)
val2, err := rdb.Get(ctx, "key2").Result()
if err == redis.Nil {
fmt.Println("key2 does not exist")
} else if err != nil {
panic(err)
} else {
fmt.Println("key2", val2)
}
}
來寫個http api使用redis當cache的例子
package main
import (
"context"
"fmt"
"time"
"github.com/gin-gonic/gin"
"github.com/go-redis/redis/v8"
)
func main() {
var ctx = context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
})
_, err := rdb.Ping(ctx).Result()
if err != nil {
fmt.Println("redis ping err:", err)
}
r := gin.Default()
r.GET("/imslow", func(c *gin.Context) {
result := ""
v, err := rdb.Get(ctx, "cache").Result()
if v != "" {
result = "i'm cache"
} else {
time.Sleep(5 * time.Second)
result = "i'm sleep 5 second"
err = rdb.Set(ctx, "cache", "ininder", 0).Err()
if err != nil {
panic(err)
}
}
c.JSON(200, gin.H{
"message": result,
})
})
//defaut 8080 port
r.Run()
}
執行結果
curl --location --request GET '127.0.0.1:8080/imslow'
//{"message":"i'm sleep 5 second"}%
curl --location --request GET '127.0.0.1:8080/imslow'
//{"message":"i'm cache"}%
執行速度比較
[GIN] 2020/10/01 - 23:01:52 | 200 | 5.004710825s | 127.0.0.1 | GET "/imslow"
[GIN] 2020/10/01 - 23:01:55 | 200 | 1.74188ms | 127.0.0.1 | GET "/imslow"
從上面的比較就可以明顯看出有無redis當cache的差距,如果真的要去擠出效能又不要讓db被打爆的話,加台redis是個不錯的解決方案