Redis簡介 Redis是什麼 Redis是一個開源的,使用ANSI C 編寫,高性能的Key Value的NoSQL資料庫。 Redis特點 1. 基於記憶體 2. 可持久化數據 3. 具有豐富的數據結構類型,適應非關係型數據的存儲需求 4. 支持絕大多數主流開發語言,如C、C++、Java、Py ...
Redis簡介
Redis是什麼
Redis是一個開源的,使用ANSI C 編寫,高性能的Key-Value的NoSQL資料庫。
Redis特點
- 基於記憶體
- 可持久化數據
- 具有豐富的數據結構類型,適應非關係型數據的存儲需求
- 支持絕大多數主流開發語言,如C、C++、Java、Python、R、JavaScript等。
- 支持集群模式,高效、穩定。
數據模型(重點)
- 鍵值對形式。
- Redis的數據結構類型,指的就是Redis值的結構類型。
Redis作用
本質是資料庫,能存儲數據。
Redis能靈活處理非關係型數據的讀、寫問題,是對MySQL等關係型資料庫的補充。新浪微博就是使用Redis集群做資料庫。應用場景:微博、即時通訊、驗證碼等
緩存數據。
所謂緩存,就是將數據載入到記憶體中後直接使用,而不是每次都通過IO流從磁碟上讀取。好處:讀寫效率高。而Redis則是將數據直接存儲在記憶體中,只有當記憶體空間不足時,將部分數據持久化到磁碟上。
在 Linux 上安裝 Redis
- 在官網上下載最新版源碼
wget http://download.redis.io/releases/redis-5.0.5.tar.gz
- 解壓
tar -xzvf redis-5.0.5.tar.gz
- 預編譯,檢測是否滿足環境需求
cd redis-5.0.5/deps/jemalloc/
./configure
缺少什麼就安裝什麼
- 安裝
回到源碼根目錄
make
make install
- 拷貝配置文件
cp redis.conf /etc/redis.conf
- 通過配置文件啟動 redis 服務
redis-server /etc/redis.conf
redis.conf常用配置說明
requirepass foobar
給redis設置密碼,去掉#號,修改自己需要的密碼。在客戶端使用auth命令,驗證密碼。
databases 16
Redis預設有16個資料庫,定址角標從0開始。預設連接db0
客戶端使用select命令,切換資料庫
port 6379
指定redis的服務埠,預設6379.
daemonize no
Redis預設關閉後臺進程模式,改成yes,redis服務在後臺啟動。
logfile “ ”
Redis日誌輸出目錄,預設不輸出日誌到文件。
dbfilename dump.rdb、dir ./
指定數據持久化的文件名及目錄。
將redis添加為系統服務
第一步:開啟後臺模式
修改配置文件,將daemonize改為yes
第二步:創建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
##############################
第三步:添加shell腳本可執行許可權
chmod +x /etc/init.d/redis
第四步:添加Redis開機啟動
chkconfig --add redis
chkconfig redis on
Redis的值value(數據結構類型)
Redis的數據結構類型,指的就是redis的值value的類型。
Redis常用的數據結構類型:string、list、set、sortedSet、hash
Redis的鍵key
key的類型
redis的key 值是二進位儲存的,這意味著可以用任何二進位序列作為key值,從形如”foo”的簡單字元串到一個JPEG文件的內容都可以。空字元串也是有效key值。
redis建議使用字元串做為key的類型
key取值規範
- 鍵值不需要太長,消耗記憶體,在數據中查找這類鍵值的計算成本較高
- 鍵值不宜過短,可讀性較差,通常建議見名知意。
127.0.0.1:6379> set user:id:1:username lisi
OK
127.0.0.1:6379> set user:id:1:password 111111
OK
127.0.0.1:6379> set user:id:1:email [email protected]
OK
127.0.0.1:6379> keys user:id:1* #查找有幾個屬性
1) "user:id:1:password"
2) "user:id:1:username"
3) "user:id:1:email"
Key命令
Redis的key是單線程模式,這就意味一瞬間只有一個線程能夠持有這個key,所以可以使用redis解決部分涉及線程安全的業務。比如,在初級時候通過多線程模擬賣票,使用加鎖的方式,保證只有一個線程能夠持有鎖,進行買票業務。
exists key
檢查給定key是否存在。註意事項: 不支持通配符
del key
刪除一個key
del key1 key2 key3 刪除多個key
keys pattern (模糊查找)
查找所有符合給定模式 pattern 的 key 。
- keys * 匹配資料庫中所有 key 。
- keys n?me 匹配 name、neme、nfme 等。
- keys n* 匹配 name、neme、naaaaame等。
- keys n[ae]me 只能匹配 name、neme。
expire key seconds
指定key的過期時間。新添加的key,如果沒有指定過期時間,則會一直保存。
可以對一個已經帶有生存時間的key執行EXPIRE命令,新指定的生存時間會取代舊的生存時間。
ttl key (time to live)
查看某個key的剩餘過期時間,返回值:
- -2 表示這個key已經過期,刪除掉
- -1 表示沒有設置過期時間
其它 表示剩餘的生存時間,單位為秒。
rename
語法格式:rename key newkey
將 key 改名為 newkey 。
- 當 key 和 newkey 相同,或者 key 不存在時,返回一個錯誤。
- 當 newkey 已經存在時, RENAME 命令將覆蓋舊值。
127.0.0.1:6379> set orgKey yes
OK
127.0.0.1:6379> set newKey no
OK
127.0.0.1:6379> rename orgKey newKey
OK
127.0.0.1:6379> keys *
1) "newKey"
127.0.0.1:6379> get newKey
"yes"
type key
查看key對應的value的數據結構類型。
get key
獲取某一個key的值
string類型
string類型是redis最常用的數據結構類型,存儲的值為字元串。
String相關命令
set key value
設置一個key,值為value,類型為String類型;如果這個key已經存在,則更新這個key的值。
返回值
- 1 表示成功
- 0 表示失敗
setnx key value
如果這個key不存在,則設置一個key,值為value;如果key存在,則不做更新。
返回值
- 1 表示成功
- 0 表示失敗
get key
獲取key對應的value值;如果key不存在,則返回nil
mget key1 key2 key3
一次獲取多個key的值,如果對應key不存在,則對應返回nil。
incr key (increment)
將 key 中儲存的數字值增一,然後返回。如果這個key不存在,那麼key的值會先被初始化為0,然後再執行INCR操作。
如果這個key對應的value值,不能表示數字,則會返回一個錯誤。
incrby key increment
將key增加指定的步長值。increment是步長
decr key (decrement)
將 key 中儲存的數字值減一,然後返回。如果這個key不存在,那麼key的值會先被初始化為0,然後再執行INCR操作。
如果這個key對應的value值,不能表示數字,則會返回一個錯誤。
decrby key decrement
將key減少對應的步長值。
append key value
如果key已經存在,則將value追加到這個key原先的value值的末尾。如果這個key不存在,則執行set操作。
String類型的應用場景
- 做與統計有關的業務,如新浪微博(微信朋友圈)中的點贊功能
- 解決多線程的線程安全問題
List類型
特點
- 基於Linked List實現
- 元素是字元串類型
- 列表頭尾增刪快,中間增刪慢,增刪元素是常態
- 元素可以重覆出現
- 最多包含2^32-1元素
列表的索引:
- 從左至右,從0開始
- 從右至左,從-1開始
List類型相關命令
lpush key value [value ...]
將一個或多個值value插入到列表key的表頭(即從左邊插入);
如果有多個value值,那麼各個value值按從左到右的順序依次插入到表頭:比如說,對空列表mylist執行命令LPUSH mylist a b c
,列表的值將是 c b a 這等同於原子性地執行 LPUSH mylist a
、 LPUSH mylist b
和 LPUSH mylist c
三個命令;
如果 key 不存在,一個空列表會被創建並執行 LPUSH 操作。
當 key 存在但不是列表類型時,返回一個錯誤。
rpush key value [value ...]
尾部添加(從右向左),操作同上。
llen key
返回key對應list的長度,key不存在返回0,如果key對應類型不是list返回錯誤
lindex key index
獲取 list 某一元素,index是元素在list列表中的下角標,從0開始; lindex 是從左到右取元素
lrange key start stop
獲取指定區間的所有元素;
下角標從0開始,0表示第一個元素,1表示第二個,依次類推;-1表示最後一個元素,-2表示倒數第二個元素,依次類推;
lpop key
移除並返回列表中的第一個元素
rpop key
移除並返回列表中的最後一個元素。
List類型應用場景
- 處理排名類業務。如新浪微博評論、論壇回帖樓層等。
- 聊天室
Hash類型(散列)
特點
- 由Field和與之關聯的value組成map鍵值對
- field和value是字元串類型;
- 一個hash中最多包含2^32-1鍵值對
Hash相關命令
hset key field value
設置hash field為指定值,如果key不存在,則先創建;如果field已經存在,那麼將更新這個field的值。
hget key field
獲取指定的hash field
hmget key filed1....fieldN
獲取全部指定的hash filed
hmset key filed1 value1 ... filedN valueN
同時設置hash的多個field
hexists key field
測試指定field是否存在
hdel key field
刪除指定的hash field
hlen key
返回指定hash的field數量
hkeys key
返回hash的所有field
hvals key
返回hash的所有value
hgetall
返回hash的所有filed和value
Hash的用途(能使用hash的時候儘量使用hash)
節約記憶體空間!
redis每創建一個鍵,都會為這個鍵儲存一些附加的管理信息(比如這個鍵的類型,這個鍵最後一次被訪問的時間等等),redis的key相對於值來說,更珍貴!!!
所以資料庫裡面的鍵越多,redis資料庫伺服器在儲存附加管理信息方面耗費的記憶體就越多,在獲取key對應的value值時cpu的開銷也會更多。Hash結構可以將具有關聯關係的一組key-value,存儲到同一個hash結構中,從而減少key的數量。
Set類型(集合)
特點
- 無序的、去重的;
- 元素是字元串類型;
- 最多包含2^32-1元素。
Set相關命令
sadd key member [member ...](無序不重覆)
將一個或多個 member 元素加入到集合 key 當中,已經存在於集合的 member 元素將被忽略。假如 key 不存在,則創建一個只包含 member 元素作成員的集合。
當 key 不是集合類型時,返回一個錯誤。
smembers key
返回集合 key 中的所有成員。不存在的 key 被視為空集合。
spop key
移除並返回集合中的一個隨機元素。當key不存在或key是空集時,返回nil。
scard key
返回集合key的基數(集合中元素的數量)。當key不存在時,返回0。
交集、並集、差集sinter sunion sdiff
sinter key [key ...]
返回一個集合的全部成員,該集合是所有給定集合的交集。不存在的 key 被視為空集。
sunion key [key ...]
返回一個集合的全部成員,該集合是所有給定集合的並集。不存在的 key 被視為空集。
sdiff key [key ...]
返回一個集合的全部成員,該集合是所有給定集合之間的差集。不存在的 key 被視為空集。
SortedSet類型
特點
- 類似Set集合;
- 有序的、去重的;
- 元素是字元串類型;
- 每一個元素都關聯著一個浮點數分值(Score),並按照分值從小到大的順序排列集合中的元素。分值可以相同
- 最多包含2^32-1元素
SortedSet相關命令
zadd key [sort member sort member] :增加值
如: zadd set1 1 zhangsan 2 lisi
zrange key start end 查詢只定範圍的值
如: zrange set1 0 10
zcount key start end 統計一個範圍內元素的個數
如: zcount set1 0 10
zcard key :統計元素的個數
如 : zcard set1
zrank key :返回成員的索引號
如: zrank set1
zrem key [member member] 刪除成員
如: zrem set1 zhangsan
使用Jedis連接redis伺服器
註意事項:
- 必須要放開redis允許啟動主機訪問。註釋
/etc/redis.conf
的bind 127.0.0.1
這句話
- redis處於保護模式,只能本地鏈接,我們需要修改配置文件redis.conf,將protected-mode yes改成no
項目結構:
測試代碼:
import java.util.Set;
import org.junit.Test;
import redis.clients.jedis.Jedis;
public class TestJedis {
@Test
public void testJedisConnect(){
// 連接redis伺服器端(使用host)
@SuppressWarnings("resource")
Jedis jedis = new Jedis("192.168.56.128");
System.out.println("連接redis服務端成功!");
//測試redis伺服器是否正在運行
System.out.println("redis伺服器正在運行嗎?"+ jedis.ping());
System.out.println("redis伺服器信息?\n"+ jedis.info());
}
}
Redis持久化
Redis持久化,就是將記憶體中的數據,永久保存到磁碟上。Redis持久化有兩種方式:RDB(Redis DB)、AOF(AppendOnlyFile)
RDB(快照模式)
在預設情況下,Redis 將資料庫快照保存在名字為dump.rdb的二進位文件中,可以在redis.conf配置文件中修改持久化信息。
- save 900 1 表示在900秒內,至少更新了1條數據。Redis就將數據持久化到硬碟
- save 300 10 表示在300內,至少更新了10條數據,Redis就會觸發將數據持久化到硬碟
- save 60 10000 表示60秒內,至少更新了10000條數據,Redis就會觸發將數據持久化到硬碟
策略
自動:BGSAVE
按照配置文件中的條件滿足就執行BGSAVE
- 非阻塞,Redis服務正常接收處理客戶端請求;
- Redis會folk()一個新的子進程來創建RDB文件,子進程處理完後會向父進程發送一個信號,通知它處理完畢;
手動:SAVE
客戶端(redis-cli)發起SAVE命令
- 阻塞Redis服務,無法響應客戶端請求;
- 創建新的dump.rdb替代舊文件。
優點
- 執行效率高;
- 恢復大數據集速度較AOF快。
缺點
- 會丟失最近寫入、修改的而未能持久化的數據;
- folk過程非常耗時,會造成毫秒級不能響應客戶端請求。
AOF(追加模式、文本重演)
特點
Append only file,採用追加的方式保存,預設文件appendonly.aof。記錄所有的寫操作命令,在服務啟動的時候使用這些命令就可以還原資料庫
AOF預設關閉,需要在配置文件中手動開啟。
寫入機制
說明:AOF機制,添加了一個記憶體緩衝區(buffer)。
- 將內容寫入緩衝區
- 當緩衝區被填滿、或者用戶手動執行fsync、或者系統根據指定的寫入磁碟策略自動調用fdatasync命令,才將緩衝區里的內容真正寫入磁碟里。
- 在緩衝區里的內容未寫入磁碟之前,可能會丟失。
寫入磁碟的策略
appendfsync 選項,這個選項的值可以是always、everysec或者no
- Always:伺服器每寫入一個命令,就調用一次fdatasync,將緩衝區裡面的命令寫入到硬碟。這種模式下,伺服器出現故障,也不會丟失任何已經成功執行的命令數據
- Everysec(預設):伺服器每一秒重調用一次fdatasync,將緩衝區裡面的命令寫入到硬碟。這種模式下,伺服器出現故障,最多只丟失一秒鐘內的執行的命令數據
- No:伺服器不主動調用fdatasync,由操作系統決定何時將緩衝區裡面的命令寫入到硬碟。這種模式下,伺服器遭遇意外停機時,丟失命令的數量是不確定的
運行速度:always的速度慢,everysec和no都很快
aof重寫機制
AOF文件過大,合併重覆的操作,AOF會使用儘可能少的命令來記錄。
重寫過程
- folk一個子進程負責重寫AOF文件
- 子進程會創建一個臨時文件寫入AOF信息
- 父進程會開闢一個記憶體緩衝區接收新的寫命令
- 子進程重寫完成後,父進程會獲得一個信號,將父進程接收到的新的寫操作由子進程寫入到臨時文件中
- 新文件替代舊文件
重寫的本質:就是將操作同一個鍵的命令,合併。從而減小AOF文件的體積
aof重寫觸發機制
- 手動:客戶端向伺服器發送BGREWRITEAOF命令
- 自動:配置文件中的選項,自動執行BGREWRITEAOF命令
auto-aof-rewrite-min-size <size>
,觸發AOF重寫所需的最小體積:只要在AOF文件的體積大於等於size時,才會考慮是否需要進行AOF重寫,這個選項用於避免對體積過小的AOF文件進行重寫auto-aof-rewrite-percentage <percent>
,指定觸發重寫所需的AOF文件體積百分比:當AOF文件的體積大於auto-aof-rewrite-min-size指定的體積,並且超過上一次重寫之後的AOF文件體積的percent %時,就會觸發AOF重寫。(如果伺服器剛剛啟動不久,還沒有進行過AOF重寫,那麼使用伺服器啟動時載入的AOF文件的體積來作為基準值)。將這個值設置為0表示關閉自動AOF重寫。
優點
- 寫入機制,預設fysnc(手工同步)每秒執行,性能很好不阻塞服務,最多丟失一秒的數據;
- 重寫機制,優化AOF文件;
- 如果誤操作了(FLUSHALL等),只要AOF未被重寫,停止服務移除AOF文件尾部FLUSHALL命令,重啟Redis,可以將數據集恢復到FLUSHALL 執行之前的狀態。
缺點
- 相同數據集,AOF文件體積較RDB大了很多;
- 恢複數據庫速度較RDB慢(文本,命令重演)。