RD1
Redis是完全開源免費的,遵守BSD協議,是一個高性能的key-value數據庫。
Redis與其他key - value緩存產品有以下三個特點:
幾十年來,用於開發應用程式的主要資料模型,均是諸如 Oracle、DB2、SQL Server、MySQL 和 PostgreSQL 等關聯式資料庫所採用的關聯式資料模型。一直到 2000 年中後期,其他資料模型才開始廣受採納和運用。為了區分和歸類這些新類型的資料庫和資料模組,因此創造了「NoSQL」這個名詞。「NoSQL」這個名詞常常與「非關聯式」互換使用。
雖然 NoSQL 資料類型多樣且功能各異,但您可從以下表格瞭解 SQL 和 NoSQL 資料庫的一些差異性
差異 | 關聯式資料庫 | NoSQL 資料庫 |
---|---|---|
最佳工作負載 | 關聯式資料庫專門用於交易性以及高度一致性的線上交易處理 (OLTP) 應用程式,並且非常適合於線上分析處理 (OLAP) 使用。 | NoSQL 資料庫專門用於包含低延遲應用程式的多樣資料存取模式。NoSQL 搜尋資料庫專門用於進行半結構資料的分析。 |
資料模型 | 關聯式模型將資料標準化,成為由列和欄組成的表格。結構描述嚴格定義表格、列、欄、索引、表格之間的關係,以及其他資料庫元素。此類資料庫強化資料庫表格間的參考完整性。 | NoSQL 資料庫提供鍵值、文件和圖形等多種資料模型,具有最佳化的效能與規模。 |
ACID 屬性 | 關聯式資料庫則提供單元性、一致性、隔離性和耐用性 (ACID) 的屬性 |
NoSQL 資料庫通常透過鬆綁部分關聯式資料庫的 ACID 屬性來取捨,以達到能夠橫向擴展的更彈性化資料模型。這使得 NoSQL 資料庫成為橫向擴展超過單執行個體上限的高吞吐量、低延遲使用案例的最佳選擇 |
效能 | 一般而言,效能取決於磁碟子系統。若要達到頂級效能,通常必須針對查詢、索引及表格結構進行優化。 | 效能通常會受到基礎硬體叢集大小、網路延遲,以及呼叫應用程式的影響。 |
擴展 | 關聯式資料庫通常透過增加硬體運算能力向上擴展,或以新增唯讀工作負載複本的方式向外擴展。 | NoSQL 資料庫通常可分割,因為存取模式可透過使用分散式架構來向外擴展,以近乎無限規模的方式提供一致效能來增加資料吞吐量。 |
API | 存放和擷取資料的請求是透過符合結構式查詢語言 (SQL) 的查詢進行通訊。這些查詢是由關聯式資料庫剖析和執行。 | 以物件為基礎的 API 讓應用程式開發人員可輕鬆存放和擷取資料結構。應用程式可透過分區索引鍵查詢鍵值組、欄集,或包含序列化應用程式物件與屬性的半結構化文件。 |
SQL | MongoDB | Couchbase |
---|---|---|
表 | 集 | 資料儲存貯體 |
列 | 列 | 文件 |
欄 | 欄 | 欄位 |
主索引鍵 | 物件 ID | 文件 ID |
索引 | 索引 | 索引 |
檢視 | 檢視 | 檢視 |
巢狀表格或物件 | 內嵌文件 | 對應 |
陣列 | 陣列 | 清單 |
由於 NoSQL 的種類很多,而技術的成熟度與使用場景不一,所以目前業界還是以 SQL 資料庫佔大多數。在 Stackoverflow 2018 年的調查結果,關聯式資料庫系統還是最多開發者使用的資料庫管理系統,佔前五名中的首四名!
下方來源 Redis
所有 Redis 資料都放在伺服器的主要記憶體內,與 PostgreSQL、Cassandra、MongoDB 和其他將大多數資料存放在磁碟或 SSD 的資料庫並不相同。使用傳統磁碟的資料庫需要在磁碟來回處理才能執行大多數的操作,而 Redis 這類記憶體內資料存放區則不受此限制。這樣它們便能夠支援更大規模的操作,而且回應時間更快。這項優勢提供超快速的效能,平均讀取和寫入操作時間低於一毫秒,並支援每秒百萬個操作。
簡易的鍵值資料存放區提供的資料結構有限,而 Redis 則提供多樣化的資料結構以滿足應用程式的需要。Redis 資料類型包括:
下方指令來源 資料庫的好夥伴:Redis
redis> SET mykey "Hello"
redis> GET mykey
"Hello"
前面有提到說 Redis 是一個 key-value pair 的資料庫,因此最簡單的 SET 就是設定某個 key 的值是多少,要取出來的話就用 GET 就好。
redis> SET mykey "10"
redis> DECR mykey
(integer) 9
redis> INCR mykey
(integer) 10
顧名思義就是針對某個 key 加一或減一的意思,像是程式語言裡面的mykey++
跟mykey--
。
還有 INCRBY
與 DECRBY
,可以指定你要加減的數量是多少。
redis> HSET mydata name "nick"
redis> HSET mydata nickname "nicknick"
redis> HGET mydata name
"nick"
H 就是 Hashmap 的意思,所以你可以存取一個 value 底下的 field,讓你可以更多元的使用,例如說你可以定義 key 的規則是:POST + 文章 id,裡面就可以存這篇文章的讚數、回覆數等等,就不用每一次都去 Database 裡面重新抓取。
redis> SADD myset "nick"
redis> SADD myset "peter"
redis> SADD myset "nick"
redis> SCARD myset
(integer) 2
SADD 的 S 就是 Set
的意思,這邊的 Set
指的是資料結構學過的那個 Set
,裡面不會有重複的內容,第二次插入的元素會被忽略。
zadd key score member
和 set 一樣是string類型元素的集合,不允許重複的key
每個元素都會關聯一個 double 分數,會通過該分數為該集合排序
127.0.0.1:6379> ZADD myset 0 hi
(integer) 1
127.0.0.1:6379> ZADD myset 1.3 hi
(integer) 0
127.0.0.1:6379> ZADD myset 1.3 hey
(integer) 1
127.0.0.1:6379> ZADD myset 22 fine
(integer) 1
127.0.0.1:6379> ZRANGEBYSCORE myset 0 20
1) "hey"
2) "hi"
redis> LPUSH mylist "a"
redis> LPUSH mylist "b"
redis> RPUSH mylist "c"
redis> LRANGE mylist 0 -1
1) "b"
2) "a"
3) "c"
redis> LSET mylist 0 "d"
redis> LRANGE mylist 0 -1
1) "d"
2) "a"
3) "c"
這邊的資料結構是 List
,你可以選擇從左邊或是右邊 push 值進去,對應到的指令就是 LPUSH
與 RPUSH
,LSET
則是指定某個 index 的 value 是多少。
LRANGE
可以印出指定範圍的值,支援-1
這種形式,表示最後一個值。
hash 是 string 類型的 field-value 的映射表
127.0.0.1:6379> HMSET myset time 20:00 des "hi" type 1
OK
127.0.0.1:6379> HGETALL myset
1) "time"
2) "20:00"
3) "des"
4) "hi"
5) "type"
6) "1"
127.0.0.1:6379> HGET myset time
"20:00"
這裡我還沒看 先貼
How To Configure Redis + Redis Commander + Docker
我們大多傾向於使用這種方式,也就是將資料庫中的變化同步到Redis,這種更加可靠。Redis在這裡只是做緩存。
做緩存,就要遵循緩存的語義規定:
讀:讀緩存redis,沒有,讀mysql,並將mysql的值寫入到redis。
寫:寫mysql,成功後,更新或者失效掉緩存redis中的值。
對於一致性要求高的,從資料庫中讀,比如金融,交易等資料。其他的從Redis讀。
這種方案的好處是由mysql,常規的關係型資料庫來保證持久化,一致性等,不容易出錯。
這裡還可以基於binlog使用mysql_udf_redis,將資料庫中的資料同步到Redis。
但是很明顯的,這將整體的複雜性提高了,而且本來我們在系統代碼中能很輕易完成的功能,現在需要依賴第三方工具,而且系統的整個邊界擴大了,變得更加不穩定也不好管理了。
也就是說將Redis中的資料變化同步到資料庫,那麼這裡是將Redis做為db,而真的db,資料庫只作為備份。(注意,這裡是一種不同看待事物的方式)。
這樣做的好處是:大大減小了資料庫的壓力,但是用redis做內存資料庫,狀態很不穩定。
雖然redis也有持久化機制,但是redis集群宕機後的重啟,資料加熱都很耗時。
另一方面,隨著大量插入或者更新導致redis持久化操作會嚴重拖累作為內存KV資料庫的優勢。
將redis變更複制一份,丟到隊列中,給mysql消費。
很明顯這種方案,只能保證最終一致性,而且變更資料複製,隊列維護,這些雜七雜八的東西太複雜,拋棄。
具體做法是:寫redis時,同時將資料寫到redis維護的另外一個隊列中,但這樣又要增加內存消耗了。
其實還有一種方式是使用redis的pipeline通知機制,但是redis是不保證的一定通知到的(得到被通知方的ack)。
定時刷新redis中的最新資料到mysql。
很明顯的,無論定時任務的間距有多小,都會留下時間縫隙,如果發生宕機,故障等都會造成資料的不一致性。
雖然可以通過:比較redis和資料庫中的資料,同步那些需要同步的變化資料,但是會加大計算量和程序的複雜度。