互聯網和Web的蓬勃發展正在改變着我們的世界,隨着互聯網的不斷發展和壯大,企業數據規模越來越大,並發量越來越高,關系數據庫無法應對新的負載壓力,隨着Hadoop,Cassandra,MongoDB,Redis等NoSQL數據庫的興起,因其良好的可擴展性,弱化數據庫的設計范式,弱化一致性要求,在解決海量數據和高並發的問題上明顯優於關系型數據庫。因而很快廣泛應用於互聯網業務中。
Redis作為基於K-V的NoSQL數據庫,具有高性能、豐富的數據結構、持久化、高可用、分布式、支持復制等特性。從09年至今,經歷8年多的錘煉,已經非常穩定,並且得到業界的廣泛認可和使用,同時社區非常活躍。
團隊工作重心
微博研發中心數據庫部門主要負責全微博平台的后端資源的托管和運維,涉及的資源種類比較多,數據量比較大,業務線和資源實例數目也是非常之多,並發量巨大。而這些正是微博這種體量的公司應該具有的,微博作為當今中文社交媒體的第一品牌,擁有超過3.76億的月活用戶,也是當前社會熱點事件傳播的最主要平台,其中包括但不限制於大型活動(如:里約奧運會、朱日和沙場大點兵等),春晚,明星動態(如:王寶強離婚事件、女排奪冠、喬任梁去世、白百合出軌、TFBOYS生日、鹿晗關曉彤CP等)。
而熱點事件往往具有不可預見性和突發性,並且伴隨着極短時間內流量的數倍增長,甚至更多,有時持續時間較長。如何快速應對突發流量的沖擊,確保線上服務的穩定性,是一個非常巨大的挑戰和有意義的事情。為了達到這一目標,需要有一個完善的,穩定可靠的,健壯的數據庫運維體系來提供支撐和管理,所以我們團隊也是在領導的指導下,有目標、有計划的開展一些數據庫自動化運維平台的建設工作。
重大的變化與核心變化
Redis的版本號命名規則借鑒了Linux的方式,版本號第二位如果是奇數,則為非穩定版本,如果為偶數,則為穩定版本。
穩定版本的一些主要改進吧:
-
Redis2.6
1)鍵的過期時間支持毫秒
2)從節點提供只讀功能
3)服務端支持Lua腳本
4)放開客戶端連接數的硬編碼限制
5)去掉虛擬內存相關功能等 -
Redis2.8
1)完善主從復制功能,實現增量復制
2)Redis設置明顯的進程名,在系統中ps命令即可查看
3)發布/訂閱添加pub/sub命令
4)Redis Sentinel第二版發布,較Redis 2.6更加完善,可以線上使用
5)可以通過config set命令設置maxclients等 -
Redis3.0
1)推出Redis的分布式集群 Redis Cluster
2)全新的embedded string對象編碼結果,優化小對象的內存訪問,在特定的工作負載下能大幅度提升性能
3)LRU算法提升
4)config set 設置maxmemory的時候可以設置不用的單位
5)新的Client pause命令,在指定時間內停止處理客戶端請求等 -
Redis3.2
1)添加GEO功能
2)新的List編碼類型quicklist
3)SDS在速度和節省空間上都做了優化
4)Lua腳本功能增強
5)新的RDB格式,仍兼容舊版RDB,同時加載速度上也有提升
6)Cluster nodes命令加速等 -
在Redis4.0版本上,我認為最核心的功能應該是支持了module,這極大的豐富的Redis的功能,使得許多Redis本身不具有的,第三方開發者拓展的功能也能加載到Redis中當一個功能進行使用,比如RediSearch、ReJSON、Redis-ML等。除此之外,還看到有很多新特性:
1)psync2.0,優化了之前版本主從節點切換必然引起全量復制的問題
2)提供全新的緩存剔除算法LFU,並對已有算法進行了優化
3)提供了非阻塞del和flushall和flushdb功能,有效解決了刪除bigkey可能造成的Redis阻塞
4)提供了RDB-AOF混合持久化格式
5)提供memory命令,實現對內存的更為全面的監控統計
6)Redis Cluster 兼容NAT和Docker
7)引入Jemalloc庫,優化內存訪問等等
Redis中的數據類型和它們的使用場景
Redis之所以能夠被廣泛的應用於企業的架構中,而且是不可或缺的重要組成部分,也可以說是標配吧,其中很重要的一點就是得益於它具有豐富的數據結構,這也是它逐漸替代Memcached,備受青睞的重要原因。那么Redis都提供哪些數據類型呢?
相信對Redis有了解過的同學都知道,它的數據類型有:String、Hash、List、Set、Zset、Bitmaps、HyperLogLog、GEO等。
隨着互聯網的興起和Redis技術的不斷完善和發展,它已經被廣泛應用於各行各業中,應用場景也是百花齊放。比如:會話緩存(Session cache)、全頁緩存(FPC)、手機驗證碼、訪問頻率限制/黑白名單、消息隊列、發布與訂閱、消息通知、排名/排行榜/最新列表、計數器(比如微博的轉評贊計數、閱讀數(瀏覽數,視頻播放計數)、博文數(發帖數)、粉絲數、關注數(喜歡商品數)、未讀數(動態數))、共同好友/喜好/標簽、推送、下拉刷新、私信、商品庫存管理(限時的優惠活動信息)、證券指標實時計算,發號器/UUID、以及隨着LBS(基於位置服務)的發展,加入的GEO(地理信息定位)的功能和基於Lua自定義命令或功能等等。大家在使用過程中,需要結合自己的業務場景,選擇正確的數據類型。
Redis數據庫主要的特點和優勢
Redis作為基於K-V的NoSQL數據庫,具有高性能、豐富的數據結構、持久化、高可用、分布式、支持復制等特性。從09年至今,經歷8年多的錘煉,已經非常穩定,並且得到業界的廣泛認可和使用,同時社區非常活躍,開發者又很嚴謹,這使得Redis版本非常精簡,bug fix非常高效。根據similarweb.com的統計,中國Redis用戶占全球Redis用戶的40.96%,所以我們在使用的過程中遇到的問題,大部分可能都有解決方案。
-
需要關注的點比較多:
1)安全問題:Redis用非root用戶啟動,並且運行在內網,盡可能不要暴露在外網,配置認證requirepass xxx,減少被攻擊的風險;開啟危險命令認證(keys-need-auth yes rename-command KEYS MY_KEYS)2)容量問題:合理評估;合理使用內存分配策略(no-enviction、allkeys-random、allkeys-lru、volatile-random、volatile-ttl、volatile-lru);檢查是否有內存碎片;選擇合適的服務類型(Redis cluster或者pika);水平拆分;性能滿足的條件下選擇諸如ziplist類的內部編碼
3)big-key問題:可能會引起慢查或者帶寬瓶頸,按照業務邏輯拆成小key或者業務解耦剝離big-key或直接改用其他存儲方式
4)hot-key問題:Redis是單進程,節點實例很容易成為系統的短板,垂直擴容;增加local cache;如果只是簡單的k-v結構,可以考慮使用Memcached
5)使用姿勢問題:避免使用阻塞操作(如:flushall、flushdb、keys *等);盡量使用Pipeline,減少syscall帶來的網絡IO,但要注意限制數據量大小;對多個元素操作時,像使用SORT、LREM、SUNION,計算復雜度為O(N), 避免線上亂用;盡可能使用最新的版本
6)Key過期問題:合理設置過期時間;如果存在許多該過期的key而沒被及時刪除,可以通過命令scan、hscan、sscan、zscan、keys *遍歷一遍key的方式實現
7)配置上:建議開啟tcp-keepalive,tcp-backlog,從庫設置readonly yes
8)系統設置:關閉NUMA;關閉transparent _hugepage; 關閉swap
Redis如何做消息隊列
Redis做消息隊列,有兩種實現方式:
第一種:通過數據結構List來實現
優點:
- 能夠實現持久化;支持集群;接口使用簡單
缺點:
- 如上圖所示,一條消息只會被一個消費者消費,所以不存在有多個消費者消費一條消息
- 生產者和消費者的高可用或崩潰后的處理機制需要自己實現
- 當生產者消息寫入太快,消費者消費太慢,則有可能會導致內存溢出問題,導致進程crash
第二種:通過pub/sub來實現
優點:
一個生產者可以對應多個消費者,但是必須保證消息發布者和消息的訂閱者同時在線,否則,否則一旦消息訂閱者由於各種異常情況而被迫斷開連接,在其重新連接后,其離線期間的消息是無法被重新通知的(即發即棄)。當然,生產者不需要關心有多少的訂閱者,也不用關心訂閱者的具體信息,而訂閱者可以根據需要自由選擇訂閱哪些頻道:支持集群;接口使用簡單等。
缺點:
- 沒有持久化機制,屬於即發即棄模式,因此也不需要制定消息的備份和恢復機制
- Redis沒有提供保證pub/sub消息性能的方案
- 當大量的消息到達Redis服務時,如果訂閱者不能及時完成消費,則就會導致消息堆積,引發上面一樣的內存問題
當前Redis的集群功能和實現
要了解Redis的集群功能,可以從數據分片、數據遷移、集群通訊、故障檢測以及故障轉移等方面進行了解,Cluster相關的代碼也不是很多,注釋也很詳細,可自行查看,地址是:https://github.com/antirez/redis/blob/unstable/src/cluster.c
這里由於篇幅的原因,主要從數據分片和數據遷移兩方面進行詳細介紹:
- 數據分片
Redis cluster在設計中沒有使用一致性哈希(consistency hashing),而是使用數據分片(sharding),引入哈希槽(hash slot)來實現;一個 redis cluster包含16384(0~16383)個哈希槽,存儲在redis cluster中的所有的鍵都會被映射到這些slot中,集群中的每個鍵都屬於這16384個哈希槽的其中一個,集群使用公式slot=CRC16(key)/16384來計算key屬於哪個槽,其中CRC16(key)語句用於計算key的CRC16 校驗和。
集群中的每個主節點(Master)都負責處理16384個哈希槽中的一部分,當集群處於穩定狀態時,每個哈希槽都只由一個主節點進行處理,每個主節點可以有一個到N個從節點(Slave),當主節點出現宕機或網絡斷線等不可用時,從節點能自動提升為主節點進行處理。
如上,clusterNode數據結構中的slots和numslots屬性記錄了節點負責處理哪些槽。其中,slot屬性是一個二進制位數組(bitarray),其長度為16384/8=2048 Byte,共包含16384個二進制位。集群中的master節點用bit(0和1)來標識對於某個槽是否擁有。比如,對於編號為1的槽,master只要判斷序列的第二位(索引從0開始)的值是不是1即可,時間復雜度為O(1)。
集群中所有槽的分配信息都保存在clusterState數據結構的slots數組中,程序要檢查槽i是否已經被分配或者找出處理槽i的節點,只需要訪問clusterState.slots[i]的值即可,復雜度也為O(1)。clusterState數據結構如下所示:
查找關系如下圖:
- 數據遷移
數據遷移可以理解為slot和key的遷移,這個功能很重要,極大的方便了集群做線性擴展,實現平滑的擴容或縮容。
那么它是一個怎樣的實現過程呢?
下面舉個例子:現在要將Master A節點中的編號為1、2、3的slot遷移到Master B節點中,在slot遷移的中間狀態下,slot 1、2、3在Master A節點的狀態表現為MIGRATING,在Master B節點的狀態表現為IMPORTING。
MIGRATING狀態
這個狀態如上圖所示是被遷移slot在當前所在Master A節點中出現的一種狀態,預備遷移slot從Mater A到Master B的時候,被遷移slot的狀態首先變為MIGRATING狀態,當客戶端請求的某個key所屬的slot的狀態處於MIGRATING狀態的時候,可能會出現以下幾種情況:
1)如果key存在則成功處理
2)如果key不存在,則返回客戶端ASK,客戶端根據ASK首先發送ASKING命令到目標節點,然后發送請求的命令到目標節點
3)當key包含多個命令時:
- 如果都存在則成功處理
- 如果都不存在,則返回客戶端ASK
- 如果一部分存在,則返回客戶端TRYAGAIN,通知客戶端稍后重試,這樣當所有的key都 遷移完畢的時候客戶端重試請求的時候回得到ASK,然后經過一次重定向就可以獲取這批鍵
此時並不刷新客戶端中node的映射關系
IMPORTING狀態
這個狀態如上圖所示是被遷移slot在目標Master B節點中出現的一種狀態,預備遷移slot從Mater A到Master B的時候,被遷移slot的狀態首先變為IMPORTING狀態。在這種狀態下的slot對客戶端的請求可能會有下面幾種影響:
1)如果key不存在則新建
2)如果key不在該節點上,命令會被MOVED重定向,刷新客戶端中node的映射關系
如果是ASKING命令則命令會被執行,從而key沒在被遷移的節點,已經被遷移到目標節點的情況命令可以被順利執行。
鍵空間遷移
這是完成數據遷移重要的一步,鍵空間遷移是指當滿足了slot遷移前提的情況下,通過相關命令將slot 1、2、3中的鍵空間從Master A節點轉移到Master B節點,這個過程由MIGRATE命令經過3步真正完成數據轉移。步驟示意如下:
經過上面三步可以完成鍵空間數據遷移,然后再將處於MIGRATING和IMPORTING狀態的槽變為常態即可,從而完成整個重新分片的過程。
Redis的高可用方案
根據業務的規模以及Redis使用環境的不同,Redis的高可用方案也比較多。這里舉一些例子說明一下業界比較常用的一些方案吧。需要說明一下的是下面的這些方案不涉及到同城多活或異地多活的場景,但是部分方案能夠做到跨數據中心的災備。
- Keepalive + Redis
- Redis Sentinel
- Twemproxy + Redis Sentinel + Redis
- Redis Cluster
- Redis Sentinel + Proxy + Zookeeper + Redis
- Zookeeper + MySQL + Redis + DNS
Redis數據庫在向着自動化運維的方向發展的過程中,面臨的最大的挑戰是什么?
我想最大的挑戰應該是“智能化”吧。現在業界都在追捧DevOps、AIOps,那么在Redis的自動化運維過程中,也需要學習行業的先進思想,結合部門自身的實際穩扎穩打,逐一突破。
首先在智能化實現之前,我們要盡力實現下面的一些需求:
1)數據庫運維自動化平台的建設,為RD和DBA提供較全面的自助服務和數據庫管理功能
2)工單事件關聯任務系統,一鍵完成自動安裝部署,添加產品線和報警
3)海量報警智能分類(比如按產品線或按DBA分類),實現部分報警故障自愈 (比如:從庫readonly設置、內存使用率超過95%自動擴容)
4)基於隊列分布式批量部署,可橫向擴展,任務異步調度,滿足大規模部署、擴容的需求
5)日志實時展示,監控數據實時采集,圖形化多維度展示,滿足可視化的需求
6)RedisHA支持秒級響應,實現故障無縫切換,滿足高可用的需求
7)緩存彈性擴縮容(利用私有雲和公有雲,結合Docker容器化技術實現),滿足對熱點的快速應對
8)內部開發了各種通用的管理和運維腳本,化繁為簡,提高工作效率
9)根據歷史/晚高峰資源的性能指標設置水位線,和報警閾值,提供決策支持
10)在Redis集群、容災、異地多活(跨數據中心數據同步)、微服務等等方面還需要花很大的力氣去建設,目前依舊比較欠缺
智能化的實現還需要持續的投入和迭代。
數據庫的未來,會朝着什么樣的方向發展?
是的,這幾年從運維的角度看,明顯能感覺到數據體量上的膨脹,一個實例動不動就幾十G,一個集群動不動幾百G、幾T,甚至更多。以Redis為代表的NoSQL數據庫在處理這方面的表現還是令人非常滿意的。它的高性能表現得淋漓盡致,從微博的業務來看,Redis實例每天承載着千億級的寫QPS、萬億級的讀QPS,數據量TB級,確實沒有Redis,且不說能不能用關系型數據庫存儲,單是硬件成本就幾何倍增長了吧。
未來,隨着硬件成本的降低,硬件性能優化的極致,比如PCIE、25GE網絡的升級,一定是軟硬結合,會出現更多的Redis的相關產品和服務。包括收費的Redis Enterprise,Cloud Redis等,也包括開源的Pika、TiDB等NewSQL。正如阿里雲的同學所說,“數據庫終極是九九歸一 -- 量子數據庫”,一起期待吧。
對於初學Redis的同學,您有什么好的學習方法和技巧給他們嗎?
首先當然還是需要多看官方文檔,多看看業界大牛的技術博客。其次可以買幾本書對比着學習下,目前市面上的相關書籍也就4,5本的樣子。然后主要的還是要多動手,實踐出真知,在使用的過程中,還是要結合具體的業務場景,靈活使用。有能力的時候,看看源碼,了解底層的實現原理。最后,多思考多總結,好記性不如爛筆頭,每一次踩坑都是一次成長,遇到解決不了的問題的時候多向業界大牛們請教學習,平時多關注一些業界相關技術的最新動態。
如何看待Redis的未來?從技術和非技術的多個維度,如何看待Redis的發展方向?
縱觀Redis的發展,無獨有偶的與互聯網的發展浪潮緊緊相隨,從web1.0到web2.0的轉變,從博客、貼吧、論壇到社交媒體,從文本到圖文再到短視頻的興起,從互聯網到移動互聯網,從3G到4G到即將普及的5G,從異軍突起的新興產業,如:團購、電商、外賣、旅游、游戲、互聯網金融和證券、出行和直播等等,商業模式在不斷的改變,不斷的在刷新人們的生活方式。
但是在這些變化的背后,不變的是Redis作為基礎服務為企業的高可用架構保駕護航,變化的是Redis的使用案例越來越豐富、服務體驗越來越好。在Redis的發展過程中,由於企業需求的多樣化,對Redis的要求越來越高,許多場景Redis的功能顯得相形見絀,因此出現了諸如Codis、Pika、CounterService、ApsaraCache、CacheCloud、smartClient(Redisson)等產品,它們是對Redis的有益補充。
隨着4.0版本module功能的推出,使得Redis擁有更多的想象和發展空間,在全文索引(RediSearch),AI(Redis-ML)、雲計算、大數據、物聯網、人工智能、BlockChain等領域,模塊化的融合能力將極大的豐富Redis的功能,從而為企業構建更為多元化、立體化的數據庫使用方式。
其它分享
在使用Redis的過程中,還需要保持關注官方的動態,多看看github上的changelog和issue,因為隨着Redis的用戶群體的增多,使用場景的復雜化,Redis自身隱藏的問題或瓶頸也會暴露出來,這樣有助於我們避免踩一些不必要的坑,及早規避一些風險。
不僅僅是Redis,學習其他的數據庫也是一樣的。另外,我們在關注Redis本身以外,還需要關注一些其他的Redis的替代產品(比如:SSDB、Pika、Codis、ApsaraCache、TiDB等),Redis的周邊工具(如:redis-migrate-tool、redis-faina、redis-audit、redis-rdb-tools、RedisMyAdmin等)、中間件(如:twemproxy、corvus、redis-cerberus)等。如果你想要從事Redis的開發,那么你可能需要關注的更多,比如各種鎖的實現。
引用自:數據和雲