RitoLabo

LaravelでRedisを使う入門編。導入設定と基本的なRedisファサードの使い方(DBキャッシュ)

  • 公開:
  • カテゴリ: PHP Laravel
  • タグ: PHP,Laravel,5.5,5.4,5.3,cache,Redis

今回はLaravelとRedisを使って、DBキャッシュを行います。

アジェンダ
  1. 開発環境
  2. パッケージの導入
  3. Redisの設定
  4. キャッシュ操作のメソッド
  5. 基本クラス構造
  6. [SET]strings型データを登録する
  7. [GET]strings型データを取得する
  8. [GETRANGRE]strings型データを範囲を指定して取得する
  9. [RPUSH]list型データを登録する
  10. [LRANGE]指定した範囲でのリスト型データを取得する
  11. [SADD]set型のデータを登録する
  12. [SMEMBERS]狙ったKEYの集合を取得する
  13. [ZADD]ソート済みセット型のデータを登録する
  14. [ZRANGE]ソート済みセット型のデータを取得する
  15. [HSET]hash型データを登録する
  16. [HGETALL]ハッシュ型データから任意のKEYのデータを取得する

開発環境

今回の開発環境は以下の通りです。

  • Linux CentOS 7
  • Redis 4
  • PHP 7.2
  • MySQL 5.7
  • Laravel 5.5

Laravelのバージョンは5.5以外にも5.4、5.3であれば同一手順で進めていけます。

Laravelのルートディレクトリを「laravel/」としています。

尚、今回、Redisは構築済みの前提で進めますので、まだの場合は
CentOSにRedis(NoSQL)をインストールして初期設定&デーモン化までを行う
を参考に構築を行ってください。

ちなみにRedisとLaravelは別サーバに立てていて、Redisにはパスワードを設定している状態で構築しています。

パッケージの導入

LaravelでRedisを使うにはpredis/predisパッケージが必要なので、Composerでインストールします。

# Laravelルートディレクトリへ移動する
cd /path/to/laravel

# predis/predisパッケージインストールする
composer require predis/predis

# 実行結果
[demo@localhost laravel]# composer require predis/predis
Using version
^1.1 for predis/predis
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals

- Installing
predis/predis (v1.1.1): Downloading (100%)
predis/predis suggests installing ext-phpiredis (Allows faster serialization and deserialization of the Redis protocol)
Writing lock file
Generating optimized autoload files

> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Package manifest generated successfully.

Redisの設定

LaravelでRedisを使う為の設定を行います。DBの設定ファイルを以下のように記述します。

laravel/config/database.php
'redis' => [

'client' => 'predis',

'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
'read_write_timeout' => env('REDIS_READ_WRITE_TIMEOUT', 60),
],

],

envファイルにRedisの設定値情報を記述します。

laravel/.env
CACHE_DRIVER=redis
REDIS_HOST=192.168.99.999
REDIS_PASSWORD=your_password
REDIS_PORT=6379
REDIS_DB=0
REDIS_READ_WRITE_TIMEOUT=60

これで、LaravelでRedisを使えるようになりました。

キャッシュ操作のメソッド

それでは実際にLaravelでRedisを使った操作を行っていきます。

Laravelでは、Cacheファサードを使ってRedisを操作する事が出来ます。これは、Laravelでキャッシュを扱う上で基本となるものですが、今回はそれではなく、Redisファサードを使って操作を行います。

Cacheファサードは、キャッシュを扱う際にどの方式(ファイルでもDBでもNoSQLでも)を採用しても共通して使えるメソッドが揃っています。

一方、RedisファサードはRedis操作のためのクラスであり、Redisコマンドの全てをコールする事が出来ます。

Cacheファサードでの基本的な操作については
Laravelのキャッシュを用いてDB負荷の削減と高速化を行う
を参照ください。

また、Redisファサードには2種類のメソッドがあり、magicメソッドとcommandメソッドがあります。

magicメソッド
Redis::set($key, $value);
commandメソッド
Redis::command('SET', [$key, $value]);

どちらも同じですが、今回はより汎用性がありわかりやすいcommandメソッドを使っていきます。

基本クラス構造

ここからはアクション(メソッド)を紹介していくので、その前に基本となるクラス構造を紹介しておきます。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use DB;
use Illuminate\Support\Facades\Redis;

