使用Redis的理由

使用Redis的理由 

  Redis是一個遠程內存數據庫,它不僅性能強勁,而且還具有複製特性以及爲解決問題而生的獨一無二的數據模型。Redis提供了5種不同類型的數據結構,各式各樣的問題都可以很自然地映射到這些數據結構上:Redis的數據結構致力於幫助用戶解決問題,而不會像其他數據庫那樣,要求用戶扭曲問題來適應數據庫。除此之外,通過複製、持久化(persistence)和客戶端分片(client-side sharding)等特性,用戶可以很方便地將Redis擴展成一個能夠包含數百GB數據、每秒處理上百萬次請求的系統。

   筆者第一次使用Redis是在一家公司裏面,這家公司需要對一個保存了6萬個客戶聯繫方式的關係數據庫進行搜索,搜索可以根據名字、郵件地址、所在地和電話號碼來進行,每次搜索需要花費10~15秒的時間。在花了一週時間學習Redis的基礎知識之後,我使用Redis重寫了一個新的搜索引擎,然後又花費了數週時間來仔細測試這個新系統,使它達到生產級別,最終這個新的搜索系統不僅可以根據名字、郵件地址、所在地和電話號碼等信息來過濾和排序客戶聯繫方式,並且每次操作都可以在50毫秒之內完成,這比原來的搜索系統足足快了 200 倍。

 

1、Redis簡介

  前面對於Redis數據庫的描述只說出了一部分真相。Redis是一個速度非常快的非關係數據庫(non-relational database),它可以存儲鍵(key)與5種不同類型的值(value)之間的映射(mapping),可以將存儲在內存的鍵值對數據持久化到硬盤,可以使用複製特性來擴展讀性能,還可以使用客戶端分片1來擴展寫性能。

 

2、使用Redis的理由

  有memcached使用經驗的讀者可能知道,用戶只能用APPEND命令將數據添加到已有字符串的末尾。memcached的文檔中聲明,可以用APPEND命令來管理元素列表。這很好!用戶可以將元素追加到一個字符串的末尾,並將那個字符串當作列表來使用。但隨後如何刪除這些元素呢?memcached採用的辦法是通過黑名單(blacklist)來隱藏列表裏面的元素,從而避免對元素執行讀取、更新、寫入(包括在一次數據庫查詢之後執行的memcached寫入)等操作。相反地,Redis的LIST和SET允許用戶直接添加或者刪除元素。

  使用Redis而不是memcached來解決問題,不僅可以讓代碼變得更簡短、更易懂、更易維護,而且還可以使代碼的運行速度更快(因爲用戶不需要通過讀取數據庫來更新數據)。除此之外,在其他許多情況下,Redis的效率和易用性也比關係數據庫要好得多。

  數據庫的一個常見用法是存儲長期的報告數據,並將這些報告數據用作固定時間範圍內的聚合數據(aggregates)。收集聚合數據的常見做法是:先將各個行插入一個報告表裏面,之後再通過掃描這些行來收集聚合數據,並根據收集到的聚合數據來更新聚合表中已有的那些行。之所以使用插入行的方式來存儲,是因爲對於大部分數據庫來說,插入行操作的執行速度非常快(插入行只會在硬盤文件末尾進行寫入)。不過,對錶裏面的行進行更新卻是一個速度相當慢的操作,因爲這種更新除了會引起一次隨機讀(random read)之外,還可能會引起一次隨機寫(random write)。而在Redis裏面,用戶可以直接使用原子的(atomic)INCR命令及其變種來計算聚合數據,並且因爲Redis將數據存儲在內存裏面2,而且發送給Redis的命令請求並不需要經過典型的查詢分析器(parser)或者查詢優化器(optimizer)進行處理,所以對Redis存儲的數據執行隨機寫的速度總是非常迅速的。

  使用 Redis 而不是關係數據庫或者其他硬盤存儲數據庫,可以避免寫入不必要的臨時數據,也免去了對臨時數據進行掃描或者刪除的麻煩,並最終改善程序的性能。雖然上面列舉的都是一些簡單的例子,但它們很好地證明了“工具會極大地改變人們解決問題的方式”這一點。

 

