Files
2017-05-01 17:43:00 +09:00

201 lines
7.2 KiB
Markdown
Raw Permalink 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(順序付きset)を含みます。
現在redisが最もよく使われているのは新浪のマイクロブログプラットフォームでしょう。その次にFacebookに買収された画像フォーラムであるinstagramがあります。その他有名な[インターネット企業](http://redis.io/topics/whos-using-redis)もそうです。
Goは現在redisのドライバで以下をサポートしています
- [https://github.com/garyburd/redigo](https://github.com/garyburd/redigo)
- [https://github.com/go-redis/redis](https://github.com/go-redis/redis)
- [https://github.com/hoisie/redis](https://github.com/hoisie/redis)
- [https://github.com/alphazero/Go-Redis](https://github.com/alphazero/Go-Redis)
- [https://github.com/simonz05/godis](https://github.com/simonz05/godis)
redigoのドライバを使ってデータベースを操作する方法を見てみましょう
```Go
package main
import (
"fmt"
"github.com/garyburd/redigo/redis"
"os"
"os/signal"
"syscall"
"time"
)
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ドライバでどのようにデータの操作を行うかご紹介します。
package main
import (
"github.com/astaxie/goredis"
"fmt"
)
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になりそうなものです。
次にどのようにしてGoからmongoDBを操作するのかご説明します
```Go
package main
import (
"fmt"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"log"
)
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>)
* 前へ: [beedbライブラリを使用してORM開発を行う](<05.5.md>)
* 次へ: [まとめ](<05.7.md>)