# 前言
學習一個框架, Ray 的想法是, 在深入理解底層實作的原理之前, 應該先知道這個框架的 使用方法
; 先學習怎麼使用這個前人造的輪子, 再學習怎麼樣造一個輪子。
所以本篇文章重點在於細讀官方文件, 並將內容理解後以 Q&A 的方式記錄下來, 加速學習以及查詢。
# Introduction
Laravel 文件上推薦使用 PhpRedis 或 predis?
PhpRedis
# Configuration
以下的 Laravel example code 的意思是?
- Example:
<?php
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
],
'cache' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_CACHE_DB', 1),
],
], - Answer:
<?php
'redis' => [
// 使用的 redis client, 預設 phpredis
'client' => env('REDIS_CLIENT', 'phpredis'),
'default' => [
// host, 預設 127.0.0.1
'host' => env('REDIS_HOST', '127.0.0.1'),
// password, 預設 null
'password' => env('REDIS_PASSWORD', null),
// port, 預設 6379
'port' => env('REDIS_PORT', 6379),
// database, 預設 0
'database' => env('REDIS_DB', 0),
],
'cache' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_CACHE_DB', 1),
],
],
以下的 Laravel example code 的意思是?
- Example:
<?php
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'default' => [
'url' => 'tcp://127.0.0.1:6379?database=0',
],
'cache' => [
'url' => 'tls://user:password@127.0.0.1:6380?database=1',
],
], - Answer:
預設會需要定義 host, password, port, database, 可用 url 方式定義全部
# Configuring The Connection Scheme
以下的 Laravel example code 的意思是?
- Example:
<?php
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'default' => [
// 這行意思是?
'scheme' => 'tls',
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
],
], - Answer:
預設使用 tcp 方式, 可自訂為 TLS
# Clusters
以下的 Laravel example code 的意思是?
- Example:
<?php
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
// 這行意思是?
'clusters' => [
'default' => [
[
'host' => env('REDIS_HOST', 'localhost'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
],
],
],
], - Answer:
如果使用 Redis Cluster 的話, 需定義於 ‘clusters’ 參數之下
以下的 Laravel example code 的意思是?
- Example:
<?php
// 在 config/database.php
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
],
'clusters' => [
// ...
],
],
// 在 .env
REDIS_CLUSTER=redis - Answer:
Laravel 預設 cluster redis 會使用 client-side sharding, 若希望使用 native redis cluster, 可將 options.cluster 的 value 設為 redis
# Predis
以下的 Laravel example code 的意思是?
- Example:
<?php
// 在 config/database.php
'redis' => [
'client' => env('REDIS_CLIENT', 'predis'),
// Rest of Redis configuration...
], - Answer:
指定 redis client, 預設是 phpredis, 若要使用 predis, 需特別指定 env
當使用 Laravel predis 時, 除了以下的預設 setting, 還可以設定額外的 setting 嗎?
- Example:
<?php
'default' => [
'host' => env('REDIS_HOST', 'localhost'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
'read_write_timeout' => 60,
], - Answer:
可, 官方文件
Laravel 中, 為何在 config/app.php 當中, alias array 中, redis 是被 disable 的?
- Example:
<?php
'Queue' => Illuminate\Support\Facades\Queue::class,
'Redirect' => Illuminate\Support\Facades\Redirect::class,
// 'Redis' => Illuminate\Support\Facades\Redis::class,
'Request' => Illuminate\Support\Facades\Request::class,
'Response' => Illuminate\Support\Facades\Response::class, - Answer:
因為 Redis alias 會跟 phpredis extension 提供的 class name 衝突, 因此如果使用 phpredis 時是 disable 的, 但如果使用 predis 時, 可以 uncomment
# PhpRedis
以下的 Laravel example code 的意思是?
- Example:
<?php
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
// Rest of Redis configuration...
],
// .env
REDIS_CLIENT=phpredis - Answer:
Laravel 預設使用 Phpredis extension 來跟 Redis 溝通
以下的 Laravel example code 的意思是?
- Example:
<?php
// phpredis
'default' => [
'host' => env('REDIS_HOST', 'localhost'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
'read_timeout' => 60,
'context' => [
// 'auth' => ['username', 'secret'],
// 'stream' => ['verify_peer' => false],
],
], - Answer:
phpredis 也有提供一些額外的 parameter 可以設定
# Interacting With Redis
以下的 Laravel example code 的意思是?
- Example:
<?php
class UserController extends Controller
{
public function show($id)
{
return view('user.profile', [
'user' => Redis::get('user:profile:'.$id)
]);
}
} - Answer:
使用 redis 的 get command, 取得指定的 key 的 value
以下的 Laravel example code 的意思是?
- Example:
<?php
use Illuminate\Support\Facades\Redis;
Redis::set('name', 'Taylor');
$values = Redis::lrange('names', 5, 10); - Answer:
set key / value 為 name / Taylor
取得 range between 5, 10 的 value, 0 代表第一個位置, 1 代表第二個位置, -1 代表倒數第一個位置, -2 代表倒數第二個位置, 若是超出範圍, 則代表最後一個位置, 比如 總共只有 10 個 item, range 10 會等於第十個位置, range -100 會等於第一個位置
# Pipelining Commands
以下的 Laravel example code 的意思是?
- Example:
<?php
$values = Redis::command('lrange', ['name', 5, 10]); - Answer:
使用 command method, 直接 pass command name 給 redis server, 同 Redis::lrange()
# Using Multiple Redis Connections
以下的 Laravel example code 的意思是?
- Example:
<?php
$redis = Redis::connection();
$redis = Redis::connection('connection-name'); - Answer:
取得 redis 預設 connection
取得 redis 指定名為'connection-name'
的 connection
# Transactions
以下的 Laravel example code 的意思是?
- Example:
<?php
use Illuminate\Support\Facades\Redis;
Redis::transaction(function ($redis) {
$redis->incr('user_visits', 1);
$redis->incr('total_visits', 1);
}); - Answer:
使用 redis 的 transaction feature, 所有的 command 會一次性執行, 所以無法在 transaction 的過程中取值
# Lua Script
以下的 Laravel example code 的意思是?
- Example:
<?php
$value = Redis::eval(<<<'LUA'
local counter = redis.call("incr", KEYS[1])
if counter > 5 then
redis.call("incr", KEYS[2])
end
return counter
LUA, 2, 'first-counter', 'second-counter'); - Answer:
使用 eval 執行 redis script, 既有 transaction 的 atomic 特性, 又可以在過程中可以與 redis 互動
arg1 為 lua script, arg2 為 key 的數量, arg3 為 key1, arg4 為 key2, 在往後可以帶入任何會在 script 內用到的變數
# Pipelining Commands
以下的 Laravel example code 的意思是?
- Example:
<?php
use Illuminate\Support\Facades\Redis;
Redis::pipeline(function ($pipe) {
for ($i = 0; $i < 1000; $i++) {
$pipe->set("key:$i", $i);
}
}); - Answer:
當需要執行複數的 redis command 時, 可以使用 pipeline method, 只經由一次的 connection 將多個 command 送到 redis server, closure 內的 command 會按照順序執行
如果沒使用 pipeline, 多個 command 會建立多次 connection
# Pub / Sub
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Redis;
class RedisSubscribe extends Command
{
protected $signature = 'redis:subscribe';
protected $description = 'Subscribe to a Redis channel';
public function handle()
{
Redis::subscribe(['test-channel'], function ($message) {
echo $message;
});
}
}
// in Route
use Illuminate\Support\Facades\Redis;
Route::get('/publish', function () {
// ...
Redis::publish('test-channel', json_encode([
'name' => 'Adam Wathan'
]));
}); - Answer:
使用 redis pub/sub feature, 可使用 Laravel subscribe 一個 channel, 而用其他的應用 publish 到這個 channel
# Wildcard Subscriptions
以下的 Laravel example code 的意思是?
- Example:
<?php
Redis::psubscribe(['*'], function ($message, $channel) {
echo $message;
});
Redis::psubscribe(['users.*'], function ($message, $channel) {
echo $message;
}); - Answer:
使用 psubscribe method, 可以 subscribe wildcard channels
留言