Redis 相關入門
1.Redis 特性
- 性能高:基於內存讀寫,讀的速度是11萬次/秒,寫的速度是8.1萬次/秒;
- 多種數據類型:String(字符串)、list(列表)、hash(哈希)、set(集合)、zset(有序集合)等;
- 原子性:所有單個命令都是原子操作,同時還支持對幾個操作合併後的原子性執行(通過 MULTI和 EXEC 指令包起來使用);
- 支持持久化:支持 RDB(快照備份全量數據)和 AOF(只追加文件命令)兩種持久化操作;
- 主從備份:支持 master-slaves 模式的數據備份;
- 分佈式高可用集羣:不僅支持 master-slaves 模式,還支持 Sentinel 模式 + cluster 集羣模式;
- 獨立功能:發佈與訂閱、事務、Lua腳本、排序、二進制位數組;
2.Redis 使用場景
-
緩存
緩存機制幾乎在所有的大型網站都有使用,合理地使用緩存不僅可以加快數據的訪問速度,而且能夠有效地降低後端數據源的壓力。
Redis提供了鍵值過期時間設置,並且也提供了靈活控制最大內存和內存溢出後的淘汰策略。 -
排行榜系統
排行榜系統幾乎存在於所有的網站,例如按照熱度排名的排行榜,按照發布時間的排行榜,按照各種複雜維度計算出的排行榜,Redis提供了列表和有序集合數據結構,
合理地使用這些數據結構可以很方便地構建各種排行榜系統。 -
計數器應用
計數器在網站中的作用至關重要,例如視頻網站有播放數、電商網站有瀏覽數,爲了保證數據的實時性,每一次播放和瀏覽都要做加1的操作,
如果併發量很大對於傳統關係型數據的性能是一種挑戰。Redis天然支持計數功能而且計數的性能也非常好,可以說是計數器系統的重要選擇。 -
社交網絡
贊/踩、粉絲、共同好友/喜好、推送、下拉刷新等是社交網站的必備功能,由於社交網站訪問量通常比較大,而且傳統的關係型數據不太適合保存這種類型的數據,
Redis提供的數據結構可以相對比較容易地實現這些功能。 -
消息隊列系統
消息隊列系統可以說是一個大型網站的必備基礎組件,因爲其具有業務解耦、非實時業務削峯等特性。Redis提供了發佈訂閱功能和阻塞隊列的功能,
雖然和專業的消息隊列比還不夠足夠強大,但是對於一般的消息隊列功能基本可以滿足。 -
分佈式集羣架構中的session分離
-
布隆過濾器
3.Redis 單機安裝
- 下載
官網地址:http://redis.io/
下載地址:http://download.redis.io/releases/redis-3.0.0.tar.gz
- 安裝
#sftp 上傳安裝包到linux
#解壓
tar -zxvf redis.3.0.0.tar.gz
#安裝c語言環境
sudo apt-get install gcc-c++
#編譯
cd redis-3.0.0
make
#安裝
make install PREFIX = /usr/local/redis
# 查看
cd /usr/local/redis
ls
- 啓動
- 前端啓動
#前端啓動命令
./redis-server
#前端啓動的關閉 強制關閉 ctrl+c 正常關閉
./redis-cli shutdown
#tips:一旦客戶端關閉,則redis服務也會停掉
- 後端啓動
# 將 redis 源碼包中的 redis.conf 文件拷貝至 bin 目錄下 cp /root/redis-3.0.0/redis.conf
# 修改 redis.conf 文件,將 daemonize 改爲 yes vim redis.conf
# 使用後端命令啓動 redis
./redis-server redis.conf
#查看是否啓動成功
ps -aux | grep redis
#關閉後端啓動的方式
##強制關閉:
kill -9 進程號
##正常關閉:
./redis-cli shutdown
4.Redis 的對象
- redisObject對象
type // 記錄對象類型
encoding // 記錄對象編碼
ptr // 指向底層實現數據結構的指針
refcount // 引用計數
lru //記錄最後一次被訪問時間
- Redis數據庫中每個鍵值對的鍵和值都是一個對象
- Redis共有字符串、列表、哈希、集合、有序集合五種類型對象,每種類型對象至少都有兩種或以上的編碼方式,不同的編碼可以再不同的使用場景上優化對象的使用效率
- 服務器在執行某些命令之前,會先檢查給定鍵的類型能否執行指定的命令,而檢查一個鍵的類型就是檢查鍵的值對象的類型
- Redis的對象系統帶有引用計數實現的內存回收機制,當一個對象不再被使用時,該對象所佔用的內存就會被自動釋放
- Redis會共享值爲0~9999的字符串對象
- 對象會記錄自己的最後一次被訪問的時間,這個時間可以用於記錄對象的空轉時間
String 字符串對象
類型 | 編碼 | 對象 | 使用場景 |
---|---|---|---|
REDIS_STRING |
REDIS_ENCODING_INT |
使用整數值實現的字符串對象 |
保存的是一個整數值,並且可以用long類型來表示 |
REDIS_STRING | REDIS_ENCODING_EMBSTR | 使用embstr編碼的簡單動態字符串實現的字符串對象 | 保存的是一個字符串且<=39字節 |
REDIS_STRING | REDIS_ENCODING_RAW | 使用簡單動態字符串實現的字符串對象 | 保存的是一個字符串且>39字節 |
List 列表對象
類型 | 編碼 | 對象 | 使用場景 |
---|---|---|---|
REDIS_LIST |
REDIS_ENCODING_ZIPLIST |
使用壓縮列表實現的列表對象 |
同時滿足條件:1.列表對象保存的所有字符串元素的長度都小於64字節;2.列表對象保存的元素個數小於512個。 |
REDIS_LIST | REDIS_ENCODING_LINKEDLIST | 使用雙端列表實現的列表對象 | 不滿足上述條件時,可在配置中修改 |
Hash 哈希對象
類型 | 編碼 | 對象 | 使用場景 |
---|---|---|---|
REDIS_HASH |
REDIS_ENCODING_ZIPLIST |
使用壓縮列表實現的哈希對象 |
同時滿足條件:1.哈希對象保存的所有鍵值對的鍵和值都小於64字節;2.哈希對象保存的鍵值對個數小於512個。 |
REDIS_HASH | REDIS_ENCODING_HT |
使用字典實現的哈希對象 | 不滿足上述條件,可在配置中修改 |
Set 集合對象
類型 | 編碼 | 對象 | 使用場景 |
---|---|---|---|
REDIS_SET |
REDIS_ENCODING_INTSET |
使用整數集合實現的集合對象 |
同時滿足條件:1.集合對象保存的所有元素都爲整數;2.集合對象保存的元素個數小於512個。 |
REDIS_SET | REDIS_ENCODING_HT | 使用字典實現的集合對象 | 不滿足上述條件,可在配置中修改 |
ZSet 有序集合對象
類型 | 編碼 | 對象 | 使用場景 |
---|---|---|---|
REDIS_ZSET |
REDIS_ENCODING_ZIPLIST |
使用壓縮列表實現的有序集合對象 |
同時滿足條件:1.有序集合保存元素個數小於128個;2.有序集合保存的所有元素成員的長度小於64字節。 |
REDIS_ZSET | REDIS_ENCODING_SKIPLIST | 使用跳躍表實現的有序集合對象 | 不滿足上述條件,可在配置中修改 |
5.Redis 常用命令
5.1 String 對象類型常用操作
// set get
127.0.0.1:6379> set test 123
OK
127.0.0.1:6379> get test
"123"
// 取值並賦值 getset key value
127.0.0.1:6379> getset test 321
"123"
127.0.0.1:6379> get test
"321"
// 設置獲取多個鍵值 mset key value [key value...] mget key [key...]
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> mget k1 k2
1) "v1"
2) "v2"
// 刪除 del key
127.0.0.1:6379> del test
(integer) 1
// 數值遞增 incr key
127.0.0.1:6379> set num 1
OK
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> incr num
(integer) 3
127.0.0.1:6379> incr num
(integer) 4
// 增加指定的整數 incrby key increment
127.0.0.1:6379> incrby num 2
(integer) 8
127.0.0.1:6379> incrby num 2
(integer) 10
// 遞減數值 decr key
127.0.0.1:6379> decr num
(integer) 9
127.0.0.1:6379> decr num
(integer) 8
// 減少指定的數值 decryby key decrement
127.0.0.1:6379> decrby num 2
(integer) 6
127.0.0.1:6379> decrby num 2
(integer) 4
// 向尾部追加值 APPEND的作用是向鍵值的末尾追加value。如果鍵不存在則將該鍵的值設置爲value,即相當於 SET key value。返回值是追加後字符串的總長度。 語法:append key value
127.0.0.1:6379> set str hello
OK
127.0.0.1:6379> append str "world"
(integer) 10
127.0.0.1:6379> get str
"helloworld"
// 獲取字符串長度 STRLEN命令返回鍵值的長度,如果鍵不存在則返回0。 語法:strlen key
127.0.0.1:6379> strlen str
(integer) 10
5.2 List 對象類型常用操作
Arraylist是使用數組來存儲數據,特點:查詢快、增刪慢
Linkedlist是使用雙向鏈表存儲數據,特點:增刪快、查詢慢,但是查詢鏈表兩端的數據也很快。
Redis的list是採用來鏈表來存儲的,所以對於redis的list數據類型的操作,是操作list的兩端數據來操作的。
添加元素
// 向列表左邊增加元素 語法:lpush key value [value...]
127.0.0.1:6379> lpush list:1 1 2 3
(integer) 3
// 按照順序 左側增加 結果爲 3 2 1
// 向列表右邊增加元素 語法:rpush key value [value...]
127.0.0.1:6379> rpush list:1 4 5 6
(integer) 6
// 按照順序 右側增加 結果爲 3 2 1 4 5 6
查看列表
# 查看列表 LRANGE命令是列表類型最常用的命令之一,獲取列表中的某一片段,將返回start、stop之間的所有元素(包含兩端的元素),索引從0開始。
# 索引可以是負數,如:“-1”代表最後邊的一個元素。 語法:lrange key start stop
127.0.0.1:6379> lrange list:1 0 2
1) "3"
2) "2"
3) "1"
127.0.0.1:6379> lrange list:1 0 -1
1) "3"
2) "2"
3) "1"
4) "4"
5) "5"
6) "6"
彈出&移除元素
// 從列表兩端彈出元素 LPOP命令從列表左邊彈出一個元素,會分兩步完成:
// 第一步是將列表左邊的元素從列表中移除
// 第二步是返回被移除的元素值。
// 語法: lpop key
127.0.0.1:6379> lpop list:1
"3"
// 語法:rpop key
127.0.0.1:6379> rpop list:1
"6"
// 獲取列表中元素的個數 語法:llen key
127.0.0.1:6379> llen list:1
(integer) 4
// 刪除列表中指定的值 LREM命令會刪除列表中前count個值爲value的元素,返回實際刪除的元素個數。根據count值的不同,該命令的執行方式會有所不同:
// 當count>0時, LREM會從列表左邊開始刪除。
// 當count<0時, LREM會從列表後邊開始刪除。
// 當count=0時, LREM刪除所有值爲value的元素。
// 語法:lrem key count value
127.0.0.1:6379> lrem list:1 1 1
(integer) 1
// 獲得指定索引的元素值 語法:lindex key index
127.0.0.1:6379> lindex list:1 2
"4"
// 設置指定索引的元素值 語法:lset key index value
127.0.0.1:6379> lset list:1 2 2
OK
其他場景
# 只保留列表指定片段 指定範圍和 lrange 一致 語法:ltrim key start stop
127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "2"
4) "5"
127.0.0.1:6379> ltrim list:1 0 2
OK
127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "2"
# 向列表中插入元素 該命令首先會在列表中從左到右查找值爲pivot的元素,
# 然後根據第二個參數是BEFORE還是AFTER來決定將value插入到該元素的前面還是後面。
# 語法:linsert key before | after pivot value
127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "2"
127.0.0.1:6379> linsert list:1 after 1 9
(integer) 4
127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "9"
4) "2"
# 將元素從一個列表轉移到另一個列表 語法:rpoplpush source destination
127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "9"
4) "2"
127.0.0.1:6379> rpoplpush list:1 newlist
"2"
127.0.0.1:6379> lrange newlist 0 -1
1) "2"
127.0.0.1:6379> lrange list:1 0 -1
1) "2"
2) "1"
3) "9"
5.3 Hash 對象類型常用操作
hash叫散列類型,它提供了字段和字段值的映射。字段值只能是字符串類型,不支持散列類型、集合類型等其它類型。如下:
賦值 HSET命令不區分插入和更新操作,當執行插入操作時HSET命令返回1,當執行更新操作時返回0。
// 一次只設置一個字段值 語法:hset key field value
127.0.0.1:6379> hset user username zhangsan
(integer) 1
// 一次設置多個字段值 語法:hmset key field value [field value...]
127.0.0.1:6379> hmset user age 20 username lisi
OK
// 當字段不存在時賦值,類似hset,區別在於如果字段存在,該命令不執行任何操作。 語法:hsetnx key field value
127.0.0.1:6379> hsetnx user age 30
(integer) 0
取值
// 一次獲取一個字段值 語法:hget key field
127.0.0.1:6379> hget user username
"lisi"
// 一次可以獲取多個字段值 語法:hmget key field [field...]
127.0.0.1:6379> hmget user age username
1) "20"
2) "lisi"
// 獲取所有字段值 語法:hgetall key
127.0.0.1:6379> hgetall user
1) "username"
2) "lisi"
3) "age"
4) "20"
刪除
# 刪除一個或多個字段,返回值是被刪除的字段的個數。 語法:hdel key field [field...]
127.0.0.1:6379> hdel user age
(integer) 1
127.0.0.1:6379> hdel user age username
(integer) 1
其他場景
// 增加數字 語法:hincrby key field increment
127.0.0.1:6379> hincrby user age 2
(integer) 2
// 判斷字段是否存在 語法:hexists key field
127.0.0.1:6379> hexists user age
(integer) 1
// 只獲取字段名或字段值 語法: hkeys key
127.0.0.1:6379> hkeys user
1) "age"
// hvals key
127.0.0.1:6379> hvals user
1) "2"
// 獲取字段數量 語法:hlen key
127.0.0.1:6379> hlen user
(integer) 1
// 獲取當前 key 所有信息 語法: hgetall key
127.0.0.1:6379> hgetall items:1001
1) "id"
2) "3"
3) "name"
4) "apple"
5) "price"
6) "5.00"
5.4 Set 對象類型常用操作
集合類型:無序、不可重複 列表類型:有序、可重複
// 增加元素 語法:sadd key member [member...]
127.0.0.1:6379> sadd set a b c
(integer) 3
127.0.0.1:6379> sadd set a
(integer) 0
// 刪除元素
127.0.0.1:6379> srem set c
(integer) 1
// 獲得集合中的所有元素 語法:smembers key
127.0.0.1:6379> smembers set
1) "b"
2) "a"
// 判斷元素是否在集合中 語法:sismember key member
127.0.0.1:6379> sismember set a
(integer) 1
127.0.0.1:6379> sismember set h
(integer) 0
集合運算
集合的差集運算 A-B 屬於 A 並且 不屬於 B 的元素構成的集合
// 語法:sdiff key [key...]
127.0.0.1:6379> sadd setA 1 2 3
(integer) 3
127.0.0.1:6379> sadd setB 2 3 4
(integer) 3
127.0.0.1:6379> sdiff setA setB
1) "1"
127.0.0.1:6379> sdiff setB setA
1) "4"
集合的交集運算 屬於A且屬於B的元素構成的集合
// 語法:sinter key [key...]
127.0.0.1:6379> sinter setA setB
1) "2"
2) "3"
集合的並集運算 屬於 A 或者 屬於 B 的元素構成的集合
// 語法:sunion key [key...]
127.0.0.1:6379> sunion setA setB
1) "1"
2) "2"
3) "3"
4) "4"
獲得集合中元素的個數 語法:scard key
127.0.0.1:6379> smembers setA
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> scard setA
(integer) 3
從集合中彈出一個元素 注意:由於集合是無序的,所有spop命令會從集合中隨機選擇一個元素彈出。 語法:spop key
127.0.0.1:6379> spop setA
"2"
5.5 ZSet 對象類型常用操作
Sortedset 又叫 zset Sortedset 是有序集合,可排序的,但是唯一。 Sortedset 和 set 的不同之處,會給 set 中元素添加一個分數,然後通過這個分數進行排序。
// 增加元素
// 向有序集合中加入一個元素和該元素的分數,如果該元素已經存在則會用新的分數替換原有的分數。返回值是新加入到集合中的元素個數,不包含之前已經存在的元素。 語法:zadd key score member [score member...]
127.0.0.1:6379> zadd scoreboard 80 zhangsan 89 lisi 94 wangwu
(integer) 3
127.0.0.1:6379> zadd scoreboard 97 lisi
(integer) 0
// 獲取元素分數 語法:zscore key member
127.0.0.1:6379> zscore scoreboard lisi
"97"
// 刪除元素
// 移除有序集key中的一個或多個成員,不存在的成員將被忽略。 當key存在但不是有序集類型時,返回一個錯誤。
// 語法:zrem key member [member...]
127.0.0.1:6379> zrem scoreboard lisi
(integer) 1
獲得排名在某個範圍的元素列表
// 按照元素分數從小到大的順序返回索引從start到stop之間的所有元素(包含兩端的元素) 語法:zrange key start stop [withscores]
127.0.0.1:6379> zrange scoreboard 0 2
1) "zhangsan"
2) "wangwu"
// 按照元素分數從大到小的順序返回索引從start到stop之間的所有元素(包含兩端的元素) 語法:zrevrange key start stop [withscores]
127.0.0.1:6379> zrevrange scoreboard 0 2
1) "wangwu"
2) "zhangsan"
// 如果需要獲得元素的分數可以在命令末尾加上 withscores 參數
27.0.0.1:6379> zrevrange scoreboard 0 2 withscores
"wangwu"
"94"
"zhangsan"
"80"
獲取元素的排名
// 從小到大 語法:zrank key member
127.0.0.1:6379> zrank scoreboard zhangsan
(integer) 0
// 從大到小 語法:zrevrank key member
127.0.0.1:6379> zrevrank scoreboard zhangsan
(integer) 1
獲得指定分數範圍的元素
// 語法:zrangebyscore key min max [withscores][limit offset count]
127.0.0.1:6379> ZRANGEBYSCORE scoreboard 90 97 WITHSCORES
1) "wangwu"
2) "94"
3) "lisi"
4) "97"
127.0.0.1:6379> ZRANGEBYSCORE scoreboard 70 100 limit 1 2
1) "wangwu"
2) "lisi"
增加某個元素的分數
// 返回值是更改後的分數 語法:zincrby key increment member
127.0.0.1:6379> ZINCRBY scoreboard 4 lisi
"101“
獲得集合中元素的數量
// 語法:zcard key
127.0.0.1:6379> zcard scoreboard
(integer) 3
// 獲得指定分數範圍內的元素個數 語法:zcount key min max
127.0.0.1:6379> zcount scoreboard 80 90
(integer) 1
刪除元素
// 按照排名範圍刪除元素 語法:zremrangebyrank key start stop
127.0.0.1:6379> zremrangebyrank scoreboard 0 1
(integer) 2
127.0.0.1:6379> zrange scoreboard 0 -1
1) "wangwu"
// 按照分數範圍刪除元素 語法:zremrangebyscore key min max
127.0.0.1:6379> zadd scoreboard 84 zhangsan
(integer) 1
127.0.0.1:6379> ZREMRANGEBYSCORE scoreboard 80 100
(integer) 1
應用:商品銷售排行榜
需求:根據商品銷售量對商品進行排行顯示 思路:定義商品銷售排行榜(sorted set集合),Key爲items:sellsort,分數爲商品銷售量。
// 寫入商品銷售量:
// 商品編號1001的銷量是9,商品編號1002的銷量是10
192.168.101.3:7007> ZADD items:sellsort 9 1001 10 1002
// 商品編號1001的銷量加1
192.168.101.3:7001> ZINCRBY items:sellsort 1 1001
// 商品銷量前10名:
192.168.101.3:7001> ZRANGE items:sellsort 0 9 withscores
5.6 其他常用命令
// keys 返回滿足給定pattern 的所有key
127.0.0.1:6379> keys mylist*
1)"mylist"
2)"mylist5"
3)"mylist6"
4)"mylist7"
5)"mylist8"
// exists 確認一個key 是否存在
// 示例:從結果來看,數據庫中不存在HongWan 這個key,但是age 這個key 是存在的 redis
127.0.0.1:6379> exists HongWan
1)(integer) 0
redis 127.0.0.1:6379> exists age
1)(integer) 1
//del 刪除一個key
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> del hello
(integer) 1
127.0.0.1:6379> del hello
(integer) 0
127.0.0.1:6379>
// rename 重命名key
127.0.0.1:6379> set age 18
OK
127.0.0.1:6379> get age
"18"
127.0.0.1:6379> rename age age_new
OK
127.0.0.1:6379> get age_new
"18"
127.0.0.1:6379> get age
(nil)
127.0.0.1:6379>
// type 返回值的類型
127.0.0.1:6379> type age_new
string
127.0.0.1:6379> sadd set11 1 2 3
(integer) 3
127.0.0.1:6379> type set11
set
設置 key 的生存時間
Redis在實際使用過程中更多的用作緩存,然而緩存的數據一般都是需要設置生存時間的,即:到期後數據銷燬。
命令 | 作用 |
---|---|
EXPIRE key seconds | 設置key的生存時間(單位:秒)key在多少秒後會自動刪除 |
TTL key | 查看key剩餘的生存時間 |
PERSIST key | 清除生存時間 |
PEXPIRE key milliseconds | 生存時間設置單位爲:毫秒 |
// 設置test的值爲1
192.168.101.3:7002> set test 1
OK
// 獲取test的值
192.168.101.3:7002> get test
"1"
// 設置test的生存時間爲5秒
192.168.101.3:7002> EXPIRE test 5
(integer) 1
// 查看test的生於生成時間還有1秒刪除
192.168.101.3:7002> TTL test
(integer) 1
192.168.101.3:7002> TTL test
(integer) -2
// 獲取test的值,已經刪除
192.168.101.3:7002> get test
(nil)