3、Redis與其他數據庫和軟件的對比

  如果你熟悉關係數據庫,那麼你肯定寫過用來關聯兩個表的數據的SQL查詢。而Redis則屬於人們常說的NoSQL數據庫或者非關係數據庫:Redis不使用表,它的數據庫也不會預定義或者強制去要求用戶對Redis存儲的不同數據進行關聯。

  高性能鍵值緩存服務器memcached也經常被拿來與Redis進行比較:這兩者都可用於存儲鍵值映射,彼此的性能也相差無幾,但是Redis能夠自動以兩種不同的方式將數據寫入硬盤,並且Redis除了能存儲普通的字符串鍵之外,還可以存儲其他4種數據結構,而memcached只能存儲普通的字符串鍵。這些不同之處使得Redis可以用於解決更爲廣泛的問題,並且既可以用作主數據庫(primary database)使用,又可以作爲其他存儲系統的輔助數據庫(auxiliary database)使用。

  本書的後續章節會分別介紹將Redis用作主存儲(primary storage)和二級存儲(secondary storage)時的用法和查詢模式。一般來說,許多用戶只會在Redis的性能或者功能是必要的情況下,纔會將數據存儲到Redis裏面:如果程序對性能的要求不高,又或者因爲費用原因而沒辦法將大量數據存儲到內存裏面,那麼用戶可能會選擇使用關係數據庫,或者其他非關係數據庫。在實際中,讀者應該根據自己的需求來決定是否使用Redis,並考慮是將Redis用作主存儲還是輔助存儲,以及如何通過複製、持久化和事務等手段保證數據的完整性。展示了一部分在功能上與Redis有重疊的數據庫服務器和緩存服務器,從以下表中可以看出Redis與這些數據庫及軟件之間的區別。

 

一些數據庫和緩存服務器的特性與功能

名稱

類型

數據存儲選項

查詢類型

附加功能

Redis

使用內存存儲(in-memory)的非關係數據庫

字符串、列表、集合、散列表、有序集合

每種數據類型都有自己的專屬命令,另外還有批量操作(bulk operation)和不完全(partial)的事務支持

發佈與訂閱,主從複製(master/slave replication),持久化,腳本(存儲過程,stored procedure)

memcached

使用內存存儲的鍵值緩存

鍵值之間的映射

創建命令、讀取命令、更新命令、刪除命令以及其他幾個命令

爲提升性能而設的多線程服務器

MySQL

關係數據庫

每個數據庫可以包含多個表,每個表可以包含多個行;可以處理多個表的視圖(view);支持空間(spatial)和第三方擴展

SELECT、INSERT、UPDATE、DELETE、函數、存儲過程

支持ACID性質(需要使用InnoDB),主從複製和主主複製 (master/master replication)

PostgreSQL

關係數據庫

每個數據庫可以包含多個表,每個表可以包含多個行;可以處理多個表的視圖;支持空間和第三方擴展;支持可定製類型

SELECT、INSERT、UPDATE、DELETE、內置函數、自定義的存儲過程

支持ACID性質,主從複製,由第三方支持的多主複製(multi-master replication)

MongoDB

使用硬盤存儲(on-disk)的非關係文檔存儲

每個數據庫可以包含多個表,每個表可以包含多個無schema(schema-less)的BSON文檔

創建命令、讀取命令、更新命令、刪除命令、條件查詢命令等

支持map-reduce操作,主從複製,分片,空間索引(spatial index)

 

4、Redis附加特性

  在使用類似Redis這樣的內存數據庫時,一個首先要考慮的問題就是“當服務器被關閉時,服務器存儲的數據將何去何從呢?”Redis擁有兩種不同形式的持久化方法,它們都可以用小而緊湊的格式將存儲在內存中的數據寫入硬盤:第一種持久化方法爲時間點轉儲(point-in-time dump),轉儲操作既可以在“指定時間段內有指定數量的寫操作執行”這一條件被滿足時執行,又可以通過調用兩條轉儲到硬盤(dump-to-disk)命令中的任何一條來執行;第二種持久化方法將所有修改了數據庫的命令都寫入一個只追加(append-only)文件裏面,用戶可以根據數據的重要程度,將只追加寫入設置爲從不同步(sync)、每秒同步一次或者每寫入一個命令就同步一次。我們將在第4章中更加深入地討論這些持久化選項。

   另外,儘管Redis的性能很好,但受限於Redis的內存存儲設計,有時候只使用一臺Redis服務器可能沒有辦法處理所有請求。因此,爲了擴展Redis的讀性能,併爲Redis提供故障轉移(failover)支持,Redis實現了主從複製特性:執行復制的從服務器會連接上主服務器,接收主服務器發送的整個數據庫的初始副本(copy);之後主服務器執行的寫命令,都會被髮送給所有連接着的從服務器去執行,從而實時地更新從服務器的數據集。因爲從服務器包含的數據會不斷地進行更新,所以客戶端可以向任意一個從服務器發送讀請求,以此來避免對主服務器進行集中式的訪問。我們將在第4章中更加深入地討論Redis從服務器。

 

技術分享

 

 

鏈接:http://www.epubit.com.cn/article/200

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章