寫在前面,感謝狂神莲镣,下面所有的都是來自狂神說Java - B站UP主
redis學(xué)習(xí)
Redis 是一個開源的摆碉,內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)存儲系統(tǒng)雳旅,它可以用作數(shù)據(jù)庫、緩存和消息中間件MQ舷胜。它支持字符串涕蚤、散列地来、列表卵酪、集合幌蚊、有序集合與范圍查詢,bitmaps溃卡、hyperloglogs和地理空間(geospatial)索引半徑查詢溢豆。Redis內(nèi)置了復(fù)制(replication),LUA腳本瘸羡,lURU驅(qū)動時間漩仙,事物和不通級別的磁盤持久化,并通過Redis哨兵和自動分區(qū)提供高可用性犹赖。
基本命令
# 連接命令
redis-cli -p 6379
# 看是否連接成功
127.0.0.1:6379> ping
PONG
# 清空數(shù)據(jù)庫
127.0.0.1:6379> flushall
OK
# 設(shè)置keys
127.0.0.1:6379> set name shd
OK
# 查看當(dāng)前有哪些key
127.0.0.1:6379> keys *
1) "name"
# 查看key是否存在 1是存在 0 是不存在
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> EXISTS age
(integer) 0
# 設(shè)置key的過期時間 expire key sec
127.0.0.1:6379> expire name 10
(integer) 1
# 查看當(dāng)前key的過期時間 ttl
127.0.0.1:6379> ttl name
(integer) 4
127.0.0.1:6379> ttl name
(integer) 2
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> ttl name
(integer) -2
# 根據(jù)key 獲取value
127.0.0.1:6379> get name
(nil)
# 查看key的類型
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> type name
string
#
五大數(shù)據(jù)類型
String
127.0.0.1:6379> get key1
"v1"
127.0.0.1:6379> append key1 hello # 追加队他, 如果不存在則新增一個 set key value
(integer) 7
127.0.0.1:6379> get key1
"v1hello"
127.0.0.1:6379> strlen key1 # 獲取key的長度
(integer) 7
=================================================================
# 自增和自減 incr 自增 decr 自減
127.0.0.1:6379> set age 1
OK
127.0.0.1:6379> incr age
(integer) 2
127.0.0.1:6379> incr age
(integer) 3
127.0.0.1:6379> decr age
(integer) 2
127.0.0.1:6379> decr age
(integer) 1
127.0.0.1:6379> decr age
(integer) 0
127.0.0.1:6379> decr age
(integer) -1
127.0.0.1:6379> decr age
(integer) -2
127.0.0.1:6379> decr age
(integer) -3
# 步長式增加或減少 incrby step decrby step
127.0.0.1:6379> INCRBY age 100
(integer) 97
127.0.0.1:6379> incrby age 100
(integer) 197
127.0.0.1:6379> decrby age 50
(integer) 147
127.0.0.1:6379> decrby age 50
(integer) 97
=====================================================
# 截取
127.0.0.1:6379> set name shd # 設(shè)置name的值
OK
127.0.0.1:6379> get name # 獲取key
"shd"
127.0.0.1:6379> getrange name 1 2 # 截取1到2,閉區(qū)間
"hd"
127.0.0.1:6379> getrange name 1 1
"h"
127.0.0.1:6379> getrange name 0 -1 # 獲取所有的
"shd"
#######################################
# 按下標(biāo) 截取字符串
127.0.0.1:6379> set key1 abcdefgh
OK
127.0.0.1:6379> get key1
"abcdefgh"
127.0.0.1:6379> setrange key1 1 xxx # 從下標(biāo)1更改為xxx
(integer) 8
127.0.0.1:6379> get key1
"axxxefgh"
127.0.0.1:6379>
################################################
# setex 設(shè)置過期時間
127.0.0.1:6379> setex name 30 ddd
OK
127.0.0.1:6379> get name
"ddd"
127.0.0.1:6379> ttl name
(integer) 23
# setnx 不存在在設(shè)置 -- 分布式鎖中會用到
127.0.0.1:6379> set name shd # 首先設(shè)置name 為shd
OK
127.0.0.1:6379> setnx name myj # 通過setnx 設(shè)置name 為myj
(integer) 0 # 設(shè)置失敗
127.0.0.1:6379> setnx bb myj # 設(shè)置bb 為myj
(integer) 1 #設(shè)置成功
127.0.0.1:6379> get bb
"myj"
################################################
# 批量設(shè)置 mset 批量
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> keys *
1) "k3"
2) "k2"
3) "k1"
# 批量獲取
127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"
# setnx 批量設(shè)置為原子操作
127.0.0.1:6379> msetnx k1 v1 k4 v4 # 因為k1存在了冷尉,所有k4設(shè)置失敗了
(integer) 0
#######################################################
# 存入對象
127.0.0.1:6379> set user:1 "{name:zhangsan, age:10}"
OK
127.0.0.1:6379> get user:1
"{name:zhangsan, age:10}"
# 批量存放對象 漱挎, 設(shè)計的key為關(guān)鍵
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 10
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "10"
#######################################################
# 先get在set
127.0.0.1:6379> keys * # 目前沒有一個key
(empty array)
127.0.0.1:6379> getset name shd # 先獲取name在設(shè)置name為shd
(nil) # 因為不存在系枪,所以為nil
127.0.0.1:6379> getset name myj # 在來一次雀哨,設(shè)置name為myj
"shd" # 獲取到了之前設(shè)置的shd
String 類型使用場景:value 除了是字符串,還可以是數(shù)字
- 計數(shù)器 incr
- 統(tǒng)計多單位的數(shù)量
- 粉絲數(shù) uid:988123:follow 0
- 對象緩存存儲
List
基本數(shù)據(jù)類型私爷,列表
所有的list命令都是l開頭的
##########################################
127.0.0.1:6379> lpush l one # 將一個元素放入頭部
(integer) 1
127.0.0.1:6379> lpush l two
(integer) 2
127.0.0.1:6379> lpush l three
(integer) 3
127.0.0.1:6379> lrange l 1 -1 # 獲取第2個到最后一個元素
1) "two"
2) "one"
127.0.0.1:6379> lrange l 0 -1 # 獲取第1個到最后一個元素
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> rpush l four # 將一個元素放入尾部
(integer) 4
127.0.0.1:6379> lrange l 0 -1 # 通過區(qū)間獲取列表的值
1) "three"
2) "two"
3) "one"
4) "four"
##########################################
# 移除元素
127.0.0.1:6379> lrange l 0 -1
1) "three"
2) "two"
3) "one"
4) "four"
127.0.0.1:6379> lpop l # 移除第一個元素
"three"
127.0.0.1:6379> rpop l # 移除最后一個元素
"four"
##########################################
# 根據(jù)下標(biāo)獲取元素
127.0.0.1:6379> lrange l 0 -1
1) "foure"
2) "three"
3) "two"
4) "one"
127.0.0.1:6379> lindex l 0 # 獲取第0位元素
"foure"
## 返回列表的長度
127.0.0.1:6379> llen l
(integer) 4
##########################################
# 移除指定的值
127.0.0.1:6379> lrange l 0 -1
1) "three"
2) "three"
3) "three"
4) "five"
5) "foure"
6) "two"
7) "one"
127.0.0.1:6379> lrem l 2 three # 移除指定數(shù)量的具體元素
(integer) 2
127.0.0.1:6379> lrange l 0 -1
1) "three"
2) "five"
3) "foure"
4) "two"
5) "one"
##########################################
# 截斷
127.0.0.1:6379> lrange l 0 -1
1) "python"
2) "vue"
3) "world"
4) "hello"
127.0.0.1:6379> ltrim l 1 2 # 通過下標(biāo)截取1到2的元素
OK
127.0.0.1:6379> lrange l 0 -1
1) "vue"
2) "world"
##########################################
# rpoplpush 移除最后一個元素到另一個元素
127.0.0.1:6379> lrange l1 0 -1
1) "c"
2) "b"
3) "a"
127.0.0.1:6379> RPOPLPUSH l1 l2 # 把l1最后一個元素移動到l2中
"a"
127.0.0.1:6379> lrange l1 0 -1
1) "c"
2) "b"
127.0.0.1:6379> lrange l2 0 -1
1) "a"
########################################
# exists 查看列表是否存在
# lset 把已存在的元素通過下標(biāo)更新為另一個元素
127.0.0.1:6379> exists l
(integer) 0
127.0.0.1:6379> lset l 0 name #如果不存在雾棺,則報錯
(error) ERR no such key
127.0.0.1:6379> lpush l age
(integer) 1
127.0.0.1:6379> lset l 0 name
OK
127.0.0.1:6379> lindex l 0
"name"
########################################
# 插入值
127.0.0.1:6379> lindex l 0
"name"
127.0.0.1:6379> LINSERT l before name your # name前面插入一個值
(integer) 2
127.0.0.1:6379> lrange l 0 -1
1) "your"
2) "name"
127.0.0.1:6379> linsert l after name is # name后面插入一個值
(integer) 3
127.0.0.1:6379> lrange l 0 -1
1) "name"
2) "your"
3) "name"
4) "is"
127.0.0.1:6379> linsert l before name my # 如果有兩個相同的元素,在name前插入衬浑,會優(yōu)先插入下標(biāo)最小的那個
(integer) 5
127.0.0.1:6379> lrange l 0 -1
1) "my"
2) "name"
3) "your"
4) "name"
5) "is"
它實際上是一個鏈表捌浩,before node after, left工秩,right都可以插值
如果key不存在尸饺,創(chuàng)建新的鏈表
如果key存在,新增內(nèi)容
如果移除了所有值助币,空鏈表浪听,也代表不存在
在兩邊插入或改動值,效率最高眉菱,中間元素迹栓,相對來說效率較低
-
消息排隊,消息隊列 lpush rpop俭缓, 棧 lpush lpop
Set(集合)
set中的值是不可以重復(fù)的
######################################### 127.0.0.1:6379> sadd s name # 新增元素 (integer) 1 127.0.0.1:6379> sadd s age (integer) 1 127.0.0.1:6379> smembers s # 獲取所有成員 1) "age" 2) "name" 127.0.0.1:6379> sismember s age # 判斷元素是否存在 (integer) 1 127.0.0.1:6379> sismember s sex (integer) 0 ######################################### 127.0.0.1:6379> scard s # 獲取元素個數(shù) (integer) 2 127.0.0.1:6379> srem s age # 移除指定的元素 (integer) 1 127.0.0.1:6379> srem s sex (integer) 0 127.0.0.1:6379> smembers s 1) "name" 127.0.0.1:6379> smembers s # 獲取所有的元素 1) "age" 2) "name" 3) "address" 4) "sex" 127.0.0.1:6379> spop s # 隨機(jī)移除一個元素 "address" 127.0.0.1:6379> smembers s 1) "age" 2) "name" 3) "sex" ######################################### 127.0.0.1:6379> SRANDMEMBER s 1 # 隨機(jī)抽選隨機(jī)個數(shù)的元素 srandmember 1) "sex" 127.0.0.1:6379> SRANDMEMBER s 1 1) "name" 127.0.0.1:6379> SRANDMEMBER s 1 1) "age" 127.0.0.1:6379> SRANDMEMBER s 1 1) "age" ######################################### 127.0.0.1:6379> sadd s one (integer) 1 127.0.0.1:6379> sadd s two (integer) 1 127.0.0.1:6379> sadd s three (integer) 1 127.0.0.1:6379> sadd s1 aaa (integer) 1 127.0.0.1:6379> smove s s1 one # 把s中的one 移到s1中 (integer) 1 127.0.0.1:6379> smembers s 1) "two" 2) "three" 127.0.0.1:6379> smembers s1 1) "one" 2) "aaa" ######################################### 127.0.0.1:6379> sadd s c (integer) 1 127.0.0.1:6379> sadd e c (integer) 1 127.0.0.1:6379> sadd e d (integer) 1 127.0.0.1:6379> sadd e f (integer) 1 127.0.0.1:6379> sdiff s e # 差集 1) "a" 2) "b" 127.0.0.1:6379> sinter s e # 交集 共同好友 1) "c" 127.0.0.1:6379> sunion s e # 并集 1) "a" 2) "c" 3) "f" 4) "b" 5) "d"
微博克伊,a用戶將所有關(guān)注的人放一個set集合酥郭,將他的粉絲也放到一個集合中!
Hash
Map集合
#################################################################################### # 注意hmset 批量設(shè)置多個key value 在redis4.0 被廢棄 127.0.0.1:6379> hset my age 10 name shd sex man # 設(shè)置多個key 和value (integer) 3 127.0.0.1:6379> hget my age # 根據(jù)指定key 獲取 value "10" 127.0.0.1:6379> hmget my age name sex # 根據(jù)多個filed 獲取value 1) "10" 2) "shd" 3) "man" 127.0.0.1:6379> hgetall my # 根據(jù)key獲取所有的 filed 和value 1) "age" 2) "10" 3) "name" 4) "shd" 5) "sex" 6) "man" #################################################################################### 127.0.0.1:6379> hdel my name # 刪除指定的field (integer) 1 127.0.0.1:6379> hgetall my 1) "age" 2) "10" 3) "sex" 4) "man" #################################################################################### 127.0.0.1:6379> hlen my # 獲取hash的長度 (integer) 2 #################################################################################### 127.0.0.1:6379> hgetall my 1) "age" 2) "10" 3) "sex" 4) "man" 127.0.0.1:6379> hexists my name # 判斷 field 是否存在 (integer) 0 127.0.0.1:6379> hexists my age (integer) 1 #################################################################################### 127.0.0.1:6379> hkeys my # 獲取所有的fields 1) "age" 2) "sex" 127.0.0.1:6379> hvals my # 獲取所有的values 1) "10" 2) "man" #################################################################################### 127.0.0.1:6379> HINCRBY my age -1 # 指定增量 (integer) 9 127.0.0.1:6379> HINCRBY my age -1 (integer) 8 127.0.0.1:6379> HINCRBY my age -1 (integer) 7 127.0.0.1:6379> HINCRBY my age -1 (integer) 6 127.0.0.1:6379> hset my age 10 (integer) 1 127.0.0.1:6379> hsetnx my age 100 (integer) 0 127.0.0.1:6379> hsetnx my name shd # 不存在就創(chuàng)建 (integer) 1
hash變更的數(shù)據(jù)user name 愿吹,age不从,尤其是用戶信息類的,經(jīng)常變動的信息洗搂!hash更適合與對象的存儲消返,string更適合自字符串的存儲
Zset
在set的基礎(chǔ)上,增加了一個值耘拇,set k1 v1 zset v1 score v1
#################################### 127.0.0.1:6379> zadd myset 1 one # 添加一個元素 (integer) 1 127.0.0.1:6379> zadd myset 1 one 2 two 3 three 4 four # 添加多個元素 (integer) 3 127.0.0.1:6379> zrange myset 0 -1 1) "one" 2) "two" 3) "three" 4) "four" #################################### # 排序 127.0.0.1:6379> zadd user 1000 zhangsan (integer) 1 127.0.0.1:6379> zadd user 800 wangwu (integer) 1 127.0.0.1:6379> zadd user 1500 zhaosi (integer) 1 127.0.0.1:6379> zrangebyscore user -inf +inf # 負(fù)無窮到 正無窮 排序 1) "wangwu" 2) "zhangsan" 3) "zhaosi" 127.0.0.1:6379> ZRANGEBYSCORE user -inf +inf # 升序 1) "one" 2) "two" 3) "three" 4) "foure" 5) "five" 127.0.0.1:6379> ZREVRANGE user 0 -1 # 降序 1) "five" 2) "foure" 3) "three" 4) "two" 5) "one" 127.0.0.1:6379> zrangebyscore user 0 800 # 0 到800 的升序排列 1) "wangwu" ################################################# 127.0.0.1:6379> zrem user wangwu # 移除元素 (integer) 1 127.0.0.1:6379> zcard user # 獲取集合中的個數(shù) (integer) 2 ################################################# 127.0.0.1:6379> ZREVRANGE user 0 -1 1) "five" 2) "foure" 3) "three" 4) "two" 5) "one" 127.0.0.1:6379> 127.0.0.1:6379> 127.0.0.1:6379> zcount user 2 3 # 獲取區(qū)間的個數(shù) (integer) 2 127.0.0.1:6379> zcount user 2 4 # 獲取區(qū)間的個數(shù) (integer) 3
案例思路:
set排序撵颊,存儲班級成績表 工資排序標(biāo)
普通消息 1 重要消息 2 帶權(quán)重進(jìn)行判斷
排行榜應(yīng)用
三種特殊類型
Geospatial (地理位置)
朋友的定位,附近的人 惫叛, 打車距離計算
############################################################
# geoadd
# 兩極無法直接添加
127.0.0.1:6379> geoadd china:city 116.397128 39.916527 beijing # 添加一個城市的經(jīng)緯度
(integer) 1
127.0.0.1:6379> geoadd china:city 121.48941 31.40527 chongqing
(integer) 1
127.0.0.1:6379> geoadd china:city 113.6401 34.72468 zhengzhou 108.93425 34.23053 xian # 添加多個城市的經(jīng)緯度
(integer) 2
############################################################
# geopos 獲取指定城市的經(jīng)緯度
127.0.0.1:6379> GEOPOS china:city beijing # 獲取一個城市的
1) 1) "116.39712899923324585"
2) "39.91652647362980844"
127.0.0.1:6379> GEOPOS china:city beijing zhengzhou # 獲取多個城市的
1) 1) "116.39712899923324585"
2) "39.91652647362980844"
2) 1) "113.64010244607925415"
2) "34.72467993544626808"
############################################################
# 獲取兩人的距離
單位
m 表示米
km 表示千米
mi 表示英里
ft 表示英尺
# 獲取兩個城市的距離
127.0.0.1:6379> geodist china:city beijing zhengzhou km # 千米
"626.7593"
############################################################
# 獲取附件的人
127.0.0.1:6379> georadius china:city 116 39 1000 km # 獲取中心為經(jīng)度116 維度 39 1000千米的所有城市
1) "zhengzhou"
2) "beijing"
3) "chongqing"
4) "xian"
127.0.0.1:6379> georadius china:city 116 39 1000 km withdist # 獲取中心為經(jīng)度116維度391000千米的所有城市和距離
1) 1) "zhengzhou"
2) "519.7813"
2) 1) "beijing"
2) "107.4949"
3) 1) "chongqing"
2) "980.5655"
4) 1) "xian"
2) "823.7398"
127.0.0.1:6379> georadius china:city 116 39 1000 km withcoord # 獲取中心為經(jīng)度116維度391000千米的所有城市和經(jīng)緯度
1) 1) "zhengzhou"
2) 1) "113.64010244607925415"
2) "34.72467993544626808"
2) 1) "beijing"
2) 1) "116.39712899923324585"
2) "39.91652647362980844"
3) 1) "chongqing"
2) 1) "121.48941010236740112"
2) "31.40526993848380499"
4) 1) "xian"
2) 1) "108.93425256013870239"
2) "34.23053097599082406"
127.0.0.1:6379> georadius china:city 116 39 1000 km count 2 # 獲取指定數(shù)量的城市
1) "beijing"
2) "zhengzhou"
##################################################
# 找出指定元素周圍的元素
127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km withcoord
1) 1) "zhengzhou"
2) 1) "113.64010244607925415"
2) "34.72467993544626808"
2) 1) "beijing"
2) 1) "116.39712899923324585"
2) "39.91652647362980844"
3) 1) "xian"
2) 1) "108.93425256013870239"
2) "34.23053097599082406"
127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km withdist
1) 1) "zhengzhou"
2) "626.7593"
2) 1) "beijing"
2) "0.0000"
3) 1) "xian"
2) "915.0863"
geo底層的實現(xiàn)原理其實就是zset倡勇,可以使用zset的命令操作geo
Hyperloglog 基數(shù)統(tǒng)計
hyperlogolog優(yōu)勢:
占用內(nèi)存是固定,2^64不通的元素的技術(shù)嘉涌,只需要廢12KB的內(nèi)存
什么是基數(shù)妻熊?
A {1,3仑最,5扔役,7,8警医,7}
B{1亿胸,3,5预皇,7侈玄, 8}
基數(shù)(不重復(fù)元素的個數(shù)) = 5,可以接受誤差
網(wǎng)頁的UV (1個人訪問一個網(wǎng)站多次吟温,但是還算做一個人)
傳統(tǒng)的方式序仙,set保存用戶的id,然后就可以統(tǒng)計set中的元素來判斷
這個方式如果保存了大量的用戶id就會比較麻煩鲁豪。我們目的是為了計數(shù)潘悼,而不是保存用戶id
##########################################
127.0.0.1:6379> pfadd k1 a b c d # 新增元素
(integer) 1
127.0.0.1:6379> pfadd k2 d e f j k
(integer) 1
127.0.0.1:6379> pfmerge k3 k1 k2 # 合并元素到另一個元素中
OK
127.0.0.1:6379> pfcount k3 # 獲取元素個數(shù)
(integer) 8
Bitmaps
位存儲
統(tǒng)計疫情感染人數(shù)
統(tǒng)計用戶信息,活躍爬橡,不活躍 登錄 和未登錄治唤, 365打卡。兩種狀態(tài)的都可以使用bitmaps
bitmaps 位圖堤尾,數(shù)據(jù)結(jié)構(gòu)肝劲! 都是操作二進(jìn)制位來記錄,就只有0和1
##########################################################
# 統(tǒng)計一周內(nèi)打卡的天數(shù)
# 首先是設(shè)置每周的打開狀態(tài) 0 到6 表示 周一到周末
127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 1 0
(integer) 0
127.0.0.1:6379> setbit sign 2 1
(integer) 0
127.0.0.1:6379> setbit sign 3 1
(integer) 0
127.0.0.1:6379> setbit sign 4 1
(integer) 0
127.0.0.1:6379> setbit sign 5 1
(integer) 0
127.0.0.1:6379> setbit sign 6 1
(integer) 0
## 查看某天是否打卡
127.0.0.1:6379> getbit sign 3 # 查看周四是否打卡
(integer) 1
## 查看一周是否全部打卡
127.0.0.1:6379> bitcount sign
(integer) 6