1. 程式人生 > 實用技巧 >關於for迴圈中使用setTimeout的四種解決方案

關於for迴圈中使用setTimeout的四種解決方案

1.redis為什麼是key,value的,為什麼不是支援SQL的?

為什麼是key,value
redis是基於記憶體的資料庫,其應用場景是大量資料的快速讀寫;
大量的資料吞吐量,在同一時間,會併發的有成千上萬的連線對資料庫進行操作;在這種情況下,單臺伺服器或者幾臺伺服器遠遠不能滿足這些資料處理的;需要key-value可以滿足快速讀寫;

為什麼不是支援SQL
redis是基於記憶體的資料庫,不是一般的關係型資料庫;
應用場景是快速讀寫,複雜查詢等操作不是redis的重點,所以不支援SQL;

2.redis是多執行緒還是單執行緒?

Redis在4.0之前的版本,是單執行緒;
原因如下:
1.使用單執行緒模式的Redis,其開發和維護更簡單,因為單執行緒模式方便開發和除錯。

2.即使使用單執行緒模型也能夠併發地處理多客戶端的請求,主要是因為Redis內部使用了基於epoll的多路複用;
3.對於Redis來說,主要的效能瓶頸是記憶體或網路頻寬,而非CPU。

Redis在4.0版本中引入了多執行緒,但是該版本的多執行緒只能用於大資料量的非同步刪除,對於非刪除操作的意義並不是很大。(意思就是可以使用非同步的方式對Redis中的資料進行刪除操作)
通常情況下使用del指令可以很快的刪除資料,但是當被刪除的key是一個非常大的物件時,例如:刪除的時包含成千上萬個元素的hash集合時,那麼del指令就會造成Redis主執行緒卡頓,因此使用惰性刪除可以有效避免Redis卡頓問題。

這樣處理的好處是不會使Redis的主執行緒卡頓,會把這些操作交給後臺執行緒來執行。

Redis為什麼這麼快?
1.基於記憶體操作:Redis的所有資料都存在記憶體中,因此所有的運算都是記憶體級別的,所以它的效能比較高。
2.資料結構簡單:Redis的資料結構比較簡單,是為Redis專門設計的,而這些簡單的資料結構的查詢和操作的時間複雜度都是O(1)。
3.多路複用和非阻塞IO:Redis使用IO多路複用功能來監聽多個socket連線的客戶端,這樣就可以使用一個執行緒來處理多個情況,從而減少執行緒切換帶來的開銷,同時也避免了IO阻塞操作,從而大大提高了Redis的效能。
4.避免上下文切換:因為是單執行緒模型,因此就避免了不必要的上下文切換和多執行緒競爭,這就省去了多執行緒切換帶來的時間和效能上的開銷,而且單執行緒不會導致死鎖的問題發生。

注意:官方使用的基準測試結果表明,單執行緒的Redis可以達到10W/S的吞吐量。

3.redis的持久化開啟了RDB和AOF下重啟服務是如何載入的?

1.AOF持久化開啟且存在AOF檔案時,優先載入AOF檔案,
2.AOF關閉或者AOF檔案不存在時,載入RDB檔案,
3.載入AOF/RDB檔案成功後,Redis啟動成功。
4.AOF/RDB檔案存在錯誤時,Redis啟動失敗並列印錯誤資訊

RDB是一種快照儲存持久化方式,具體就是將Redis某一時刻的記憶體資料儲存到硬碟的檔案當中,預設儲存的檔名為dump.rdb,而在Redis伺服器啟動時,會重新載入dump.rdb檔案的資料到記憶體當中恢復資料。
AOF持久化方式會記錄客戶端對伺服器的每一次寫操作命令,並將這些寫操作以Redis協議追加儲存到以後綴為aof檔案末尾,在Redis伺服器重啟時,會載入並執行aof檔案的命令,以達到恢復資料的目的。

4.redis如果做叢集該如何規劃?AKF/CAP如何實現和設計?

