Files
build-web-application-with-…/zh-tw/05.6.md
2019-02-26 01:40:54 +08:00

209 lines
5.4 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?raw=true)
圖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>)