NoSQL一詞最先出現於1998年,是Carlo Strozzi開發的一個輕量、開源、不提供SQL功能的關係數據庫。2009年,Last.fm的Johan Oskarsson發起了一次關於分佈式開源數據庫的討論,來自Rackspace的Eric Evans再次提出了NoSQL的概念,這時的NoSQL主要指非關係型、分佈式、不提供ACID的數據庫設計模式。它不一樣於傳統的關係數據庫,二者存在許多顯著的不一樣點,其中最重要的是NoSQL不使用SQL做爲查詢語言。其數據存儲能夠不須要固定的表格模式。前端
git
Redis是使用c語言開發的一個高性能鍵值數據庫。經常使用於分佈式系統中的緩存、電商秒殺、排行榜、訪問量統計、分佈式會話共享等高併發應用場景。Redis能夠經過一些鍵值類型來存儲數據。其數據類型包括字符類型、散列類型、列表類型、集合類型、有序集合類型。github
訪問Redis官網https://redis.io/download下載最新的版本 。redis
解壓並編譯安裝sql
$ tar xzf redis-5.0.3.tar.gz
$ cd redis-5.0.3
$ make install
Redis官網並無提供windows版本,但能夠前往https://github.com/tporadowski/redis/releases下載windows的我的編譯版本(注意:並非最新的版本)。數據庫
在redis的src目錄有一個redis-server文件,用於啓動一個redis服務。windows
redis的默認端口爲6379,當客戶端須要鏈接到redis服務時,就經過服務端的IP地址以及這個端口進行鏈接。也能夠修改這個默認端口。在redis的根目錄下有一個redis.conf文件,它是redis的核心配置文件,redis的全部配置信息都在此文件中。若是須要修改端口,咱們在配置文件中找到port配置,並將6379改成其餘的端口號。後端
修改完後須要從新啓動redis服務,須要注意的是,在使用redis-server啓動服務時須要指定redis.conf文件的絕對路徑,不然redis將以默認的配置啓動一個服務實例。設計模式
前端啓動的模式咱們能夠在終端看到redis的啓動信息和相關的操做日誌,但此時若是關閉了終端或者使用control+c將會當即中止redis服務。緩存
所謂後端啓動,就是以一個獨立的進程來運行一個redis服務。首先修改redis.conf文件,找到daemonize選項並設置爲yes,以下圖:
保存退出後從新啓動redis服務,此時redis將之後臺進程的方式啓動服務。終端沒有顯示相關的啓動信息,而且啓動完成後,終端能夠繼續執行其餘的操做。
在redis的src目錄下有一個redis-cli命令,這個就是官方提供的redis客戶端,可使用它來鏈接和操做redis。固然,這僅僅只是一個命令行的客戶端程序,在實際的開發中會有不一樣的平臺語言,所以官網也提供了對各類語言的客戶端實現,在實際的項目開發中使用不一樣語言的客戶端來操做redis。例如官網提供了一個Java的客戶端Jedis。
1)使用redis-cli
可使用使用官方自帶的redis-cli客戶端來鏈接redis服務。參數-h爲鏈接redis服務器的IP地址,-p爲redis的端口號。鏈接完成後就能夠對redis進行操做了,咱們使用簡單的set和get命令來進行存儲和訪問操做。
2)退出客戶端
若是想要退出客戶端的鏈接只須要在鏈接的狀態下輸入quit或者exit便可。
3)身份認證
默認鏈接Redis時是不須要認證密碼的,咱們能夠爲其設置一個鏈接的認證密碼。首先在redis.conf中找到requirepass配置項,取消註釋並設置一個密碼。
保存後重啓服務,在鏈接客戶端時加上-a參數並輸入配置的密碼。
鏈接時也能夠不指定密碼也能夠正常鏈接,但在操做Redis時候會提示一個錯誤,要求輸入認證密碼。這時使用auth命令來輸入密碼便可。
若是設置了認證密碼,在關閉客戶端時也一樣須要指定。
也可使用第三方的redis的可視化客戶端RDM(redis-desktop-manager),它同時提供了各類系統平臺的編譯版本,安裝後便可使用。下載地址:
點擊左上角的Connect to Redis Server,在彈出的窗口中填寫相關的Name(鏈接名稱)、Address(鏈接地址)、端口號以及認證密碼(Auth),點擊OK便可。
這裏咱們看到鏈接redis後默認有16個庫(0 ~ 15),這是redis默認的配置,能夠在redis.conf中能夠找到相應的選項並修改默認數量。
當咱們使用客戶端鏈接redis時,默認選擇的是index爲0的數據庫,然而也可使用select命令選擇其餘數據庫。例如選擇index爲15的數據庫,以下操做:
若是使用前端啓動redis,可使用control+c或者kill命令來殺掉進程的方式關閉redis(注意:control+c並不能中止後端啓動的redis),但這些方式都是強制性的關閉redis,因爲redis保存的數據先會存儲在內存,若是此時強制關閉,將致使redis還沒將數據持久化到文件中就退出,可能會照成部分的數據丟失。所以,應該使用正常的退出方式來中止redis服務,正常退出redis一樣使用redis-cli客戶端。
上面的命令表示關閉本機端口爲6379的redis服務。
Redis支持五種數據類型:string(字符串),hash(哈希),list(列表),set(集合)及sorted set(zset:有序集合)。
String 是 redis 最基本的類型,一個 key 對應一個 value。它是二進制安全的,能夠包含任何數據,如jpg圖片或者序列化的對象。
1)SET
語法:set key value
賦值操做。
2)GET
語法:get key
取值操做。
3)GETSET
語法:getset key value
取值並賦值。
4)MSET
語法:mset key value [key value ...]
同時設置多個鍵值。
5)MGET
語法:mget key [key ...]
獲取多個鍵值。
6)DEL
語法:del key [key ...]
刪除一個或多個鍵值對。
7)INCR
語法:incr key
當存儲的字符串是整數時,讓當前鍵值遞增,並返回遞增或增長後的值。
8)INCRBY
語法:incrby key increment*
當存儲的字符串是整數時,讓當前鍵值增長指定的數值,並返回遞增或增長後的值。
9)DECR
語法:decr key
讓當前鍵值遞減,並返回遞減或減小後的值。
10)DECRBY
語法:decrby key decrement
讓當前鍵值減小指定的數值,並返回遞減或減小後的值。
11)APPEND
語法:append key value
向鍵值的末尾追加value。若是鍵不存在則將該鍵的值設置爲value,即至關於 SET key value。返回值是追加後字符串的總長度。
12)獲取字符串長度(STRLEN)
STRLEN命令返回鍵值的長度,若是鍵不存在則返回0。
hash是一個string類型的field和value的映射表,而field只能是String類型,hash特別適合用於存儲對象。
1)HSET
語法:HSET key field value
HSET一次只能設置一個字段值。HSET命令不區分插入和更新操做,當執行插入操做時HSET命令返回1,當執行更新操做時返回0。
2)HMSET
語法:HMSET key field value [field value ...]
HMSET和HSET做用同樣,只不過一次能夠設置多個字段值。
3)HSETNX
語法:HSETNX key field value
當字段不存在時賦值,相似HSET。區別在於若是字段存在,該命令不執行任何操做。
例如:hsetnx user name zing
說明:若是user中不存在name字段則設置name的值爲zing,不然不作任何操做。
4)HGET
語法:HGET key field
HGET一次只能獲取一個字段值。
5)HMGET
語法:HMGET key field [field ...]
HMGET一次能夠獲取多個字段值。
6)HGETALL
語法:HGETALL key
獲取全部字段值。
7)HDEL
語法:HDEL key field [field...]
能夠刪除一個或多個字段,返回值是被刪除的字段個數。
8)HINCRBY
語法:HINCRBY key field increment
爲某個字段增長數值。
9)HEXISTS
語法:HEXISTS key field
判斷字段是否存在,存在則返回1,不然返回0。
10)HKEYS
語法:HKEYS key
獲取全部的字段名。
11)HVALS
語法:HVALS key
獲取全部字段的值。
12)HLEN
語法:HLEN key
獲取字段數量。
Redis的list是採用來鏈表來存儲的,因此對於Redis的list數據類型的操做,是操做list的兩端數據來操做的。
1)LPUSH
語法:LPUSH key value [value ...]
向列表左邊添加元素。
2)RPUSH
語法:RPUSH key value [value ...]
向列表右邊添加元素。
3)LRANGE
語法:LRANGE key start stop
LRANGE命令是列表類型最經常使用的命令之一,用於獲取列表中的某一片斷,將返回start到stop之間的全部元素(包含兩端的元素),索引從0開始。索引能夠是負數,如:-1表明最後邊的一個元素。
4)LPOP
語法:LPOP key
LPOP命令從列表左邊彈出一個元素,會分兩步完成:第一步是將列表左邊的元素從列表中移除。第二步是返回被移除的元素值。
5)RPOP
語法:RPOP key
RPOP命令從列表右邊彈出一個元素,步驟與LPOP相似,第一步是將列表右邊的元素從列表中移除。第二步是返回被移除的元素值。
6)LLEN
語法:LLEN key
獲取列表中元素的個數
7)LREM
語法:LREM key count value
LREM命令會刪除列表中前count個值爲value的元素,返回實際刪除的元素個數。根據count值的不一樣,該命令的執行方式會有所不一樣:
當count>0時, LREM會從列表左邊開始刪除。
當count<0時, LREM會從列表右邊開始刪除。
當count=0時,LREM刪除全部值爲value的元素。
8)LINDEX
語法:LINDEX key index
得到指定索引的元素值。
9)LSET
語法:LSET key index value
設置指定索引的元素值。
10)LTRIM
語法:LTRIM key start stop
只保留列表的指定片斷
11)LINSERT
語法:LINSERT key BEFORE|AFTER pivot value
LINSERT首先會在列表中從左到右查找值爲pivot的元素,而後根據第二個參數是BEFORE仍是AFTER來決定將value插入到該元素的前面仍是後面。
12)RPOPLPUSH
語法:RPOPLPUSH source destination
將一個列表的最後一個元素轉移到另外一個列表的最前面
Redis 的 Set 是 String 類型的無序集合。集合成員是惟一的,這就意味着集合中不能出現重複的數據。
1)SADD
語法:SADD key member [member ...]
增長一個或多個元素。
2)SREM
語法:SREM key member [member ...]
移除一個或多個元素。
3)SMEMBERS
語法:SMEMBERS key
得到集合中的全部元素。
4)SISMEMBER
語法:SISMEMBER key member
判斷元素是否存在集合中。存在返回1,不然返回0。
5)SDIFF
語法:SDIFF key [key ...]
查找屬於集合A而且不屬於集合B的元素。(差集運算)
6)SINTER
語法:SINTER key [key ...]
查找屬於集合A且屬於集合B的元素。(交集運算)
7)SUNION
語法:SUNION key [key ...]
查找屬於集合A或者屬於集合B的元素。(合併運算)
8)SCARD
語法:SCARD key
獲取集合中元素的個數。
9)SPOP
語法:SPOP key [count]
從集合中彈出一個或多個元素,由count指定。若是不指定count,默認彈出一個。因爲集合是無序的,全部SPOP命令會從集合中隨機選擇一個元素彈出。
zset又稱sorted set,稱之爲有序集合,可排序的,可是惟一。和set的不一樣支出在於zet會給集合中的元素添加一個分數,而後經過這個分數進行排序。
1)ZADD
語法:ZADD key score member [score member ...]
向有序集合中加入一個或多個元素和該元素的分數,若是該元素已經存在則會用新的分數替換原有的分數。返回值是新加入到集合中的元素個數,不包含以前已經存在的元素。
2)ZSCORE
語法:ZSCORE key member
獲取元素的分數。
3)ZREM
語法:ZREM key member [member ...]
移除有序集合中的一個或多個成員,不存在的成員將被忽略。
4)ZRANGE
語法:ZRANGE key start stop [WITHSCORES]
按照元素分數從小到大的順序返回索引從start到stop之間的全部元素(包含兩端的元素)。若是須要得到元素的分數能夠在命令尾部加上WITHSCORES參數。
5)ZREVRANGE
語法:ZREVRANGE key start stop [WITHSCORES]
按照元素分數從大到小的順序返回索引從start到stop之間的全部元素(包含兩端的元素)。若是須要得到元素的分數的能夠在命令尾部加上WITHSCORES參數。
6)ZRANK
語法:ZRANK key member
獲取元素排名(從小到大)。
7)ZREVRANK
語法:ZREVRANK key member
獲取元素排名(從大到小)。
8)ZRANGEBYSCORE
語法:ZRANGEBYSCORE key min max WITHSCORES
得到指定分數範圍的元素。
9)ZINCRBY
語法:ZINCRBY key increment member
增長某個元素的分數,並返回更改後的分數。
10)ZCARD
語法:ZCARD key
獲取集合元素的數量。
11)ZCOUNT
語法:ZCOUNT key min max
獲取指定分數範圍內的元素個數。
12)ZREMRANGEBYRANK
語法:ZREMRANGEBYRANK key start stop
按照排名範圍刪除元素。
13)ZREMRANGEBYSCORE
語法:ZREMRANGEBYSCORE key min max
按照分數範圍刪除元素。
Redis鍵是二進制安全的,這意味着你可使用任何二進制序列做爲鍵,從像」foo」 這樣的字符串到一個 JPEG文件的內容。空字符串也是合法的鍵。
不要使用太長的鍵。例如,不要使用一個1024字節的鍵,不只是由於佔用內存,並且在數據集中查找key時須要屢次耗時的key比較。
不要使用過短的key。例如,user:1001比u1001更具備實際意義,相對於key自己以及value對象來講,增長的空間微乎其微。固然,短的鍵會消耗少的內存,須要找到平衡點。
規範一種模式 (schema)。用冒號或者下橫線來鏈接多單詞字段,例如:」user:1000」或者"user_1000"。
1)KEYS
語法:keys pattern
返回指定pattern的全部key
2)EXISTS
語法:exists key
判斷一個key是否存在。存在返回後1,不然返回0。
3)RENAME
語法:rename key newkey
重命名key
4)TYPE
語法:type key
根據key返回value的類型。
5)EXPIRE
語法:expire key seconds
設置key的生存時間。Redis的數據是緩存在內存中的,而後不少時候數據通常都會設置一個過時時間(即到期後銷燬數據,從而釋放更多的內存)。過時時間默認以秒爲單位,默認值爲-1,表示永不過時。
也能夠在設值的時候指定過時時間(秒)
6)TTL
語法:ttl key
查看key剩餘的過時時間。
7)PERSIST
語法:persist key
清除key的過時時間。
8)PEXPIRE
語法:pexpire key
以毫秒爲單位設置key的過時時間。
也能夠在設值的時候指定過時的時間(毫秒)
Redis是一個支持持久化的內存數據庫,能夠將內存中的數據同步到磁盤保證持久化。咱們知道Redis會將數據緩存在內存中,若是沒有持久化,在服務器關閉或重啓以後數據會丟失。爲了保證數據的安全以及效率,Redis會週期性的把更新的數據寫入磁盤或者把修改操做寫入追加的記錄文件。而Redis提供了RDB和AOF兩種持久化策略。
Redis默認是會以快照RDB的形式將數據持久化到磁盤的一個dump.rdb二進 制文件。當Redis決定要持久化時,會 fork 一個子進程將數據寫到磁盤上一個臨時的RDB文件中,當子進程完成寫操做後,將原來的RDB替換掉。而Redis會在知足某些條件後會進行持久化,而且能夠對其進行配置。
配置RDB
在redis.conf文件中找到「Save the DB on disk」的配置,咱們能夠根據須要來修改這Redis的RDB持久化策略。
說明:
save 900 1(若是在900秒以內有1次操做,則執行快照保存)
save 300 10(若是在300秒內有10次操做,則執行快照保存)
save 60 10000(若是在1分鐘以內有10000個次操做,則執行快照保存)
SAVE和BGSAVE
咱們能夠在客戶端直接使用SAVE或者BGSAVE命令當即將Redis的數據持久化到RDB文件中。他們二者的區別在於BGSAVE命令會fork一個子進程在後臺進行持久化,主進程能夠繼續處理客戶端發送的命令(非阻塞)。而SAVE命令須要等待Redis持久化完成後才能夠繼續處理客戶端發送的命令(阻塞)。
RDB優勢
RDB很是適合用於數據備份, 能夠在當天內每小時備份一次,或者每月的天天都進行備份。 若是遇到斷電或者宕機等其餘一些災難狀況,能夠隨時將數據集還原。
RDB缺點
若是對數據的完整性和安全性要求很是高,要求每一次的操做數據都能持久化到文件中,這時RDB就不太適合了。由於RDB是按照時間範圍的操做次數爲條件促發持久化,若是未知足這些觸發條件,Redis並不會將數據保存到文件,致使數據丟失。例如:save 60 10000,若是在1分鐘以內有9000次的操做,若是此時服務器異常退出或宕機,因爲未知足條件,將致使丟失這1分鐘的數據。
AOF持久化能夠記錄每一個寫操做,將Redis執行過的全部寫指令(讀操做不記錄)保存到appendonly.aof文件中,而且只容許追加文件而不能夠改寫文件。在Redis啓動的時候會讀取該文件從新構建緩存數據。在打開AOF持久化機制以後,Redis每當接收到一條寫命令,會先寫入系統緩存,而後每隔必定時間(默認是每秒鐘)fsync一次(寫入到指定文件)。
啓用AOF
AOF持久化默認是關閉的,若是要啓用AOF,須要在redis.conf配置文件中啓用該功能,將appendonly no設置爲appendonly yes。
全部寫操做默認保存在appendonly.aof文件中,能夠自行修改保存的路徑和文件名。
同步策略
AOF提供了三種同步策略:
always(每次寫操做就執行一次fsync)
everysec(每秒執行一次fsync,默認)
no(不執行fsync)
AOF重寫
AOF會記錄Redis全部的寫操做命令,但這種方式會形成一個問題,就是隨着時間的推移,大量頻繁的操做將致使AOF文件體積的急劇增加,對系統會形成影響。爲了解決以上的問題, Redis就須要對AOF文件進行重寫。重寫的過程會建立一個新的AOF文件來代替原有的AOF文件, 而新AOF文件和原有AOF 文件保存的數據狀態是一致的,但新文件的體積將變得儘量地小。如下兩種方式會觸發AOF重寫。
1)手動出發
在客戶端直接向Redis發送BGREWRITEAOF命令,這個命令會經過移除AOF文件中的冗餘命令來重寫(rewrite)AOF文件。
2)自動觸發
其實在啓用了AOF以後(appendonly yes),Redis會依據redis.conf配置文件中的auto-aof-rewrite-percentage選項和auto-aof-rewrite-min-size選項來自動執行BGREWRITEAOF命令。
說明:
例如設置了auto-aof-rewrite-percentage爲100和auto-aof-rewrite-min-size爲64mb,那麼當AOF文件的體積大於64MB時,而且AOF文件的體積比上一次重寫以後的體積大一倍(100%)的,Redis將執行BGREWRITEAOF命令進行重寫。
AOF優勢
AOF彌補了RDB按照時間範圍的操做次數爲條件的缺點,即便在默認的策略中發生故障,最多也只會丟失一秒鐘的數據,更大程度的保證了數據的安全性。
AOF缺點
AOF會保存每一次的寫操做,這將致使AOF文件的體積一般要大於RDB文件。若是選用always策略,則表示每一次操做都會記錄到AOF文件中,從性能的角度上來講會低於RDB。固然,使用默認的everysec策略進行持久化性能仍是很是可觀的。
在實際應用中,一般會同時使用RDB和AOF兩種持久化來找到一個最佳的平衡點,即能保證性能的同時最大程度保證數據的安全。所以須要RDB和AOF二者同時進行合理的設置和調整。而從Redis 4.0開始,官方提供了一種更加方便的混合持久化配置。
未啓用混合持久化
在未啓用混合持久化以前,若是咱們往Redis寫入一條記時,RDB文件會保存操做的鍵值數據,AOF文件則保存的是寫操做的指令,咱們能夠分別查看一下這兩個文件的內容。
使用cat命令查看RDB文件
然而顯示的內容並不太直觀也不易理解,所以能夠藉助Redis提供的redis-check-rdb工具進行查看。
RDB文件中會保存Redis的相關信息以及存儲的keys數量和相關的活期時間。接下來咱們繼續查看AOF文件的內容,直接使用cat命名進行查看。
結果顯示AOF文件中保存的是相關的操做指令。
啓用混合持久化
要使用混合持久化,除了在redis.conf文件中啓用AOF(將appendonly設置爲yes),還須要將aof-use-rdb-preamble設置爲yes。
設置完從新啓用Redis服務。啓用了混合持久化以後,使用BGREWRITEAOF命令執行一次AOF重寫,同時向Redis插入一條新的數據。
而後再次使用cat命令再次查看AOF文件,這時會發現啓用混合持久化以後的AOF文件內容和未啓用時的AOF文件內容不同。這是由於此時產生的AOF文件是一個RDB-AOF的混合文件,Redis會基於某種協議將此文件的前半部分存儲RDB的數據,後半部分存儲的是AOF的操做命令。
Redis事務能夠一次執行多個命令(批量命令操做),而且是一個單獨的隔離操做。事務中的全部命令都會按順序地執行。事務在執行的過程當中,不會被其餘客戶端發送來的命令請求所打斷。
Redis事務主要由MULTI 、 EXEC、DISCARD、WATCH和UNWATCH這些基礎命令構成。
1)MULTI
語法:MULTI
用於標記事務的開始,後續客戶端執行的命令都將被存入一個命令隊列,直到執行EXEC時,這些命令纔會被執行。
2)EXEC
語法:EXEC
執行命令隊列中的全部命令,但若是在啓用一個事務以前執行了WATCH命令,那麼只有當WATCH所監控的keys沒有被修改的前提下,EXEC命令才能執行事務隊列中的全部命令,並返回全部命令的執行結果,不然EXEC將放棄當前事務中的全部命令。
3)DISCARD
語法:DISCARD
取消事務隊列中的全部命令,並將當前鏈接的狀態恢復爲非事務狀態。若是WATCH命令被使用,會自動執行UNWATCH取消監視的全部keys。
4)WATCH
語法:WATCH key[key...]
WATCH命令相似於關係型數據庫的樂觀鎖,能夠在啓用事務以前監視某些keys的變化。在MULTI命令執行以前,能夠指定須要監視的keys,在執行EXEC以前,若是被監控的keys發生修改,EXEC將放棄執行該隊列中的全部指令。而且WATCH命令能夠監控一個或多個鍵,一旦其中有一個鍵被修改(或刪除),以後的事務就不會執行。
首先打開一個客戶端,並使用watch命令監視user:1001的key,接着使用multi啓用事務。
而後打開第二個客戶端,並修改key爲user:1001的value爲user01。
最後回到第一個客戶端再次對key爲user:1001的value修改成user001,並執行exec命令。因爲user:1001這個key被第一個客戶端所監視,而這個key在啓用事務前被第二個客戶端修改了,所以當第一個客戶端啓用事務後再對其進行修改時這是無效的,Redis將放棄隊列中的全部指令,返回了(nil)。
5)UNWATCH
語法:WATCH key[key...]
取消當前事務中指定監控的keys。若是執行了EXEC或DISCARD命令,則無需再手工執行該命令了,由於在此以後UNWATCH命令會自動執行,事務中全部的keys都將自動取消監控。
在關係型數據庫中的原子性表明一系列不可分割的操做,要麼所有執行成功,要麼所有不執行。若是執行過程當中產生了錯誤或者異常,那麼事務將會自動回滾。而在Redis的事務中是否具有原子性呢?咱們看看如下兩種狀況,並得出相關的結論。
錯誤指令
在使用multi命令開啓事務以後,而後輸入一些命令,其中包含一個錯誤的命令。
從結果來看彷佛有點符合咱們對事務的理解。但仔細想一想,這只是在輸入命令的時候產生語法的錯誤,Redis對其進行了校驗,報錯以後Redis就放棄了這個事務。所以得出的結論是:Redis在啓用事務輸入操做命令時是原子操做,它會對命任何一個命令進行語法檢查,當輸入有誤時,Redis會清空隊列並放棄事務。
運行時錯誤
若是輸入的命令都正確,而在執行這些命令時產生了錯誤,Redis是否會取消全部命令並放棄事務呢?看下面的例子。
當執行到第二條命令時產生了錯誤(用戶名不是一個整型數值,並不能自增),可是前面和後面的命令都執行成功。並不會由於執行了一個錯誤的命令而回退全部已經執行成功的命令並放棄整個事務。所以得出的結論是:Redis在執行命令隊列時並非原子性的,通俗點說就是Redis自己並不支持事務的回滾機制。