1.官方cluster方案
從redis 3.0版本開始支援redis-cluster叢集,redis-cluster採用無中心結構,每個節點儲存資料和整個叢集狀態,每個節點都和其他節點連線。redis-cluster是一種服務端分片技術。
特點:
每個節點都和n-1個節點通訊,這被稱為叢集匯流排(cluster bus)。它們使用特殊的埠號,即對外服務埠號加10000。所以要維護好這個叢集的每個節點資訊,不然會導致整個叢集不可用,其內部採用特殊的二進位制協議優化傳輸速度和頻寬。
redis-cluster把所有的物理節點對映到[0,16383]slot(槽)上,cluster負責維護node–slot–value。
叢集預分好16384個桶,當需要在redis叢集中插入資料時,根據CRC16(KEY) mod 16384的值,決定將一個key放到哪個桶中。
客戶端與redis節點直連,不需要連線叢集所有的節點,連線叢集中任何一個可用節點即可。
redis-trib.rb指令碼(rub語言)為叢集的管理工具,比如自動新增節點,規劃槽位,遷移資料等一系列操作。
節點的fail是通過叢集中超過半數的節點檢測失效時才生效。
整個cluster被看做是一個整體,客戶端可連線任意一個節點進行操作,當客戶端操作的key沒有分配在該節點上時,redis會返回轉向指令,指向正確的節點。
為了增加叢集的可訪問性,官方推薦的方案是將node配置成主從結構,即一個master主節點,掛n個slave從節點。如果主節點失效,redis cluster會根據選舉演算法從slave節點中選擇一個上升為master節點,整個叢集繼續對外提供服務。

2.twemproxy代理方案
Redis代理中介軟體twemproxy是一種利用中介軟體做分片的技術。twemproxy處於客戶端和伺服器的中間,將客戶端發來的請求,進行一定的處理後(sharding),再轉發給後端真正的redis伺服器。也就是說,客戶端不直接訪問redis伺服器,而是通過twemproxy代理中介軟體間接訪問。降低了客戶端直連後端伺服器的連線數量,並且支援伺服器叢集水平擴充套件。
twemproxy中介軟體的內部處理是無狀態的,它本身可以很輕鬆地叢集,這樣可以避免單點壓力或故障。
twemproxy又稱nutcracker,起源於推特系統中redis、memcached叢集的輕量級代理。

注意:twemproxy是一個單點,很容易對其造成很大的壓力,所以通常會結合keepalived來實現twemproy的高可用。這時,通常只有一臺twemproxy在工作,另外一臺處於備機,當一臺掛掉以後,vip自動漂移,備機接替工作。

3.哨兵模式方案
Sentinel(哨兵)是Redis的高可用性解決方案:由一個或多個Sentinel例項組成的Sentinel系統可以監視任意多個主伺服器以及這些主伺服器下的所有從伺服器,並在被監視的主伺服器進入下線狀態時,自動將下線主伺服器屬下的某個從伺服器升級為新的主伺服器。

Sentinel的工作方式:
每個Sentinel以每秒鐘一次的頻率向它所知的Master、Slave以及其他Sentinel例項傳送一個PING命令。
如果一個例項距離最後一次有效回覆PING命令的時間超過down-after-milliseconds選項所指定的值,則這個例項會被Sentinel標記為主觀下線。
如果一個Master被標記為主觀下線,則正在監視這個Master的所有Sentinel要以每秒一次的頻率確認Master的確進入了主觀下線狀態。
當有足夠數量的Sentinel(大於等於配置檔案指定的值)在指定的時間範圍內確認Master的確進入了主觀下線狀態,則Master會被標記為客觀下線。
在一般情況下,每個Sentinel會以每10秒一次的頻率向它所知的所有Master、Slave傳送INFO命令。
當Master被Sentinel標記為客觀下線時,Sentinel向下線的Master的所有Slave傳送INFO命令的頻率會從10秒一次改為每秒一次。
若沒有足夠數量的Sentinel同意Master已經下線,Master的客觀下線狀態就會被移除。若Master重新向Sentinel的PING命令返回有效值,Master的主觀下線狀態就會被移除。

4.codis方案
codis是一個分散式的Redis解決方案,由豌豆莢開源,對於上層的應用來說,連線codis proxy和連線原生的redis server沒什麼明顯的區別,上層應用可以像使用單機的redis一樣使用,codis底層會處理請求的轉發,不停機的資料遷移等工作,所有後邊的事情,對於前面的客戶端來說是透明的,可以簡單的認為後邊連線的是一個記憶體無限大的redis服務。

