Redis FAQ
Redis與其他key-value存儲有什么不同?
主要有以下兩個原因。
- Redis有著更為復雜的數據結構并且提供對他們的原子性操作,這是一個不同于其他數據庫的進化路徑。Redis的數據類型都是基于基本數據結構的同時對程序員透明,無需進行額外的抽象。
- Redis運行在內存中但是可以持久化到磁盤,所以在對不同數據集進行高速讀寫時需要權衡內存,應為數據量不能大于硬件內存。在內存數據庫方面的另一個優點是, 相比在磁盤上相同的復雜的數據結構,在內存中操作起來非常簡單,這樣Redis可以做很多內部復雜性很強的事情。 同時,在磁盤格式方面他們是緊湊的以追加的方式產生的,因為他們并不需要進行隨機訪問。
Redis的內存占用情況怎么樣?
給你舉個例子: 100萬個鍵值對(鍵是0到999999值是字符串“hello world”)在我的32位的Mac筆記本上 用了100MB。同樣的數據放到一個key里只需要16MB, 這是因為鍵值有一個很大的開銷。 在Memcached上執行也是類似的結果,但是相對Redis的開銷要小一點點,因為Redis會記錄類型信息引用計數等等。
當然,大鍵值對時兩者的比例要好很多。
64位的系統比32位的需要更多的內存開銷,尤其是鍵值對都較小時,這是因為64位的系統里指針占用了8個字節。 但是,當然,64位系統支持更大的內存,所以為了運行大型的Redis服務器或多或少的需要使用64位的系統。
我喜歡Reids的高水平操作和功能,但我不喜歡所有數據都放在內存中,因為我沒有一個大數據集的內存,有沒有改變這方面的機會呢。
在過去,Redis開發商嘗試試用虛擬內存和其他系統為了讓RAM數據集更大,但是畢竟我們非常高興,如果我們能做好一件事:數據保存在內存,存儲在磁盤。 但是現在沒有計劃創建一個基于磁盤的Redis,畢竟目前的設計是直接的原因。
然而,許多大型系統的用戶采用多個Redis節點通過客戶端Hash的辦法解決了大數據集分配的問題。Craigslist和Groupon就是兩個列子。
同時Redis Cluster(一個Redis的子集自動分發和容錯實現)正在開發中,這可能是很多使用案例的一個很好的解決方案
如果我的數據集需要使用非常大的內存,我不希望使用一致性哈希或其他方式將數據集分布在不同的節點,我還能采用Redis嗎?
一個可行的方案是同時使用傳統數據庫(Mysql或者其他的)和Redis,Redis里面存放狀態信息(元數據,小但經常寫的信息),和所有其他讀寫頻繁的數據:用戶身份驗證token, 使用Redis List 存放與時間順序有關的id列表、編碼等等。然后使用MySQL(或其他)作為存儲引擎來存放更大的數據, 創建一個自增長ID作為主鍵和一個較大的BLOB字段作為數據字段,訪問MySQL的數據只能通過主鍵(ID) 。執行查詢操作時,通過Redis讀取數據, 但是當有讀取打數據時需要通過主鍵(ID)訪問MySQL數據庫。
都有哪些辦法可以降低Redis的內存使用情況呢?
如果你使用的是32位的Redis實例,可以好好利用Hash,list,sorted set,set等集合類型數據,因為通常情況下很多小的Key-Value可以用更緊湊的方式存放到一起。
Redis的內存用完了會發生什么?
隨著現代操作系統的malloc(),返回NULL是不常見的,通常服務器會啟動swap交換,這樣Redis的性能會隨之降低,您也可能會發現某些不妥。
INFO命令可以查看Redis的使用量,因此您可以編寫一個監視Redis服務器狀態的臨界監控腳本以檢查服務器的狀態。 或者可以在配置文件中使用“maxmemory”配置Redis可以使用的最大內存,如果達到設置的上限,Redis的寫命令會返回錯誤信息(但是讀命令還可以正常返回)。 或者你可以將Redis當緩存來使用配置淘汰機制,當Redis達到內存上限時會沖刷掉舊的內容。
在liunx下即使有很多的RAM通過fork()調用后臺保存還是會失敗!
簡短的回答:echo 1 > /proc/sys/vm/overcommit_memory :)
下面是長的回答:
Redis background saving schema relies on the copy-on-write semantic of fork in modern operating systems: Redis forks (creates a child process) that is an exact copy of the parent. The child process dumps the DB on disk and finally exits. In theory the child should use as much memory as the parent being a copy, but actually thanks to the copy-on-write semantic implemented by most modern operating systems the parent and child process will share the common memory pages. A page will be duplicated only when it changes in the child or in the parent. Since in theory all the pages may change while the child process is saving, Linux can’t tell in advance how much memory the child will take, so if the overcommit_memory setting is set to zero fork will fail unless there is as much free RAM as required to really duplicate all the parent memory pages, with the result that if you have a Redis dataset of 3 GB and just 2 GB of free memory it will fail. Setting overcommit_memory to 1 says Linux to relax and perform the fork in a more optimistic allocation fashion, and this is indeed what you want for Redis. A good source to understand how Linux Virtual Memory work and other alternatives for overcommit_memory and overcommit_ratio is this classic from Red Hat Magazine, “Understanding Virtual Memory”.
Redis 的 on-disk-snapshots 是原子的嗎?
是的, 當redis前臺在執行命令時后臺保存進程是fork(2)ed, 所以任何命令在RAM里是原子操作的,在磁盤快照里面也同樣是原子的。
Redis是單線程的,我怎么提高多核CPU的利用率?
CPU不太可能是Redis的瓶頸,一般內存和網絡才有可能是。 例如使用Redis的管道(pipelining)在liunx系統上運行可以達到500K的RPS(requests per second) ,因此,如果您的應用程序主要使用O(N) 或者O(log(N)) 的命令,他們幾乎不需要使用什么CPU。
然而,為了最大限度的使用CPU,可以在同一個服務器部署多個Redis的實例,并把他們當作不同的服務器來使用,在某些時候,無論如何一個服務器是不夠的,
所以,如果你想使用多個CPU,你可以考慮一下分片(shard) 。。
在Redis的客戶端類庫里面,比如RB(Ruby的客戶端)和Predis(最常用的PHP客戶端之一),能夠使用一致性哈希(consistent hashing)來處理多個Redis實例。
一個Redis實例最多能存放多少的keys,List、Set、Sorted Set他們最多能存放多少元素?
理論上Redis可以處理多達232的keys,并且在實際中進行了測試,每個實例至少存放了2億5千萬的keys。我們正在測試一些較大的值。
任何list、set、和sorted set都可以放232個元素。
換句話說,Redis的存儲極限是系統中的可用內存值。
Redis 是什么意思?
他的意思是 REmote DIctionary Server。
總結
- 上一篇: Redis 数据类型介绍
- 下一篇: Redis Streams 介绍