1. 程式人生 > >為寫入效能優化:Redis

為寫入效能優化:Redis

http://book.51cto.com/art/201505/475427.htm

從表面上看,眾多的分散式資料庫似乎涵蓋了許多相同的用例。因此,當試圖選擇一個非關係資料庫解決方案時,新手們往往困惑不已。事實上,這些流行的非關係資料庫往往偏執於某一方面。有些為了能便於分佈到多臺機器上而以犧牲資料一致性為代價。其他一些則專注於提高資料讀寫速度。當你在多個非關係資料庫中做選擇時,你也必須堅持自己的主見。選擇資料庫最重要的目標是瞭解你具體的使用情況。

作為例子,讓我們試圖明確我們應用的首要目標,並選擇能實現該目標的合適的資料庫解決方案。在這個過程中,我們將逐步瞭解擴充套件自己所選的資料庫時所面臨的挑戰。一個越來越普遍的使用案例是那些需要快速執行大量資料庫插入操作的應用。小型開發團隊可能希望構建一個Web 應用程式,它能處理來自數千個甚至數百萬使用者的訊息。又或許用例是一個在某個電視節目播出時能滾動顯示提到該節目的推文的應用。類似地,某個應用也許要彙集來自世界各地成千上萬個氣象感測器的資料。這種設計模式在網路遊戲界也很常見。許多社會化多玩家遊戲提供遊戲重放的功能,並且將遊戲環境的統計資料公開地廣播。在這種情況下,隨時都可能有來自數千甚至數百萬玩家的資料流持續不斷地匯入應用的後端中。

在以上的例子中,查詢的靈活性相比於非常迅速地收集資料的能力顯得不那麼重要。對於此型別的應用,鍵- 值儲存是很好的選擇,因為該模型的簡單性使得資料庫的寫入操作儘可能地快。這種鍵- 值的設計也非常適用於分散式應用,此時選擇資料庫的哪一部分進行分片不是特別的重要。滿足這些條件的一個數據庫是開源的鍵- 值儲存Redis。網站DB-Engines.com4 聲稱Redis 是目前最流行的鍵- 值資料儲存,該網站使用搜索引擎的結果數量和諸如StackOverflow.com 等論壇上技術問題的數量等指標對最流行的資料庫軟體進行排名。

對於那些有快速讀寫效能需求的應用來說,Redis 很多有趣的特性使其成為一個不錯的選擇。Redis 基本上是一種“記憶體”資料庫,這意味著它使用伺服器的可用記憶體來儲存整個資料庫。這看上去似乎是一個很大的限制,因為你需要為你的應用提供足夠的硬體(無論是物理的,還是虛擬的),而且一旦斷電,你的資料很可能會丟失。別這麼著急下結論! Redis 還可以提供ACID 中“D”的特性:永續性。Redis 提供了可配置的選項,將記憶體中的資料持久化寫入磁碟。換句話說,Redis 提供了基於記憶體的易失的,但高效能的讀寫資料的功能;同時也提供了基於磁碟的資料快取的永續性。

正如資料世界中的所有事物一樣,巨大的優勢需要以犧牲其他方面為代價。在此處,這個其他方面就是一致性。例如,如果該記憶體資料庫設定為每隔10 秒就將資料持久化到磁碟上,而在這段時間內(比如由於電源故障)記憶體失效了,資料就將會丟失。記錄數以千計的線上遊戲玩家分數的高流量的Web 應用將會產生大量的資料。也可以讓Redis 將每個寫操作都持久化到磁碟上,從而提供非常好的永續性。但不幸的是,這將大大降低Redis 的效能,抵消了使用記憶體資料庫帶來的好處。在這些功能之上,Redis 也提供易於配置的複製功能,允許主例項非同步地將更新流式傳輸到備用伺服器上。

通過資料的鍵,Redis 在快速設定和獲取資料方面表現優秀。但由於它是一個鍵- 值儲存,Redis 不允許查詢直接訪問由鍵所指的值。如果你的應用需要不同型別的功能,例如需要基於資料本身的內容快速檢索,那麼其他型別的非關係資料庫(例如文件儲存)可能會更合適。

清單3.4 展示瞭如何通過Redis 命令列介面執行基本的命令來插入和檢索單個值、列表和雜湊結構。

清單3.4 使用Redis 處理單個值、列表和雜湊結構

  1. # Setting values by key  
  2. > SET user:1:name 'Michael'  
  3. > SET user:2:name 'Ben'  
  4. # Retrieve a list of keys matching a pattern  
  5. > KEYS user*  
  6. 1) "user:2:name"  
  7. 2) "user:1:name"  
  8. # Retrieving a value using the respective key  
  9. > GET user:2:name  
  10. "Ben"  
  11. # Using lists - LPUSH adds values to the head of a list  
  12. > LPUSH names 'Jared'  
  13. > LPUSH names 'Melinda'  
  14. # Retrieve a range of values from a list  
  15. > LRANGE names 0 1  
  16. 1) "Melinda"  
  17. 2) "Jared"  
  18. # RPUSH adds values to the tail of the list  
  19. > RPUSH names 'Debra'  
  20. > LRANGE names 0 2  
  21. 1) "Melinda"  
  22. 2) "Jared"  
  23. 3) "Debra"  
  24. # Using hashes - HMSET sets fields to their respective values for a  
  25. # hash stored at a key  
  26. > HMSET employees:1 name 'Michael' city 'San Francisco' role 'Author'  
  27. # Retrieve the "name" attribute of the hash "employees:1"  
  28. > HGET employees:1 name  
  29. "Michael"  
  30. Manoochehri_Book.indb 37 11/20/13 1:59 PM  
  31. 38 Chapter 3 Building a NoSQL-Based Web App to Collect Crowd-Sourced Data  
  32. # Retrieve all keys and values of the hash "employees:1"  
  33. > HGETALL employees:1  
  34. 1) "name"  
  35. 2) "Michael"  
  36. 3) "city"  
  37. 4) "San Francisco"  
  38. 5) "role"  
  39. 6) "Author" 

當電源關掉時,計算機記憶體中的內容就會丟失。儲存永續性資料是磁碟的職責。Redis 是一個“記憶體”資料儲存,所以當有人被電源線絆倒致使你的伺服器關閉時會有何後果?整個資料庫都會被刪除嗎?當然不完全如此:Redis 通過提供將資料持久化到磁碟上的選項完善了記憶體系統的功能。當資料量非常巨大時,我們必須考慮多方面的權衡。例如,我們是否需要在任何時候都保持完全的資料一致性?如果遇到突然斷電的情況,我們的應用是否能接受丟失最後一分鐘的資料?有許多應用完全不需要持久化,因此對於這類應用,完全可以將Redis 的持久化關閉。