很多時候在討論使用者友善,其實最簡單粗暴,也最有感的改善之一就是讓操作動作變快,也就是讓用戶更快得到他要的東西。畢竟只要操作上有卡頓,用戶馬上就會分心。
之前看 Google Startup School 的 SEO 課程中也有說
網頁 loading 每慢一秒,轉換率就會掉 12%
我們在優化我們 app 的體驗時,很常做的一件事就是去看現在效能瓶頸在哪,然後去改善。
比如之前有個很容易成為效能瓶頸的情景是「隨機配對」功能。這應該是遊戲很常出現的功能,但我們不能說是完全隨機,因為我們還有保證配對兩邊是以前沒有配對過的。
當用戶按下隨機配對,我們要從 Queue 裡面找出「還沒跟他配過對」的人給他,所以最壞情況就是每次用戶按一次這個鈕,都要回去查找一遍目前所有存在的配對來決定。關於這個動作的改善,我們有過三種版本:
最一開始,很單純的,就是每次從現有的對話 collection 裡查找,頂多把 userID 設為 index。
但是資料量變大,時間跨度變大時,mongoDB 的話,一定會有一部份舊資料會放在 disk,導致每次查找都會出現 disk I/O ,因為這是一個很高頻的操作,所以每次都有 disk 的操作會非常沒效率。於是我們自然開始思考要怎麼改善。
號稱最快的資料庫 Redis,因為是完全在memory上處理,剛好符合我們的需求,所以我們就加了一個 Redis的 node,紀錄所有配對過的帳號,專門用來解決這個問題。 Redis 用一個獨立的 node 而不是跟後端程式放在一起,原因是,我們當時的後端已經有好幾個 node。如果把 Redis 部署在其中一個 node,就會導致這些後端的 instance 產生 dependency。更不可能部署在所有的 node,這樣就無法有一個單一的正確的 snapshot。
Redis 的好處是保障所有查找都是 in-memory ,解決了 mongo 的 disk I/O 的負擔。但是量大之後,還是會受限於 Redis 所在 node 的規格,此時可以選擇就直接花錢提升 CPU 解決,或是再從架構上改善。
小團隊節儉就是美德,改善規格看似每個月不貴,但一提升就是會變成每個月的固定支出,不可不慎呀。所以我們當然是選擇從架構上改善。
導入 Redis 之後,還是會有問題的情況是,重度用戶會在短時間內按好幾次配對,所以只要尖峰時段有很多重度用戶,就會塞車。所以我們在進入 Redis 查找之前,另外加上一個 30 分鐘過期的 cache,紀錄最近30分鐘內的配對,只要在裡面找到,就不用再去 redis 找。針對重度用戶的使用情境,這個方法可以省掉很多 redis 的 query。 30 分鐘的 cache 也不會造成記憶體太大負擔。
一開始為了解決 mongo 的負擔,在查詢過往配對上我們改用 redis 來實作。後來因為 redis 也不夠用,我們為了降低資料庫查找頻率,加入了 30 分鐘的 cache。目前流程就是會先看有沒有 cache,沒有的話就是去 Redis 查找。這個方法開始用之後,就幾乎沒聽過有人抱怨這個功能的速度了。
讓操作變快變順暢,是很直觀的用戶體驗優化,但是實際上要做的事通常並不像是改介面那麼直觀。
最新文章會分享在臉書:https://www.facebook.com/gigi.wuwu/
歡迎留言討論