5.客戶端分片方案
分割槽的邏輯在客戶端實現,由客戶端自己選擇請求到哪個節點。方案可參考一致性雜湊,這種方案通常適用於使用者對客戶端的行為有完全控制能力的場景。

總結
從各個叢集方案的對比中我們也發現Codis是目前用的比較多的一種方案,Codis在高可用方面做的比較好,不需要重啟節點和增加刪除節點後自動Resharding,但是因為Codis是對redis-server做了改動,如果出現問題或者redis升級小團隊可能應付不了,所以對於小規模應用最好還是使用官方的cluster方案。

當然具體方案,看具體場景:
如果希望快速部署,那麼可以考慮單節點部署方式。
如果只需要考慮可靠性,那麼可以考慮主從複製模式。
如果想要保證高可用,不需要考慮儲存成本可以考慮哨兵模式。
如果想提高叢集的擴充套件性和可用性,不要求保證資料的強一致性,且沒有批量操作,那麼可以考慮叢集模式。

AKF
AKF擴充套件立方體(Scalability Cube),是《架構即未來》一書中提出的可擴充套件模型,這個立方體有三個軸線,每個軸線描述擴充套件性的一個維度,他們分別是產品、流程和團隊:
X軸 —— 代表無差別的克隆服務和資料,工作可以很均勻的分散在不同的服務例項上;
Y軸 —— 關注應用中職責的劃分,比如資料型別,交易執行型別的劃分;
Z軸 —— 關注服務和資料的優先順序劃分,如分地域劃分。

執行一個redis例項會有哪些問題:
單點故障
容量瓶頸
訪問壓力
AKF:
X:全量,映象
Y:業務,功能
Z:優先順序,邏輯再拆分

x軸:在x軸方向上,做N個主機的全量映象資料的副本,主redis與這些副本的關係為主從。主機可以對外提供read / write ,從機可以對外提供read(讀寫分離)。結合高可用, 可以解決單點故障和容量瓶頸的問題,只是解決了 read 的壓力,而沒有解決 write 的壓力。
y軸:在y軸方向上,可以把之前一臺redis中的資料按照業務功能來拆分成不同的redis例項儲存,並且每個redis例項都可以再次做x軸的映象副本進行讀寫分離,當然,x軸和y軸之間不是必須要結合使用。y軸的拆分解決了容量瓶頸問題和資料訪問壓力的問題。
z軸:如果y軸的某個redis例項過於臃腫,還可以把這個redis例項進行z軸的拆分,也就是把這個redis例項裡面的資料按照一定規則查分。比如:取模,優先順序等規則再次查分成多個redis,使得不同的資料出現在固定的redis裡。

CAP
CAP理論指的是一個分散式系統最多隻能同時滿足一致性(Consistency)、可用性(Availability)和分割槽容錯性(Partition tolerance)這三項中的兩項。

分割槽:一個分散式系統,網路不通訊,導致連線不通,系統被分割成幾個資料區域
原因:資料不連通了,產生資料分割槽
影響
查還好一點
資料修改時,必須要求資料一致–加鎖,實現資料一致性【需求要求資料一致性】
資料修改時,可以資料不一致–不用加鎖【需求不要求資料一致性】
分割槽容忍度
資料的一致性要求高,容忍度高,加鎖
資料的一致性要求低,容忍度低,可以不加鎖
預期結果,保持資料的一致
可用性
請求在一定時間段內都應該有響應
為了解決鎖一直加著
CP理論:【一致性+分割槽】資料的一致性要求高-加鎖
AP理論:【可用性+分割槽】資料的一致性要求低-不加鎖
CAP總結
分割槽是常態,不可避免,三者不可共存
可用性和一致性是一對冤家
一致性高,可用性低
一致性低,可用性高

5.10萬用戶一年365天的登入情況如何用redis儲存,並快速檢索任意時間窗的活躍使用者?

Bitmap是一串連續的2進位制數字(0或1),每一位所在的位置為偏移(offset),在bitmap上可執行AND,OR,XOR以及其它位操作。
佔空間少

6.redis的5中value型別?

Redis支援五種資料型別:
string(字串)
hash(雜湊)
list(列表)
set(集合)
zset(sorted set:有序集合)。

7.100萬併發4G資料,10萬併發400G資料,如何設計redis儲存方式?

主從+哨兵進行高可用,加快讀請求的速度,減輕單節點的壓力;
用叢集模式來均分這400G資料;