Couchbaseの導入検討(後編)

Couchbaseの導入検討(後編)

はじめに

这篇文章是株式会社アイスタイル Advent Calendar 第19天的文章。
终于进入了我加入公司的第二年,作为基础设施工程师@imaiy以轻松的风格,将内容分为两部分呈现给大家。

这篇文章主要是关于Couchbase的背景和介绍。这一次是关于Couchbase的安装部分。

从安装开始,尝试向数据库发出查询(NiQL),连接并获取数据使用PHP进行。

环境

服务器环境如下所示。

    • Couchbase Server

CentOS release 6.7
couchbase-server-community-4.0.0-centos6.x86_64

Clientサイド

libcouchbase-devel-2.5.3-1.el6.x86_64
libcouchbase2-core-2.5.3-1.el6.x86_64
PHP 5.5
memcached 1.4.4

安装Couchbase Server

从Couchbase官网下载rpm安装包并将其放置在服务器内,然后执行以下命令进行安装:rpm -ivh couchbase-server-community-4.0.0-centos6.x86_64.rpm。

インストール後は自動的にCouchbase Serverが起動します。
netstat -l とか叩くとわかりますが、色々なポートがオープンになりますのでご注意下さい。

# /etc/init.d/couchbase-server status
couchbase-server-community is not running

