---
# System prepended metadata

title: redis 筆記

---

# redis 筆記

### 搭配簡報服用
https://github.com/TritonHo/slides/blob/master/Taipei%202019-06%20talk/redis-2019.pdf

redis 是 single thread
multi-thread 的話應該用 memcached
跑 lua 的時候會從頭跑尾，是一個 atomic 的操作
所以如果要看看 data 再決定操作，就用 lua

sortset 是 O(logN)

需要保證工作都是很短的 operate ，不然會卡住其他所有東西。

### skill set

類似用 maindb ，能不在 redis 上面做的東西就不在上面做，像是 sort 這種事情。
一個 data 只能放在一個地方。
超多人來 access 的話就會卡住。

DB commit ok 就是已經存到硬碟裡面

redis write ok 只代表接收到在 memory 裡面，這個時候 power down 的話會掉資料

### 

很多公司會用 redis cluster
lua 如果只跑一個 key 才是 atomic 的，一個 data 只在一個 instance 上

如果你這個 lua 用到別的 key，那就會去別的地方上拉，那就不是 atomic 的


optimistic lock
拿到 last time update，會把 original time stamp 回傳

最簡單 implemant
用 hash 一次存 time 跟 data
寫一個 lua 去確認 master time stamp 來確認。
這樣就會整個 hash set 一起放到 node 裡面。
有時候不用 key value 是因為 atomic 的原因

hash[abc] -> data, ts
跑 lua 的時候一次把 hash 出來的 value 一次塞進去
lua(key, newvalue, timestamp)

lua 別當 store proposal 來寫，盡可能簡單，不要跑 for 之類的。

### 常犯錯誤

只用 local cache

這樣 auto scale out 的時候 main db 的流量會爆炸。
因為新開的沒有 local cache，全部都要從 DB 重新拉，會瞬間打大量流量。

流量越高， cache 使用量越高，但記憶體量是固定的，所以 cache miss 也會上升，最後就會雪崩式的當機。

高流的 cache miss 用類似西哥 proxy 的方式處理
只有一個人去 DB access ，然後剩下近來的人先 lock 住，直到第一個人拿回來
然後剩下的人拿 lock 在檢查一次，有則回傳
這部份是在 server 做的。很多人會少第三步。

concurentcy 的問題 ut 完全測不出來，只有 eyes 看得出來，沒事不要自己刻。
> 這裡軟絲第一個回答被稱讚了一下，軟絲覺得 hen 開心

if -> getlock -> do -> release 這樣會錯。
if -> getlock -> if -> do -> release 這樣才會對，也能增加效能。

if -> getlock 中間要是 atomic 的。

33 33 33
-> 25 25 25 25
   -8 -8 -8 +25
   
不要全部依賴 auto scaleing，可以先跟業務討論，預熱機器。

consistency hash 很重要，但不要自己寫，用網路上的強大 lib

### cache 預熱
寫一個 crontab 每一分鐘跑一次讓 redis 永遠都有 cache

### 什麼 data 要在 reldb
reldb 只有 end user 需要的 data 才在 data base

### ttl 一定要設
不然只有在 peak hours 才會發生 cache eviction，而且是 write 才會發生，這時候就會雪崩。
所以一定要設 ttl ，讓 redis 沒事就會清資料，而且不會清錯。

ttl 時間到的時候不會馬上清，他會挑 cpu 低的時候才清

### 把 redis 當 lock server

redis 沒有 block ，所以只能一直 poll，但這樣就會失去 FIFO 的能力。

SETEX key value

能 set 才操作，反之不操作。

while(1)
setex
    if ! {
        sleep(t)
}

t 可以不斷 *2 ，重試次數會大量減少

一定要有 ttl，不然如果 server 拿到 lock 之後掛掉就會卡死。

 
server A -> getlock
server B 


psuedo-thread-id

barrier 很危險，如果 client 掛掉會全炸。
這樣就永遠沒辦法還完

用多個 cron 在這種場合比較好

## rate limiting

不要 C10K 就用 nginx 內建的 rate limiting 就好
流量高的話才會用到，沒必要不要自己做，開機器就好。

流量高代表有賺錢，有賺錢開機器就不是問題。
另一叫 leaky bucket ，通常是用 token bucket(以下都是用 redis 做 rate limiting 才會用到)
用 lua 可以做簡單的 hash 計算，用 last update time 來算 current value
local memory 也要控制 redis 的存取次數
做不到完全的公平性的。

每 0.1 秒新增一個蘋果，菜籃最多 100 個。
算 max qps 的時候要加上 local buffer 的總蘋果數量。

reboot 的時候，蘋果數量應該是？
不應該是 0 ，做 hard reboot 應該要保留 buffer/2 的蘋果，不然 QPS 會突然暴跌。

為什麼 avg 是 (buffer - 1) / 2

因為 buffer 裡面的可能性是 0 ~ 9，所以 avg 就是取一半 4.5

在 load balance 上做。

有需求才會需要自己做 rate limiting(客製化 limit)

## data snapshotting

建立 crontab 固定存
資料量很大，記得做壓縮。
可以省下很多錢，在 application server 做壓縮， redis 只存放壓縮過得資料

但這樣會浪費 memory 

所以如果沒改動，後面 ts 的 data 可以 reference 到之前的，還有記得把 ttl 變長

如何比較

1. 每次備份都做比對
2. 每次修改的時候把 flag 設為 dirty (performance)

通常 local cache 的 ttl 很短，不過因為 snapshot 的內容本身是不會變動的。
所以 ttl 應該要跟 redis 一樣長

最爛的系統，是沒有人用的系統。

多少比例要開新的 redis

master slave 不是好得架構，因為要用 heart beat 做確認，這中間需要 timeout 才能 slave 上去。

什麼時候開用 cache 的用量，cpu 快滿的話有錢就可以開機器，沒錢就用 rdbtool 然後分析看誰吃了最多 memory 再去思考改進方案。

最花錢的是 develope time ，第二個就是 IO