Ray Lee | 李宗叡
Learn or Die
Published in
14 min readJan 28, 2021

--

Photo by Chris J. Davis on Unsplash

# 版本

Laravel 8.x

# 前言

我喜歡使用 Laravel 開發的感覺, 除了開發快速, 程式碼簡潔且優雅之外, Laravel 框架本身也是一個很好的學習參照物。 本篇主要將官方文件重點整理成 Q&A 的形式呈現, 原子化的概念, 這方式並不適用於每個人, 但若對你有幫助, 我會很開心。

# 目錄

Laravel — 官方文件原子化翻譯 — 目錄

# 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,
],

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

--

--

Ray Lee | 李宗叡
Learn or Die

It's Ray. I do both backend and frontend, but more focus on backend. I like coding, and would like to see the whole picture of a product.