Redis 單線程高性能,它全部的數據都在內存中,全部的運算都是內存級別的運算,並且單線程避免了多線程的切換性能損耗問題。redis利用epoll來實現IO多路複用,將鏈接信息和事件放到隊列中,依次放到文件事件分派器,事件分派器將事件分發給事件處理器。java
1.Redis數據結構及簡單操做指令
redis
String、list、set、hash、zset(有序set)算法
整體來講redis都是經過Key-Value的形式來存儲數據的。只是不用數據類型Value的形式不一樣。數據庫
String:最簡單數據結構,好比咱們將一個對象轉成json串來存儲json
set key value 存放數據緩存
get key 獲取數據安全
exists key 查看數據是否存在,存在返回1不然0數據結構
del key 刪除數據 返回操做成功的條數多線程
mset key1 value1 key2 value2 key3 value3...存放多組數據app
mget key1 ke2y key3... 獲取多個key的數據,返回一個集合,相似Map的values方法
expire key second 設置key 過時時間,單位秒
expire key second 設置key 過時時間,單位秒
setex key second value設置key 過時時間,單位秒(等價於先set,再expire)
setnx key value 若是key不存在就set 返回1.若是存在返回0(能夠基於此實現分佈式鎖)
List:並非java裏面的list,redis的list更像一個鏈表或者說隊列/棧的結構。這就意味着它的刪除插入快,可是經過索引定位就比較慢了。當列表彈出了最後一個元素以後,該數據結構自動被刪除,內存被回收。
Redis 的列表結構經常使用來作異步隊列使用。將須要延後處理的任務塞進 Redis 的列表,另外一個線程從這個列表中輪詢數據進行處理。
rpush key value1 value2 value3... 插入list數據
llen key 查看長度
lpop key 按加入順序獲取(先進先出,相似隊列)
rpop key 後進先出,有點相似棧
列表取數據,取完後整個列表都被回收了,就是說只能取一次數據。
Hash:相似java的hashMap,和字符串相比,咱們存儲數據的時候能夠只存儲對象的部分屬性,而字符串則須要完整將整個對象轉換。固然hash存儲結構的消耗確定是高於字符串的
hset redisKey hashKey1 value1
hset redisKey hashKey2 value2 插入數據
hgetall redisKey 獲取數據,key value間隔出現
hlen redisKey 查看hash長度
hget redisKey hashKey 獲取hashKey 對應的value
hmset redisKey hashKey1 value1 hashKey2 value2 hashKey2 value3 批量插入值
Set : 相似HashSet,可是list相似,最後一個數據取完以後,該結構會被清理,沒法再次獲取數據
sadd key value
sadd key value1 value2 批量添加
smembers key 查看全部
sismember key value 查詢某個值是否存在,存在返回1
scard key 查看大小
spop key 獲取一個元素
原子計數操做
若是value是整數的話還能夠實現自增操做(也能夠用於實現分佈式鎖,該增加有限,最大到long max,超過該值會直接報錯)
incr key 自增 若是key不存在默認從0自增1
incrby key step 設置增長步長step
2.redis持久化
雖說redis都是內存級別的操做,其實也是有持久化的。
一種是基於RDB快照,
Redis 將內存數據庫快照保存在名字爲 dump.rdb 的二進制文件中。
能夠對 Redis 進行設置, 讓它在N 秒內數據集至少有 M 個改動這一條件被知足時, 自動保存一次數據集。
另外一種是AOF(append-only file)
快照並不可靠,上次快照以後,還未到達下一次快照條件時,這時候服務出現了問題,那麼這期間的數據是沒法保存到快照版本中的。這個時候就須要AOF了,它將每一條指令都記錄進文件,當redis重啓的時候,從新執行這個文件裏面指令,就能夠恢復全部的數據到內存中了。
能夠經過配置appendonly yes 來開啓AOF,默認是關閉的
AOF也有三種同步數據的策略,
每次有操做都去刷新文件,很慢,但安全
每秒同步刷新一次:可能會丟失一秒內的數據
從不一樣步同步刷新:讓操做系統在須要的時候刷新數據,不安全
默認的是每秒刷一次
混合持久化:
RDB快照數據恢復速度快,可是可能會有大量數據丟失,因此一般恢復數據仍是用的AOF日誌重放,可是AOF相對來講速度會很慢,尤爲是在數據量大的時候。所以在4.0的時候帶來了混合持久化,也就是AOF在刷新的時候,先記錄上次的快照版本,而後記錄上次快照版本到如今的增量操做,而後合併成一個文件,覆蓋原來的appendonly.aof文件。Redis重啓的時候,先加載RDB快照的內容,在重放AOF日誌中增量操做的內容就能夠了。
開啓混合持久化:aof-use-rdb-preamble yes
混合持久化中appendonly.aof內容格式,一部分是RDB文件內容格式,另外的纔是AOF文件的內容格式。
3.緩存淘汰策略:
當 Redis 內存超出物理內存限制時,內存的數據會開始和磁盤產生頻繁的交換 。會讓 Redis 的性能急劇降低,對於訪問量比較頻繁的 Redis 來講,這樣存取效率基本上等於不可用。
在生產環境中咱們是不容許 Redis 出現交換行爲的,爲了限制最大使用內存,Redis 提供了配置參數 maxmemory 來限制內存超出指望大小。
當實際內存超出 maxmemory 時,Redis 提供了幾種可選策略 (maxmemory-policy) 來讓用戶本身決定該如何騰出新的空間以繼續提供讀寫服務。
maxmemory <bytes> # MAXMEMORY POLICY: how Redis will select what to remove when maxmemory # is reached. You can select among five behaviors: # # volatile-lru -> Evict using approximated LRU among the keys with an expire set. # allkeys-lru -> Evict any key using approximated LRU. # volatile-lfu -> Evict using approximated LFU among the keys with an expire set. # allkeys-lfu -> Evict any key using approximated LFU. # volatile-random -> Remove a random key among the ones with an expire set. # allkeys-random -> Remove a random key, any key. # volatile-ttl -> Remove the key with the nearest expire time (minor TTL) # noeviction -> Don't evict anything, just return an error on write operations. # # LRU means Least Recently Used # LFU means Least Frequently Used # # Both LRU, LFU and volatile-ttl are implemented using approximated # randomized algorithms. # # Note: with any of the above policies, Redis will return an error on write # operations, when there are no suitable keys for eviction. # # At the date of writing these commands are: set setnx setex append # incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd # sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby # zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby # getset mset msetnx exec sort # # The default is: # # maxmemory-policy noeviction
noeviction 不會繼續處理寫請求 (del,read請求能夠繼續進行)。這樣能夠保證不會丟失數據,可是會讓線上的寫相關的業務不能持續進行。這是默認的淘汰策略。
volatile-lru 嘗試淘汰設置了過時時間的 key,最少使用的 key 優先被淘汰。沒有設置過時時間的 key 不會被淘汰,這樣能夠保證須要持久化的數據不會忽然丟失。
volatile-ttl 跟上面同樣,除了淘汰的策略不是 LRU,而是 key 的剩餘壽命 ttl 的值,ttl 越小越優先被淘汰。
volatile-random 跟上面同樣,不過淘汰的 key 是過時 key 集合中隨機的 key。
allkeys-lru 區別於 volatile-lru,這個策略要淘汰的 key 對象是全體的 key 集合,而不僅是過時的 key 集合。這意味着沒有設置過時時間的 key 也會被淘汰。
allkeys-random 跟上面同樣,不過淘汰的策略是隨機的 key。
volatile-xxx 策略只會針對帶過時時間的 key 進行淘汰,allkeys-xxx 策略會對全部的 key 進行淘汰。若是你只是拿 Redis 作緩存,那應該使用 allkeys-xxx,客戶端寫緩存時沒必要攜帶過時時間。若是你還想同時使用 Redis 的持久化功能,那就使用 volatile-xxx 策略,這樣能夠保留沒有設置過時時間的 key,它們是永久的 key 不會被 LRU 算法淘汰。