今后,我们会在管理页面(http://:8091/)进行初始设置等操作,请仔细阅读每个项目并进行设置。

    • Couchbaseで利用可能なメモリ量

 

    • データを永続保管するためのディレクトリ指定

 

    Sample Bucketはいつでも消せるので作っておきます。

暂时先试用一下

安装完成后,让我们从本地试用一下。尝试使用样本的beer-sample Bucket执行NiQL。

# /opt/couchbase/bin/cbq
Couchbase query shell connected to http://localhost:8093/ . Type Ctrl-D to exit.
cbq>  SELECT name, type FROM `beer-sample` limit 2;
{
    "requestID": "310b452a-1ce1-4046-99ec-55f58b47fc84",
    "errors": [
        {
            "code": 4000,
            "msg": "No primary index on keyspace beer-sample. Use CREATE PRIMARY INDEX to create one."
        }
    ],
    "status": "fatal",
    "metrics": {
        "elapsedTime": "79.274704ms",
        "executionTime": "79.234254ms",
        "resultCount": 0,
        "resultSize": 0,
        "errorCount": 1
    }
}

結果がJSON形式で返ってきました。
“No primary index on keyspace beer-sample. Use CREATE PRIMARY INDEX to create one.” と言われている通り、
NiQLを発行するためにはPrimary Keyを設定して上げる必要があります。
※なお、NiQLを発行しない単なるKVSとして利用する分にはPrimary indexを作る必要はありません。

cbq> CREATE PRIMARY INDEX ON `beer-sample` USING GSI;
{
    "requestID": "7e87ef4e-baa9-46b7-a68a-1a014a24041d",
    "signature": null,
    "results": [
    ],
    "status": "success",
    "metrics": {
        "elapsedTime": "3.906325722s",
        "executionTime": "3.906271638s",
        "resultCount": 0,
        "resultSize": 0
    }
}

似乎取得成功。
再次发布NiQL。

cbq> SELECT name, type FROM `beer-sample` limit 2;
{
    "requestID": "b2cb0935-d8a5-4084-bd4b-07b915648591",
    "signature": {
        "name": "json",
        "type": "json"
    },
    "results": [
        {
            "name": "South Park Blonde",
            "type": "beer"
        },
        {
            "name": "563 Stout",
            "type": "beer"
        }
    ],
    "status": "success",
    "metrics": {
        "elapsedTime": "20.777558ms",
        "executionTime": "20.726616ms",
        "resultCount": 2,
        "resultSize": 150
    }
}

cbq> UPDATE `beer-sample` SET name = "563 Stout -X" WHERE name = "563 Stout";
{
    "requestID": "4bdfd577-f692-4bf3-a500-48f313c3213a",
    "signature": null,
    "results": [
    ],
    "status": "success",
    "metrics": {
        "elapsedTime": "621.796863ms",
        "executionTime": "621.755243ms",
        "resultCount": 0,
        "resultSize": 0,
        "mutationCount": 1
    }
}

cbq> SELECT * FROM `beer-sample` WHERE name = "563 Stout -X";
{
    "requestID": "c6842a1e-e0aa-435d-83b1-2d33b46d6060",
    "signature": {
        "*": "*"
    },
    "results": [
        {
            "beer-sample": {
                "abv": 5,
                "brewery_id": "21st_amendment_brewery_cafe",
                "category": "North American Ale",
                "description": "Deep black color, toasted black burnt coffee flavors and aroma. Dispensed with Nitrogen through a slow-flow faucet giving it the characteristic cascading effect, resulting in a rich dense creamy head.",
                "ibu": 0,
                "name": "563 Stout -X",
                "srm": 0,
                "style": "American-Style Stout",
                "type": "beer",
                "upc": 0,
                "updated": "2010-07-22 20:00:20"
            }
        }
    ],
    "status": "success",
    "metrics": {
        "elapsedTime": "657.178757ms",
        "executionTime": "657.060166ms",
        "resultCount": 1,
        "resultSize": 674
    }
}

您可以像一般的SQL查询一样执行这样的查询。
您可以参考这里找到更详细的NiQL参考资料。

构建PHP客户端

现在,让我们用PHP连接Couchbase。
首先,让我们安装适用于PHP的SDK。

wget -O /etc/yum.repos.d/couchbase.repo http://packages.couchbase.com/rpm/couchbase-centos62-x86_64.repo
yum install libcouchbase-devel
pecl install couchbase
echo "extension=couchbase.so" >> /etc/php.d/json.ini

# php -i | grep -A5 couchbase
couchbase

Version => 2.0.7

如果在php-info中出现couchbase相关信息的话,可能就没什么问题了。但我不会做进一步解释。

终于到了PHP代码的部分。
顺便提一下,我不是程序员,所以请不要太过在意代码的质量哟・ω・

<?php
// Connect to Couchbase Server

$cluster = new CouchbaseCluster('http://127.0.0.1:8091');
$bucket = $cluster->openBucket('beer-sample');

// Retrieve a document

try {
    $result = $bucket->get('21st_amendment_brewery_cafe');
} catch (Exception $e) {
    echo "CouchbaseException: " . $e->getMessage() . "\n";
}

$doc = json_decode($result->value, true);

var_dump($doc);

将单独进行解释。

    • Couchbaseクラスタに接続:$cluster = new CouchbaseCluster(‘http://127.0.0.1:8091’);

BucketをOpen:$bucket = $cluster->openBucket(‘beer-sample’);

KeyからValueを取得:$result = $bucket->get(’21st_amendment_brewery_cafe’);

在这里,我们通过类似KVS(键值存储)的“根据键获取值”的方法获取数据,而不是使用先前的NiQL查询获取。
变量”$result”中存储了与之前的NiQL查询结果相同的数据,以”CouchbaseMetaDoc”类的形式存储。
请注意,使用get方法时,如果键不存在,会抛出异常。

object(CouchbaseMetaDoc)#4 (4) {
  ["error"]=>
  NULL
  ["value"]=>
  string(666) "{"name":"21st Amendment Brewery Cafe","city":"San Francisco","state":"California","code":"94107","country":"United States","phone":"1-415-369-0900","website":"http://www.21st-amendment.com/","type":"brewery","updated":"2010-10-24 13:54:07","description":"The 21st Amendment Brewery offers a variety of award winning house made brews and American grilled cuisine in a comfortable loft like setting. Join us before and after Giants baseball games in our outdoor beer garden. A great location for functions and parties in our semi-private Brewers Loft. See you soon at the 21A!","address":["563 Second Street"],"geo":{"accuracy":"ROOFTOP","lat":37.7825,"lon":-122.393}}"
  ["flags"]=>
  int(0)
  ["cas"]=>
  resource(4) of type (CouchbaseCAS)
}

通过从这里取出value,你可以获取与NiQL结果中的Results等效的数据。如果error不是null,似乎还需要进行错误处理。

我将尝试从连续获取的数据进行编辑并进行upsert操作。
无论是编辑现有列,还是从解码的数据中添加新列都可以直接进行编辑。

$doc["comment"] = 'Random beer from Norway';
$doc["name"] = '563 Stout -X2';

$result = $bucket->upsert('21st_amendment_brewery_cafe_commented', $doc, array('expiry' => 60));

upsertにはKeyとArrayを渡すとそのKeyに対してArrayをそのValueとしてinsertもしくはupdateされます。
このとき、後ろに有効期限(Expiry)をセットしてやると期限付きのデータとして扱われ、get時に有効期限切れのデータは得られなくなります。

从NiQL获取数据

我不详细描述,但大致是这样的。
我有点困扰的是,数据的排列似乎不是固定的,每次包含多个结果时数据的顺序都会变化。
看起来需要根据需要进行排序。

    $query = CouchbaseN1qlQuery::fromString('SELECT * FROM `beer-sample` LIMIT 1');
    $result = $bucket->query($query);

尝试使用memcached的互换功能。

由于公式上标榜“可以直接在memcached库中使用”,所以我尝试一下。

    • CouchbaseServerの管理ページ上から、[Data Buckets]->[Create New Data Bucket]を選択し、[Bucket Type]はmemcachedを選択しましょう。

 

    Access ControlはSASL authとかしないので[Dedicated port]にして、利用していないTCPポートを指定しましょう。

在设定之后,我会确认所属于集群的CouchbaseServer是否正在监听指定的TCP端口,并尝试通过memcached进行访问。

<?php
$m = new Memcached();
$m->addServer('192.168.0.1', 11212);
$m->set('key2', 'wankoooo', 10);

if ($val = $m->get('key2')) {
    echo "$val\n";
}

sleep(15);

if ($val = $m->get('key2')) {
    echo "$val\n";
}

以下が実行結果です。

# php mem.php
wankoooo

过期时间也在动,所以应该没问题。

最后

CouchbaseServerの基本的な機能をざっと使ってみました。
memcachedをそのままカバー出来るため、開発側への負担少なく導入が進められそうかなと思っていたんですが、
作ったり使ったりしていると色々運用負荷も下げられそうな予感です。

memcacheに対応していないとか速度的にはmemcachedに劣るとかマイナス点もありますが
今後もう少し見極めて行く予定です。

另外,这次没能写完,但为了性能测试,搭建了5台集群,也进行了服务数据的缓存测试和访问日志分析等工作。如果有机会,我很想写一写。

bannerAds