【第六講,Redis的高并發實戰:搶購系統】
講師:淺奕,阿裡雲NoSQL核心工程師。
課程内容:IO模型和問題;資源競争,與分布式鎖;如何利用Redis的高并發原理做搶購系統。
答疑彙總:特感謝班委@張鵬 同學

1. zset 和 hash 的配合使用
zset 存儲主鍵 key 和分數,然後 key 用 hash, 這樣容量和緩存占比應該是最小的。但是問題是批量查詢,zset 是有一個還是很多個,如果是一個,要小心成為熱點 key 。hash 有一個 mget ,可以拿一個hash 的多個字段,但是多個 hash 是沒有相關 API 一次性拿的,原因是多個 hash 的 key 可能存在叢集的多個分片上。
2. 用 stream 實作一個消息隊列?
使用方法類似于 kafka , 需要有producer, consumer group, topic 等。
3. 緩存怎麼和資料庫保持強一緻?
首先是很難保證的,應該盡量避免資料不一緻。如果出現不一緻,要以最可靠的資料庫做一個兜底。要避免這個問題,主要是解決緩存在更新的時候。一種方式是隻有一個線程寫,定時從資料庫更新資料到緩存,可以監聽資料庫 binlog 的修改,更新緩存。另一種方式是業務線程來更新,先持久化再删除緩存,然後讀邏輯來更新緩存。緩存一般是要設定過期時間的。
4. Set 和 Sorted Set對性能是否有影響?
Redis 的資料結構為了省記憶體,編碼是有兩種或兩種以上的,在配置裡邊會有一個預設值,比如可以設定 set 它在成員小于多少的時候是一個清單,大于的時候是一個哈希結構。hash 結構的查詢效率是O(1), 排序集合使用跳表,成員小于一定數量是使用壓縮表。一般情況不要調大這個參數值,可以改小這個參數值,盡量用稀疏的資料結構,用 hash和跳表,不要使用壓縮結構,壓縮結構查詢和插入效率一般都是O(n) 的。
5. 秒殺場景節點多少個比較好?
看業務需求了,單分片單key 的能力是 QPS 10萬左右,然後對業務的預估确定分片數,理想情況,查詢比較散的情況下,根據總的QPS 計算,預留 30% 的水位就可以了。
分片太多也不好,正常的通路是沒問題的,隻是發生變化的時候,用戶端會有比較多的錯誤。如果是開源版,節點比較多叢集Gossip 協定廣播會比較厲害。
6. Lua 的問題是不是可以使用單獨叢集處理?
Lua 需要慎用,但不是不用。我們要清楚正常的一個讀寫能達到 QPS 10萬,如果在lua 裡面可能就隻有8萬了。對性能有一定影響。不要在 lua 裡寫比較複雜的循環。對性能的影響就是lua 本身需要編譯執行。如果 lua 都非常小,不需要單獨叢集處理。主要是控制好lua 執行的時間就好了。
7. 對于大 key 有什麼好的方案?
大 key 一般都是指 list、hash、set 這類資料結構,list 沒有什麼好的解法,可以将list 拆分成多個 list ,但是對于業務來說是比較難處理的,建議盡量避免大 key。
8. Redis 的 key 或value 用string 或 byte數組有什麼差別嗎?
對于服務端來說沒有什麼差別,主要看用戶端是怎麼實作的,比如看最終key 或 value 是怎麼序列化的,最終發的時候肯定是一個序列化對象,發到服務端存儲的時候就是一個位元組數組。隻是比如在執行incr 的時候,會對 value 做一個數字解析。
9. Memcached 和 Redis 怎麼選?
Memcached 隻有 k-v 操作和原子計數操作,Memcached 是多線程方式,單分片性能可能優于Redis,但是資料結構支援較少。業務比較簡單隻用key-value結構和incr 操作的話,可以選擇Memcached。memcached 資料導入導出比較困難,如果需要,建議選擇Redis,而且 Redis 社群比較活躍一點。
10. Mysql 和 Redis 的同步?
一般的方案是監聽 mysql 的 binlog 的變動,然後解析出原始資料操作,去 Redis更新資料。