Files
build-web-application-with-…/zh-tw/05.6.md
2019-06-22 23:41:28 +08:00

210 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 5.6 NOSQL 資料庫操作
NoSQL(Not Only SQL),指的是非關聯資料庫。隨著 Web2.0 的興起,傳統的關聯式資料庫在應付 Web2.0 網站,特別是超大規模和高併發的 SNS 型別的 Web2.0 純動態網站已經顯得力不從心,暴露了很多難以克服的問題,而非關聯資料庫則由於其本身的特點得到了非常迅速的發展。
而 Go 語言作為 21 世紀的 C 語言,對 NOSQL 的支援也是很好,目前流行的 NOSQL 主要有 redis、mongoDB、Cassandra 和 Membase 等。這些資料庫都有高效能、高併發讀寫等特點,目前已經廣泛應用於各種應用中。我接下來主要講解一下 redis 和 mongoDB 的操作。
## redis
redis 是一個 key-value 儲存系統。和 Memcached 類似,它支援儲存的 value 型別相對更多,包括 string(字串)、list(連結串列)、set(集合)和 zset(有序集合)。
目前應用 redis 最廣泛的應該是新浪微博平臺,其次還有 Facebook 收購的圖片社交網站 instagram。以及其他一些有名的 [ 網際網路企業](http://redis.io/topics/whos-using-redis)
Go 目前支援 redis 的驅動有如下
- https://github.com/garyburd/redigo (推薦)
- https://github.com/go-redis/redis
- https://github.com/hoisie/redis
- https://github.com/alphazero/Go-Redis
- https://github.com/simonz05/godis
我以 redigo 驅動為例來示範如何進行資料的操作:
```Go
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"time"
"github.com/garyburd/redigo/redis"
)
var (
Pool *redis.Pool
)
func init() {
redisHost := ":6379"
Pool = newPool(redisHost)
close()
}
func newPool(server string) *redis.Pool {
return &redis.Pool{
MaxIdle: 3,
IdleTimeout: 240 * time.Second,
Dial: func() (redis.Conn, error) {
c, err := redis.Dial("tcp", server)
if err != nil {
return nil, err
}
return c, err
},
TestOnBorrow: func(c redis.Conn, t time.Time) error {
_, err := c.Do("PING")
return err
}
}
}
func close() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
signal.Notify(c, syscall.SIGTERM)
signal.Notify(c, syscall.SIGKILL)
go func() {
<-c
Pool.Close()
os.Exit(0)
}()
}
func Get(key string) ([]byte, error) {
conn := Pool.Get()
defer conn.Close()
var data []byte
data, err := redis.Bytes(conn.Do("GET", key))
if err != nil {
return data, fmt.Errorf("error get key %s: %v", key, err)
}
return data, err
}
func main() {
test, err := Get("test")
fmt.Println(test, err)
}
```
另外以前我 fork 了最後一個驅動,修復了一些 bug目前應用在我自己的短域名服務專案中(每天 200W 左右的 PV 值)
https://github.com/astaxie/goredis
接下來的以我自己 fork 的這個 redis 驅動為例來示範如何進行資料的操作
```Go
package main
import (
"fmt"
"github.com/astaxie/goredis"
)
func main() {
var client goredis.Client
// 設定埠為 redis 預設埠
client.Addr = "127.0.0.1:6379"
//字串操作
client.Set("a", []byte("hello"))
val, _ := client.Get("a")
fmt.Println(string(val))
client.Del("a")
//list 操作
vals := []string{"a", "b", "c", "d", "e"}
for _, v := range vals {
client.Rpush("l", []byte(v))
}
dbvals,_ := client.Lrange("l", 0, 4)
for i, v := range dbvals {
println(i,":",string(v))
}
client.Del("l")
}
```
我們可以看到操作 redis 非常的方便而且我實際專案中應用下來效能也很高。client 的命令和 redis 的命令基本保持一致。所以和原生態操作 redis 非常類似。
## mongoDB
MongoDB 是一個高效能、開源的文件型資料庫,是一個介於關聯式資料庫和非關聯式資料庫之間的產品,是非關聯式資料庫當中功能最豐富,最像關聯式資料庫的。他支援的資料結構非常鬆散,採用的是類似 json 的 bjson 格式來儲存資料因此可以儲存比較複雜的資料型別。Mongo 最大的特點是他支援的查詢語言非常強大,其語法有點類似於物件導向的查詢語言,幾乎可以實現類似關聯式資料庫單表查詢的絕大部分功能,而且還支援對資料建立索引。
下圖展示了 mysql 和 mongoDB 之間的對應關係,我們可以看出來非常的方便,但是 mongoDB 的效能非常好。
![](images/5.6.mongodb.png)
圖 5.1 MongoDB 和 Mysql 的操作對比圖
目前 Go 支援 mongoDB 最好的驅動就是[mgo](http://labix.org/mgo),這個驅動目前最有可能成為官方的 pkg。
安裝 mgo:
```Go
go get gopkg.in/mgo.v2
```
下面我將示範如何透過 Go 來操作 mongoDB
```Go
package main
import (
"fmt"
"log"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
type Person struct {
Name string
Phone string
}
func main() {
session, err := mgo.Dial("server1.example.com,server2.example.com")
if err != nil {
panic(err)
}
defer session.Close()
// Optional. Switch the session to a monotonic behavior.
session.SetMode(mgo.Monotonic, true)
c := session.DB("test").C("people")
err = c.Insert(&Person{"Ale", "+55 53 8116 9639"},
&Person{"Cla", "+55 53 8402 8510"})
if err != nil {
log.Fatal(err)
}
result := Person{}
err = c.Find(bson.M{"name": "Ale"}).One(&result)
if err != nil {
log.Fatal(err)
}
fmt.Println("Phone:", result.Phone)
}
```
我們可以看出來 mgo 的操作方式和 beedb 的操作方式幾乎類似,都是基於 struct 的操作方式,這個就是 Go Style。
## links
* [目錄](<preface.md>)
* 上一節:[使用 Beego orm 函式庫進行 ORM 開發](<05.5.md>)
* 下一節:[小結](<05.7.md>)