Laravel讀寫分離 sticky參數

花了一天才解掉的bug原來是設定所引發的Orz

環境

Laravel 5.6

AWS Aurora @ Muti-AZ / Cluser [2R1W]


Code大略如下

1
2
3
4
5
6
7
8
//存入DB
$this->AdRepository->saveObjectAd($activityData);

//從DB讀取資料存入Redis

$areaCode = array($this->AdRepository->getId($activityId)[0]->area_code);

$this->setRedis($areaCode);

然後在local,測試環境都跑得好好的

一上Production就直接取不到資料沒辦法存進Redis

然後找了很久才發現是沒加sticky參數的關係

Laravel 台灣翻譯文件 | Laravel 道場 資料庫:入門 讀寫分離

sticky 選項

sticky 選項是一個可選的值,可以被用於立即讀取在目前請求週期內已寫入資料庫的記錄。如果啟動了 sticky 選項,而且已經在目前的請求週期間對資料庫執行了「寫入」操作,任何進一步的「讀取」操作都將使用「寫入」連線。這樣保證了在請求週期中寫入的任何資料可以在週期結束前立即從資料庫讀取剛寫入的資料。可以根據你的應用程式需求而決定是否要使用這個選項。

由於有replica lag的關係,所以會取不到

所以就解開了為啥測試環境沒事,一上正式就爆炸的關係

測試只有建立單顆讀寫所以沒這問題…

結論

因讀寫在同一request,在讀寫分離設定下,

需要增加'sticky' => true

database.php中,限定從write db取資料

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
'mysql' => [
'read' => [
'host' => env('DB_READ_HOST', '127.0.0.1'),
],
'write' => [
'host' => env('DB_WRITE_HOST', '127.0.0.1'),
],
'sticky' => true,
'driver' => 'mysql',
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => false,
'engine' => null,
'timezone' => '+08:00',
],