在學習redis之前,我們首先需要瞭解一下NoSQL(非關係資料庫)。非關係型資料庫通常指數據以對象的形式存儲在資料庫中,而對象之間的關係通過每個對象自身的屬性來決定。 為什麼需要NoSQL? (1) High performance - 高併發讀寫 (2) Huge Storage - 海量數據的 ...
在學習redis之前,我們首先需要瞭解一下NoSQL(非關係資料庫)。非關係型資料庫通常指數據以對象的形式存儲在資料庫中,而對象之間的關係通過每個對象自身的屬性來決定。
為什麼需要NoSQL?
(1) High performance - 高併發讀寫
(2) Huge Storage - 海量數據的高效率存儲和訪問
(3) High Scalability && Hig Availability - 高可擴展性和高可用性
NoSQL資料庫的四大分類:
(1) 鍵值(Key - Value)存儲
(2) 列存儲
(3) 文檔資料庫
(4) 圖形資料庫
NoSQL的特點:
(1) 易擴展:資料庫種類多,非關係
(2) 靈活的數據模型:無需對存儲的數據模型進行建立
(3) 大數據量,高性能:具有高讀寫性能
(4) 高可用:可以集成於很多框架
REmote DIctionary Server(Redis)是一個由Salvatore Sanfillippo寫的key-value存儲系統,遵循BSD協議、支持網路、可基於記憶體亦可持久化的日誌型、key-value資料庫,通常稱它為數據結構伺服器,因為值(value)可以是String、Hash、List、Set、Sorted Set等類型。
Redis的應用場景:
(1) 緩存:數據的查詢
(2) 任務隊列:秒殺,搶購
(3) 網站訪問統計
(4) 數據過期處理:精確到毫秒
(5) 應用排行榜
(6) 分散式集群架構中的session分離
Redis與其他 key-value緩存產品有以下三個特點:
- Redis支持數據的持久化,可以將記憶體中的數據保存在磁碟中(在寫入的時候可能會存在數據丟失),重啟的時候可以再次載入進行使用。
- Redis不僅僅支持簡單的key-value類型的數據,同時還提供list、set、sorted set、hash等數據結構的存儲。
- Redis支持數據的備份,即master-slave模式的數據備份。
Redis連接
Jedis是Redis官方推薦的Java連接開發工具。
// 1.設置IP地址和埠 Jedis jedis = new Jedis("localhost", 6379); // 2.保存數據 jedis.set("name", "張三"); String val = jedis.get("name"); System.out.println(val); // 3.關閉資源 jedis.close();
基於連接池的連接
// 獲得連接池的配置對象 JedisPoolConfig config = new JedisPoolConfig(); // 設置最大連接數 config.setMaxTotal(30); // 設置最大的空閑連接數 config.setMaxIdle(10); // 設置最大等待時間 config.setMaxWaitMillis(1000); try( // 獲得連接池 JedisPool jedisPool = new JedisPool(config, "localhost", 6379); Jedis jedis = jedisPool.getResource(); ) { jedis.set("name1","00001"); String val = jedis.get("name1"); System.out.println(val); }catch (Exception e){ e.printStackTrace(); }
Redis 優勢
- 性能極高:Redis最高讀取速度是110000次/s,寫入速度是81000次/s。
- 豐富的數據類型進行存儲。
- 操作原子性:Redis的所有操作都是原子性的,並且支持多個操作通過MULTI和EXEC指令包裹起來後的原子性。
有關redis的下載安裝請查考 https://www.runoob.com/redis/redis-install.html
Window:
- 運行服務端:打開一個 cmd 視窗 使用 cd 命令切換目錄到 redis安裝目錄(如:D:\redis) 運行:redis-server.exe redis.windows.conf 啟動服務端,也可以直接點擊 redis.window.conf 進行運行。
- 訪問服務端:另啟一個cmd視窗(原來打開的cmd視窗不要關閉,不然無法訪問服務端),使用cd命令切換到redis的安裝目錄下運行: redis-cli.exe -h 127.0.0.1 -p 6379
Redis配置
Redis的配置文件位於Redis安裝目錄下文件名為redis.windows.conf中,也可以通過config命令查看或設置配置項。
Redis CONFIG 命令格式如下:
redis 127.0.0.1:6379> CONFIG GET CONFIG_SETTING_NAME
可以使用 * 號獲取所有配置項:config get *
Redis 存儲數據類型
- 字元串(字元串):string是redis最基本的類型,是二進位安全的,意思是redis的string可以包含任何數據,比如jpg圖片或者序列化的對象。一個鍵最大存儲為512MB。
(1) 存:set key1 value1
(2) 取:get key1
(3) 獲取並設置:getSet key1 value2
(4) 刪除:del key1
(5) 遞增:incr key1 (將key1的值遞增一次,如果不存在這個值,則先將這個值設置為0,然後遞增1;如果不能轉為整形,則返回錯誤信息。)
(6) 遞減:decr key1 (將key1的值遞減一次,如果不存在這個值,則先將這個值設置為0,然後遞減1;如果不能轉為整形,則返回錯誤信息。)
(7) 遞增值:incrby key1 val1 (將key1的值遞增val1,如果不存在這個值,則先將這個值設置為0,然後遞增val1;如果不能轉為整形,則返回錯誤信息。)
(8) 遞減值:decrby key1 val1 (將key1的值遞減val1,如果不存在這個值,則先將這個值設置為0,然後遞減val1;如果不能轉為整形,則返回錯誤信息。)
(9) 拼湊字元串:append key1 val1 (字元串拼接,將redis中key1的值後面拼接一個val1字元串,返回拼接後字元串的長度,如果不存在,則進行創建設置為val1)
2.哈希(hash):hash是一個鍵值對集合,是string類型的field和value的映射表,hash特別適合用於存儲對象。
(1) 存:存單個鍵值對 - hset key1 field1 value1 存多個鍵值對 - hmset key1 field1 value1 field2 value2 ... ...
(2) 取:取單個鍵值 - hget key1 field1 取多個鍵值 - hmget key1 field1 field2 ... ... 取key1對象的全部鍵值 - hgetall key1
(3) 刪除:刪除多個鍵值對 - hdel key1 field1 field2 ... 刪除全部 del key1
3.列表(List):list是一個簡單字元串列表,按照插入順序排序。
(1) 兩端添加:左側 - lpush list1 value1 右側 - rpush list1 value2
(2) 查看:lrange list1 start_number end_number (num可以為負數,負數表示從尾部開始的索引位置)
(3) 兩端彈出:左側 - lpop list1 右側 - rpop list1
(4) 長度:llen list1
(5) 插入:lpushx list1 value1 (僅當list1存在時才在左側插入) rpushx list1 value1 (僅當key1存在時才在右側插入)
(6) 刪除指定值得元素:lrem list1 count_number value1 (刪除list1中count_number個值為value1的元素,如果count_number > 0,表示從左側開始多少個;如果 count_number < 0,表示從右側開始多少個;如果count_number = 0,表示全是全部值為value1的元素。)
(7) 在指定位置添加元素:在指定位置插入元素 - lset list1 index1 value1 在指定元素前插入元素 - linsert list1 before value1 value2 在指定元素後插入元素 - linsert list1 after value1 value2
(8) 將list1中的尾部元素取出並添加到list2的頭部:rpoplpush list1 list2
4.集合(Set):set是string類型的無序集合,set集合中不允許出現重覆的元素。添加一個string元素到key對應的set集合中,成功返回1,如果元素已經在集合中返回0,如果key對應的set不存在則返回錯誤。
(1) 存:sadd set1 value1 value2 ...
(2) 查看:smembers set1
(3) 刪除:srem set1 value1 value2 ...
(4) 判斷在集合中元素是否存在:sismember myset value1 (如果存在,返回1;不存在返回0)
(5) 差集:sdiff set1 set2 (返回在set1中存在的,在set2不存在的元素)
(6) 交集:sinter set1 set2 (返回同時set1、set2中都存在的元素)
(7) 並集:sunion set1 set2 (返回set1、set2的集合,會自動去重)
(8) 獲取元素個數:scard set1
(9) 隨機返回一個元素:srandmember set1
(10) 將兩個set(set1、set2)的差集存放在另一個集合(set3)中:sdiffstore set1 set2 set3
(11) 將兩個set(set1、set2)的交集存放在另一個集合(set3)中:sinterstore set1 set2 set3
(12) 將兩個set(set1、set2)的並集存放在另一個集合(set3)中:sunionstore set1 set2 set3
5.有序集合zset(Sorted set):zset和set一樣也是string類型元素的集合,且不允許重覆的成員。不同的是每個元素都會關聯一個double類型的分數。Redis正是通過分數來為集合中的成員進行排序。
(1) 添加元素:zadd sort1 score1 value1 score2 value2 ... ... (返回添加元素的個數)
(2) 獲取元素:獲取元素的分數 - zscore sort1 value1 獲取元素的個數 - zcard sort1
(3) 刪除元素:zrem sort1 value1 value2 ... 範圍刪除 - zremrangebyrank sort1 num1 num2 按分數範圍刪除 - zremrangebyscore sort1 score1 score2
(4) 範圍查找:zrange sort num1 num2 顯示分數 - zrange sort1 num1 num2 withscores (分數由小到大) zreverange sort1 num1 num2 withscores (分數由大到小) 按分數由小到大查找 - zrangebyscore sort1 num1 num2 按分數由小到大查找,並顯示分數 - zrangebyscore sort1 num1 num2 withscores 分頁查找 - zrangebyscore sort1 num1 num2 limit start_num stop_num
(5) 分數加減:zscore sort1 score1 value1
(6) 統計分數範圍的元素個數:zcount sort1 score1 score2
Redis的keys的通用操作
(1) 獲取所有key:keys *
(2) 獲取字元開頭的keys:keys prefix?
(3) 刪除key:del key1 key2 ...
(4) 判斷是否存在:exists key1 (返回1-存在,0-不存在)
(5) 重命名:rename key1 new_key1
(6) 設置過期時間(單位:s):expire key1 num
(7) 所剩時間:ttl key1 (無設置過期時間,返回-1)
(8) 獲取類型:type key1
Redis的特性:
- 多資料庫:一個redis可以包含多個資料庫,客戶端可以指定連接某個redis實例的資料庫,一個redis最多可以提供16個資料庫,下標為0~15,客戶端預設連接下標為0的資料庫。(index_表示下標,數值為0~15)
(1) 指定連接那個資料庫:select index_
(2) 將key1移動到另一個資料庫:move key1 index_
2.Redis事務:事務中,所有命令都會串列執行,事務執行期間,redis不會為其它的客戶端提供服務,從而保證命令原子化執行。 Redis命令在事務中可能會執行失敗,但是Redis事務不會回滾,而是繼續會執行餘下的命令。這裡和關係型資料庫有點區別,因為關係型數據在這種情況下都是會回滾的;在multi之後的事務語句,都會將事務放進隊列,這是會檢查語法等,也就是在事務執行期間語法都是沒有問題的,命令出錯的話就是程式有問題,redis不會因為一條錯誤而設計成回滾,降低存儲效率來彌補程式本身的錯誤。redis使用的是串列化隔離機制,串列化機制規定事務的提交必須有序的,如果一個事務打開了,未提交事務或者回滾事務,另外開啟一個事務的話,必須等待前一個事務處理完數據,才能處理數據,否則後面這個事務不能處理數據,所以後提交的數據時會出現鎖為獲取或者未獲取鎖無法提交等等錯誤。
(1) 開啟事務:multi
(2) 提交事務:exec
(3) 回滾事務:discard
Redis的持久化:
redis的高性能是因為所有的數據都是保存在記憶體中。為了保存數據不被丟失,就需要對數據進行持久化。
- RDB方式:預設支持、不需要配置,在指定的時間間隔內,將記憶體中的數據集快照寫入磁碟。
- AOF方式:以日誌的方式,記錄伺服器所處理的每一個操作,在redis啟動的時候會讀取該文件,來重新構建資料庫,保證啟動後資料庫中的數據是完整的。
- 不持久化:通過配置禁用redis持久化的功能,這樣redis只是一個緩存的工具
- 可以RDE、AOF結合使用。
RDB:
優勢:
1、redis的資料庫只包含一個文件,對於文件備份來說很完美
2、備份:如每個小時歸檔一次最近24小時的數據,同時每天歸檔一次最近30天的數據,那麼當系統出現災難性故障的時候,可以恢復(對於災難恢復來說RDB是非常好的選擇,可以將一個單獨的文件壓縮後轉移到其他的存儲介質上)
3、性能最大化:對於redis進程而言,在開始持久化的時候,它唯一需要做的是分叉處一些子進程,之後的由子進程完成這些持久化的工作,極大的避免伺服器進程執行IO操作
4、與AOF相比優勢:啟動效率更高
劣勢:
1、想保證數據的高可用性(最大限度避免數據的丟失),那RDB不是一個很好的選擇(如果系統在定時持久化之前發生故障,那麼數據還沒來得及往磁碟上寫,數據就已經丟失了)
2、子進程協助完成持久化,因此當數據集很大的時候,可能會導致伺服器停止幾百毫秒
配置:
redis 預設使用RDB 方式持久化,配置文件為redis.conf(window下為redis.windows-service.conf)
- save 900 1:表示每900秒至少一個key發生變化,就保存一次
- save 300 10:表示每300秒至少有10個key發生變化,就保存一次
- save 60 10000:表示每60秒至少有10000個key發生變化,就保存一次
- dbfilename dump.rdb:表示存儲數據的文件名
- dir ./ :表示數據的存儲路徑
AOF
優勢:
1、更高的數據安全性。同步策略:每秒同步,每修改同步、不同步。每秒同步:非同步完成,效率高,系統出現宕機,那麼這一秒中修改的數據就會丟失;每修改同步:可以看作同步持久化,麽一次發生數據的變化,都會立即寫到磁碟當中,效率低,但是最安全
2、對日誌文件的寫入操作,採用的是追加模式(append),因此在寫入過程中,即使出現了宕機的情況,也不會破壞日誌文件中已經存在的內容。如果本次寫入進行到一半就出現宕機,那麼這種方式也不必擔心,redis在下一次啟動之前,可以通過redis-check-aof這個工具,幫助我們解決數據一致性的問題
3、如果日誌過大,redis可以自動啟動重寫機制,redis以append模式不斷的將修改的數據寫入到老的磁碟文件當中,同時redis會創建一個新的文件,用於記錄此期間產生的哪些修改命令被執行。因此,在進行重寫切換的時候,可以更好的去保證數據的安全性
4、AOF包含一個格式清晰易於理解的日誌文件用於記錄所有的修改操作,也可以通過這個文件完成數據的重建
劣勢
1、對於相同數量的數據集而言,AOF的文件要比RDB的文件大一些
2、根據同步策略的不同,AOF在效率上往往低於RDB
配置:
redis 配置文件為redis.conf(window下為redis.windows-service.conf)
- 打開 AOF:appenddonly yes
- 日誌文件名稱:appendfilename “appendonly.aof”
- 設置同步策略:每秒同步 - appendfsync always; 每修改同步 - appendfsync everysec; 不同步 - appendfsync no;
AOF下的Redis持久化:啟動後,插入一些數據後,通過flushall清空資料庫,然後關閉redis,重新啟動redis之前,修改日誌文件配置文件,將最後一行的flushAll刪除,並保存,然後重啟redis