class SampleRedisController extends Controller
{
protected $table;
protected $id;

public function __construct()
{
$this->table = 'users';
}

/**
* ここにアクションを記述していく
*/
public function hoge()
{

}
}

Redisコマンドを使うのでRedisファサードと、データベースからデータを取得するのでDBファサードをuseしています。

以下で紹介するアクションは全て、このクラス構造の中に記述されています。

[SET]strings型データを登録する

まずは、Redisの基本型となるstrings型でのデータ収容を行います。Redisコマンドは「SET」になります。

/**
* strings型データを登録する
*/
public function set()
{
$this->id = 6;

// DBからデータ取得
$data = json_encode(DB::table($this->table)->select('id', 'name', 'email')->where('id', $this->id)->first());

// Redisへリスト型として保存する
Redis::command('SET', [$this->id, $data]);
}

commandメソッドの場合は、第一引数にRedisコマンドを渡し、第二引数にKEYとValueを配列でセットします。

セットしたら実際にRedis側を確認してみます。

"SET" "6" "{\"id\":6,\"name\":\"user06\",\"email\":\"test06@test.com\"}"

データがストアされました。

[GET]strings型データを取得する

SETでストアしたデータをGETで取得します。

/**
* strings型データを取得する
*/
public function get()
{
$this->id = 6;

$data = json_decode(Redis::command('GET', [$this->id]));

}

文字列型データを取得するので、Resisコマンドである「GET」と、取得したいKEYを渡します。

stdClass Object
(
[id] => 6
[name] => user06
[email] => test06@test.com
)

ストアした時と同じ形式で取得できました。

[GETRANGRE]strings型データを範囲を指定して取得する

文字列型はKEY-VALUEの形で収容されるので様々な使い方ができます。例えば今回のようにユーザ情報のようなものだとマッチはしませんが、GETRANGREで狙った範囲だけを取得する事もできます。

/**
* strings型データを範囲を指定して取得する
*/
public function getrange()
{
$data = Redis::command('GETRANGE', [1, 8, 22]);

}

上記の場合、KEY:1のデータに対して8文字目から22文字を取得しています。

"name":"user01"

[RPUSH]list型データを登録する

次に、リスト型でのデータストアを行います。

/**
* リスト型データを登録する(末尾)
*/
public function rpush()
{
$this->id = 6;

// DBからデータ取得
$data = json_encode(DB::table($this->table)->select('id', 'name', 'email')->where('id', $this->id)->first());

// Redisへリスト型として保存する
Redis::command('RPUSH', ['user', $data]);
}

RPUSHでlistデータの末尾にデータを追加しています。

セットしたら実際にRedis側を確認してみます。

"RPUSH" "user" "{\"id\":6,\"name\":\"user06\",\"email\":\"test06@test.com\"}"

LIST型でデータがストアされました。

[LRANGE]指定した範囲でのリスト型データを取得する

次に、リスト型データに対して、指定した範囲でデータを取得してみます。

/**
* 指定した範囲でのリスト型データを取得する
*/
public function lrange()
{
$data = Redis::command('LRANGE', ['user',2,6]);

$users = array();
foreach ($data as $d) {
$users[] = json_decode($d);
}

}

RedisコマンドのLRANGEで、userキーのリスト2~6番目のデータを取得しています。

Array
(
[0] => stdClass Object
(
[id] => 2
[name] => user02
[email] => user02@test.com
)

[1] => stdClass Object
(
[id] => 3
[name] => user03
[email] => test03@test.com
)

[2] => stdClass Object
(
[id] => 4
[name] => user04
[email] => test04@test.com
)

[3] => stdClass Object
(
[id] => 5
[name] => user05
[email] => test05@test.com
)

[4] => stdClass Object
(
[id] => 7
[name] => user07
[email] => test07@test.com
)

)

リスト型は特に何もしなければ追加した順でストアされるので、見ての通りvalueのid自体は順不同です。

[SADD]set型のデータを登録する

次はセット型です。set型は集合を扱うのに便利なデータ型です。

/**
* セット型のデータを登録する
*/
public function sadd()
{
$data =[
"ja" => ["おはよう", "こんにちは", "こんばんは"],
"en" => ["good morning", "hello", "good evening"]
];

foreach ($data as $key => $value) {
Redis::command('SADD', [$key, $value]);
}
}

