Redis的安裝使用
1.Redis是什麼
Redis是一個使用ANSI C(C語言) 編寫的開源的高性能的Key-Value的NoSQL資料庫(非關係型資料庫)。
2.Redis特點
1.基於記憶體
2.可持久化數據
3.具有豐富的數據結構類型,適應非關係型數據的存儲需求
4.支援絕大多數主流開發語言,如C、C++、Java、Python、R、JavaScript等。
5.支援集群模式,高效、穩定。
3.數據模型(A)
1.鍵值對形式。
2.Redis的數據結構類型,指的就是Redis值的結構類型。
4.Redis作用
1.本質是資料庫,能存儲數據。
Redis能靈活處理非關係型數據的讀、寫問題,是對MySQL等關係型資料庫的補充。
新浪微博就是使用Redis集群做資料庫。
2.快取數據。
所謂快取,就是將數據載入到記憶體中後直接使用,而不是每次都通過IO流從磁碟上讀取。好處:讀寫效率高。
而Redis則是將數據直接存儲在記憶體中,只有當記憶體空間不足時,將部分數據持久化到磁碟上。
5.Redis安裝(Linux)
Redis官方只提供了源碼,並沒有提供經過編譯之後的安裝包。因此,安裝Redis,要先編譯、後安裝。(即源碼安裝方式)
5.1 redis安裝步驟
1.下載,上傳到Linux伺服器,並解壓
2.預編譯(實際上是檢查編譯環境的過程)
進入目錄: cd /opt/soft/redis-3.2.9/deps/jemalloc
執行預編譯 ./configure
在預編譯的過程中,會檢測安裝redis所需的相關依賴,依次安裝即可。
如:缺少c編譯環境 yum -y install gcc-c++
預編譯不是必須的步驟,它只是在檢查編譯過程中需要的環境是否滿足。通常源碼包中,都有一個可執行的configure腳本,這個腳本執行預編譯的腳本。但是有一些源碼包中,沒有該文件,可以省略預編譯步驟。
3.編譯 進入/opt/soft/redis-3.2.9/src
make
4.安裝 進入/opt/soft/redis-3.2.9/src
make install
5.啟動redis服務端(指定配置文件)
拷貝redis.conf文件到/etc 目錄下,方便管理。
cp /opt/soft/redis-3.2.9/redis.conf /etc/
/usr/local/bin/redis-server /etc/redis.conf
6.啟動redis客戶端,登陸 /usr/local/bin/redis-cli
6.redis.conf常用配置說明
6.1 requirepass (設置密碼)
給redis設置密碼
在/etc/redis.conf中設置密碼(退出redis登錄用quit)
找到上面這行程式碼改成
設置密碼後需要重新啟動redis服務端 才會生效
在客戶端使用auth命令,驗證密碼。
6.2 databases(資料庫)
Redis默認有16個資料庫,定址角標從0開始。
默認連接db0
客戶端使用select命令可切換資料庫
6.3 port(埠)
指定redis的服務埠,默認6379
6.4 daemonize(後台進程)
Redis默認關閉後台進程模式,改成yes,redis服務在後台啟動。
6.5 loglevel(日誌級別)
6.6 logfile(日誌輸出文件)
Redis日誌輸出目錄,默認不輸出日誌到文件。
6.7 dbfilename(持久化文件名)、 dir(文件路徑)
指定數據持久化的文件名及目錄。
7.將redis添加為系統服務
7.1 第一步:開啟後台模式
修改配置文件,將daemonize改為yes
7.2 第二步:創建shell腳本
Linux系統服務,在/etc/init.d目錄下創建redis腳本
########################### #chkconfig: 2345 10 90 #description: Start and Stop redis PATH=/usr/local/bin:/sbin:/usr/bin:/bin REDISPORT=6379 EXEC=/usr/local/bin/redis-server REDIS_CLI=/usr/local/bin/redis-cli ##判斷redis是否啟動了 PIDFILE=/var/run/redis_6379.pid CONF="/etc/redis.conf" PASSWORD=$(cat $CONF|grep '^\s*requirepass'|awk '{print $2}'|sed 's/"//g') case "$1" in start) if [ -f $PIDFILE ] then echo "$PIDFILE exists, process is already running or crashed" else echo "Starting Redis server..." $EXEC $CONF fi if [ "$?"="0" ] then echo "Redis is running..." fi ;; stop) if [ ! -f $PIDFILE ] then echo "$PIDFILE does not exist, process is not running" else PID=$(cat $PIDFILE) echo "Stopping ..." if [ -z $PASSWORD ] then $REDIS_CLI -p $REDISPORT shutdown else $REDIS_CLI -a $PASSWORD -p $REDISPORT shutdown fi #$REDIS_CLI -p $REDISPORT SHUTDOWN while [ -x ${PIDFILE} ] do echo "Waiting for Redis to shutdown ..." sleep 1 done echo "Redis stopped" fi ;; restart|force-reload) ${0} stop ${0} start ;; *) echo "Usage: /etc/init.d/redis {start|stop|restart|force-reload}" >&2 exit 1 esac ##############################
7.3 第三步:添加shell腳本可執行許可權
chmod +x /etc/init.d/redis
7.4 第四步:添加Redis開機啟動
7.4 第四步:添加Redis開機啟動
8.Redis的值(value)的數據結構類型
一般說Redis的數據結構類型,指的就是redis的值value的類型;
Redis常用的數據結構類型:string、list、set、sortedSet、hash
9.Redis的使用
9.1 key的類型
redis的key 值是二進位安全的,這意味著可以用任何二進位序列作為key值,從形如」foo」的簡單字元串到一個JPEG文件的內容都可以。空字元串也是有效key值。
redis建議使用字元串做為key的類型
9.2 key取值規範
1.鍵值不需要太長,消耗記憶體,在數據中查找這類鍵值的計算成本較高
2.鍵值不宜過短,可讀性較差,通常建議見名知意。
例:user:id:1:username;user:id:1:password 。通過user:id:1*查詢。這就是一種命名方式(不一定要使用這種方式)
9.3 Key命令
9.4 string類型
string類型是redis最常用的數據結構類型,存儲的值為字元串。
string類型相關命令
String類型的應用場景
1.做與統計有關的業務,如新浪微博(微信朋友圈)中的點贊功能
2.解決多執行緒的執行緒安全問題。
Redis的key是單執行緒模式,這就意味一瞬間只有一個執行緒能夠持有這個key,所以可以使用redis解決部分涉及執行緒安全的業務,比如說搶購、秒殺。
再比如學習多執行緒時模擬買票窗口的賣票業務。
9.5 List類型
特點:
1.基於Linked List實現
2.元素是字元串類型
3.列表頭尾增刪快,中間增刪慢,增刪元素是常態
4.元素可以重複出現
5.最多包含2^32-1元素
列表的索引:從左至右,從0開始;從右至左,從-1開始
List類型相關命令
List類型應用場景
1.處理排名類業務。如新浪微博評論、論壇回帖樓層等。
2.聊天室
9.6 Hash類型(散列)
特點
1.由Field(欄位)和與之關聯的value組成map鍵值對
2.field和value是字元串類型;
3.一個hash中最多包含2^32-1鍵值對。
Hash相關命令
Hash的作用
節約記憶體空間:
redis每創建一個鍵,都會為這個鍵儲存一些附加的管理資訊(比如這個鍵的類型,這個鍵最後一次被訪問的時間等等)可以說redis的key相對於值來說,更珍貴!所以資料庫裡面的鍵越多,redis資料庫伺服器在儲存附加管理資訊方面耗費的記憶體就越多,在獲取key對應的value值時cpu的開銷也會更多 。
Hash結構可以將具有關聯關係的一組key-value,存儲到同一個hash結構中,從而減少key的數量。所以在能使用hash的時候盡量使用hash。
不適合使用Hash的場景
在需要只對hash中某個欄位設置過期時,就不建議使用hash。Redis的key的過期功能只能對鍵操作,而Hash結構不能單獨對某一個filed設置過期功能。
9.7 Set類型(集合)
特點
1.無序的、去重的;
2.元素是字元串類型;
3.最多包含2^32-1元素。
Set相關命令
Set應用場景
新浪微博的共同關注:當用戶訪問另一個用戶的時候,會顯示出兩個用戶共同關注哪些相同的用戶(交集)
9.8 SortedSet類型(有序集合)
特點
1.類似Set集合;
2.有序的、去重的;
3.元素是字元串類型;
4.每一個元素都關聯著一個浮點分數值(Score),並按照分數值從小到大的順序排列集合中的元素。分數值可以相同,相同時按字典順序排列
5.最多包含2^32-1元素
SortedSet類型相關命令
SortedSet類型適用場景
適用於需要有序且唯一的業務或操作:
如,網易音樂排行榜:
每首歌的歌名作為元素(唯一、不重複)
每首歌的播放次數作為分值
用zrevrange來獲取播放次數最多的歌曲(就是最多播放榜了,雲音樂熱歌榜,沒有競價,沒有權重)
10.使用Jedis連接redis伺服器
Jedis是Redis官方推薦的Java連接開發工具,可以通過java程式碼操作redis資料庫,就類似於jdbc
10.1 使用jedis連接redis可能會出現的問題及解決方案:
1.ip綁定問題
使用Jedis連接redis伺服器需要把Redis的配置文件redis.conf里的bind 127.0.0.1(或bind localhost)注釋掉,這句話的意思是僅允許本機才能訪問。我們需要讓redis伺服器允許其他主機訪問
2.保護模式(如果設置了密碼可以進行密碼驗證,不用關閉保護模式)
DENIED Redis is running in protected mode because protected mode is enabled…
關閉保護模式:把Redis的配置文件redis.conf中的protected-mode 的yes改成no
10.2 Jedis 相關jar包導入
10.3 Jedis連接redis服務端
package com.gjs.jedis; import org.junit.Test; import redis.clients.jedis.Jedis; public class TestJedis { @Test public void testJedisConnect() throws Exception { //創建客戶端指定連接伺服器端主機ip和埠,埠不指定時默認使用6379 Jedis jedis = new Jedis("192.168.192.128", 6379); System.out.println("連接redis伺服器端成功!"); jedis.auth("1234"); //登錄驗證 //測試連接 System.out.println("redis伺服器是否運行:"+jedis.ping()); System.out.println("redis伺服器資訊:"+jedis.info()); //關閉連接 jedis.close(); } }
10.4 Key測試
jedis類中大部分方法名都與對應的命令同名
@Test public void testKey() throws Exception { //創建客戶端指定連接伺服器端主機ip和埠,埠不指定時默認使用6379 Jedis jedis = new Jedis("192.168.192.128", 6379); System.out.println("連接redis伺服器端成功!"); //登錄驗證 jedis.auth("1234"); jedis.set("name", "zhangsan");//加入數據 System.out.println("獲取key對應的值:"+jedis.get("name")); Set<String> keys = jedis.keys("*");//使用通配符進行模糊查詢 System.out.println("獲取所有key的值:"+keys); //關閉連接 jedis.close(); }
10.5 List測試
@Test public void testList() throws Exception { //創建客戶端指定連接伺服器端主機ip和埠,埠不指定時默認使用6379 Jedis jedis = new Jedis("192.168.192.128", 6379); System.out.println("連接redis伺服器端成功!"); //登錄驗證 jedis.auth("1234"); jedis.lpush("list", new String[] {"a","c","b"});//添加數據 Long len = jedis.llen("list");//獲取長度 System.out.println("list長度:"+len); System.out.println("list元素:"+jedis.lrange("list", 0, len)); System.out.println("指定索引位置的元素:"+jedis.lindex("list", 1)); //關閉連接 jedis.close(); }
10.6 Hash測試
@Test public void testHash() throws Exception { //創建客戶端指定連接伺服器端主機ip和埠,埠不指定時默認使用6379 Jedis jedis = new Jedis("192.168.192.128", 6379); System.out.println("連接redis伺服器端成功!"); //登錄驗證 jedis.auth("1234"); //添加數據 jedis.hset("user", "id", "1"); jedis.hset("user", "name", "zhangsan"); jedis.hset("user", "password", "123456"); //獲取所有元素 Map<String, String> user = jedis.hgetAll("user"); System.out.println("獲取hash的所有欄位值:"+user); //關閉連接 jedis.close(); }
10.7 Set測試
@Test public void testSet() throws Exception { //創建客戶端指定連接伺服器端主機ip和埠,埠不指定時默認使用6379 Jedis jedis = new Jedis("192.168.192.128", 6379); System.out.println("連接redis伺服器端成功!"); //登錄驗證 jedis.auth("1234"); //添加數據 jedis.sadd("set1",new String[] {"a","s","d","f","g"}); jedis.sadd("set2", new String[] {"a","s","z","x"}); //獲取所有元素 Set<String> set1 = jedis.smembers("set1"); System.out.println("獲取set的所有元素:"+set1); System.out.println("獲取元素數量:"+jedis.scard("set1")); //獲取交並補集,方法參數是可變的 Set<String> inter = jedis.sinter("set1","set2"); System.out.println("獲取交集:"+inter); Set<String> union = jedis.sunion("set1","set2"); System.out.println("獲取並集:"+union); Set<String> diff = jedis.sdiff("set1","set2"); System.out.println("獲取差集:"+diff); //關閉連接 jedis.close(); }
10.8 SortedSet測試
@Test public void testSortedSet() throws Exception { //創建客戶端指定連接伺服器端主機ip和埠,埠不指定時默認使用6379 Jedis jedis = new Jedis("192.168.192.128", 6379); System.out.println("連接redis伺服器端成功!"); //登錄驗證 jedis.auth("1234"); //添加數據 Map<String, Double> scoreMembers = new HashMap<>(); scoreMembers.put("a", 1d); scoreMembers.put("b", 3d); scoreMembers.put("c", 2d); jedis.zadd("sortSet", scoreMembers); //獲取數據 //獲取分數值在指定區間的元素並按分數值由小到大排序 Set<String> zrange = jedis.zrange("sortSet", 0, 3); System.out.println(zrange); //關閉連接 jedis.close(); }
11.Redis持久化
Redis持久化,就是將記憶體中的數據,永久保存到磁碟上。
Redis持久化有兩種方式:RDB(Redis DB)、AOF(AppendOnlyFile)。
11.1 RDB(快照模式)
在默認情況下,Redis 將資料庫快照保存在名字為dump.rdb的二進位文件中,可以在redis.conf配置文件中修改持久化資訊。
save 900 1 表示在900秒內,至少更新了1條數據。Redis就將數據持久化到硬碟
save 300 10 表示在300內,至少更新了10條數據,Redis就會觸發將數據持久化到硬碟
save 60 10000 表示60秒內,至少更新了10000條數據,Redis就會觸發將數據持久化到硬碟
11.1.1 策略
1.自動:BGSAVE
按照配置文件中的條件滿足就執行BGSAVE;非阻塞,Redis服務正常接收處理客戶端請求;
Redis會folk()一個新的子進程來創建RDB文件,子進程處理完後會向父進程發送一個訊號,通知它處理完畢,父進程用新的dump.rdb替代舊文件。
2.手動:SAVE
由客戶端(redis-cli)發起SAVE命令;阻塞Redis服務,無法響應客戶端請求;創建新的dump.rdb替代舊文件。
11.1.2 優點
1.執行效率高;
2.恢復大數據集速度較AOF快。
11.1.3 缺點
1.會丟失最近寫入、修改的而未能持久化的數據;
2.folk過程非常耗時,會造成毫秒級不能響應客戶端請求。
11.2 AOF(追加模式、文本重演)
AOF(Append only file),採用追加的方式保存,默認文件appendonly.aof。記錄所有的寫操作命令,在服務啟動的時候使用這些命令就可以還原資料庫。AOF默認關閉,需要在配置文件中手動開啟。
11.2.1 寫入機制
說明:AOF機制,添加了一個記憶體緩衝區(buffer)。
1.將內容寫入緩衝區
2.當緩衝區被填滿、或者用戶手動執行fsync、或者系統根據指定的寫入磁碟策略自動調用fdatasync命令,才將緩衝區里的內容真正寫入磁碟里。
3.在緩衝區里的內容未寫入磁碟之前,可能會丟失。
11.2.2 寫入磁碟的策略
appendfsync選項,這個選項的值可以是always、everysec或者no
Always:伺服器每寫入一個命令,就調用一次fdatasync,將緩衝區裡面的命令寫入到硬碟。這種模式下,伺服器出現故障,也不會丟失任何已經成功執行的命令數據
Everysec(默認):伺服器每一秒重調用一次fdatasync,將緩衝區裡面的命令寫入到硬碟。這種模式下,伺服器出現故障,最多只丟失一秒鐘內的執行的命令數據
No:伺服器不主動調用fdatasync,由作業系統決定何時將緩衝區裡面的命令寫入到硬碟。這種模式下,伺服器遭遇意外停機時,丟失命令的數量是不確定的
運行速度:always的速度慢,everysec和no都很快
11.2.3 AOF重寫機制
AOF文件過大,合併重複的操作,AOF會使用儘可能少的命令來記錄。
重寫過程
1.folk一個子進程負責重寫AOF文件
2.子進程會創建一個臨時文件寫入AOF資訊
3.父進程會開闢一個記憶體緩衝區接收新的寫命令
4.子進程重寫完成後,父進程會獲得一個訊號,將父進程接收到的新的寫操作由子進程寫入到臨時文件中
5.新文件替代舊文件
重寫的本質:就是將操作同一個鍵的命令,合併。從而減小AOF文件的體積
AOF重寫觸發機制
1.手動:客戶端向伺服器發送BGREWRITEAOF命令
2.自動:配置文件中的選項,自動執行BGREWRITEAOF命令
auto-aof-rewrite-min-size ,
觸發AOF重寫所需的最小體積:只要在AOF文件的體積大於等於size時,才會考慮是否需要進行AOF重寫,這個選項用於避免對體積過小的AOF文件進行重寫
auto-aof-rewrite-percentage
指定觸發重寫所需的AOF文件體積百分比:當AOF文件的體積大於auto-aof-rewrite-min-size指定的體積,並且超過上一次重寫之後的AOF文件體積的percent %時,就會觸發AOF重寫。(如果伺服器剛剛啟動不久,還沒有進行過AOF重寫,那麼使用伺服器啟動時載入的AOF文件的體積來作為基準值)。將這個值設置為0表示關閉自動AOF重寫。
11.2.4 優點
寫入機制:默認Everysec每秒執行,性能很好不阻塞服務,最多丟失一秒的數據;
重寫機制:優化AOF文件,如果誤操作了(FLUSHALL等),只要AOF未被重寫,停止服務移除AOF文件尾部FLUSHALL命令,重啟Redis,可以將數據集恢復到FLUSHALL 執行之前的狀態。
11.2.5 缺點
1.相同數據集,AOF文件體積較RDB大了很多;
2.恢復資料庫速度較RDB慢(文本,命令重演)。