KEYそれぞれ「ja」「en」に対してのvalue値を配列で収納し、引数「SADD」共に渡します。

Redis側を確認してみます。

127.0.0.1:6379> SMEMBERS en
1) "good evening"
2) "hello"
3) "good morning"

セット型としてデータをストアできました。

[SMEMBERS]狙ったKEYの集合を取得する

先ほど追加したセット型のデータから指定したKEYの集合を取得してみます。

/**
* セット型のデータから指定したKEYの集合を取得する
*/
public function smembers()
{
$data = Redis::command('SMEMBERS', ['en']);

}

Redisコマンド「SMEMBERS」と、キーの指定「en」を渡しています。

Array
(
[0] => good evening
[1] => hello
[2] => good morning
)

キー「en」の集合を取得できました。

[ZADD]ソート済みセット型のデータを登録する

スコアでソートストアが行えるソート済みセット型でのデータ登録を行います。

/**
* ソート済みセット型のデータを登録する
*/
public function zadd()
{
$data = [
["score", 100, "user01"],
["score", 220, "user03"],
["score", 490, "user06"],
["score", 160, "user04"],
["score", 370, "user10"],
];

foreach ($data as $value) {
Redis::command('ZADD', $value);
}
}

キー「score」に対して、スコア(数値)とvalue値(userXX)をセットしています。

] "ZADD" "score" "100" "user01"
] "ZADD" "score" "220" "user03"
] "ZADD" "score" "490" "user06"
] "ZADD" "score" "160" "user04"
] "ZADD" "score" "370" "user10"

登録できていますね。

[ZRANGE]ソート済みセット型のデータを取得する

続いて、セットしたデータを取得します。ZRANGEでスコア範囲を指定して取得します。

/**
* ソート済みセット型のデータを取得する
*/
public function zrange()
{
$data = Redis::command('ZRANGE', ["score", 0, -1, "WITHSCORES"]);

}

第二引数で渡している配列ですが、左から「KEY」「スコア範囲(start)」「スコア範囲(end)」「スコアも取得」です。(上記の場合は、全て取得するようになっています。)

Array
(
[user01] => 100
[user04] => 160
[user03] => 220
[user10] => 370
[user06] => 490
)

スコアを基に並べ替えられているところが、ソート済みセット型の良いところです。

[HSET]hash型データを登録する

最後に、ハッシュ型としてデータをストアします。

/**
* ハッシュ型データを登録する
*/
public function hset()
{
$data = [
["user01", "id", 1],
["user01", "name", "mitsuha"],
["user01", "email", "mitsuha@ritolab.com"],
["user02", "id", 2],
["user02", "name", "rito"],
["user03", "email", "rito@ritolab.com"]
];

foreach ($data as $value) {
Redis::command('HSET', $value);
}
}

データは、「親KEY,子KEY,VALUE値」を1組として配列でセットします。

Redis側を確認してみます。

] "HSET" "user01" "id" "1"
] "HSET" "user01" "name" "mitsuha"
] "HSET" "user01" "email" "mitsuha@ritolab.com"
] "HSET" "user02" "id" "2"
] "HSET" "user02" "name" "rito"
] "HSET" "user03" "email" "rito@ritolab.com"

ハッシュ型でデータがストアされました。

[HGETALL]ハッシュ型データから任意のKEYのデータを取得する

では、登録したハッシュ型データから任意のKEYのデータを取得してみます。

/**
* ハッシュ型データから任意のKEYのデータを取得する
*/
public function hgetall()
{
$data = Redis::command('HGETALL', ["user01"]);

}

RedisコマンドのHGETALLと、取得したいキーである「user01」を渡しています。

Array
(
[id] => 1
[name] => mitsuha
[email] => mitsuha@ritolab.com
)

指定したキーでデータを取得できました。

まとめ

作業は以上で完了です。

引数の渡し方などで参考になりそうなものや基本的なコマンドを選んで紹介しましたが、ここで紹介したRedisコマンドはまだまだ一部です。

とはいえ、LaravelではこうしてRedisファサードを使う事でコマンドを全て自在に扱えるので便利です。是非試してみてください。