(二)Redis數據類型,事務和Jedis操作Redis

注:筆記整理來源 B站UP主狂神說Java

Redis五大基本類型

官方文檔:Redis 是一個開源(BSD許可)的,內存中的數據結構存儲系統,它可以用作數據庫、緩存和消息中間件。
它支持多種類型的數據結構,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets),
有序集合(sorted sets) 與範圍查詢, bitmaps, hyperloglogs 和 地理空間(geospatial)
索引半徑查詢。 Redis 內置了 複製(replication),LUA腳本(Lua scripting), LRU驅動事件(LRU
eviction),事務(transactions) 和不同級別的 磁盤持久化(persistence), 並通過
Redis哨兵(Sentinel)和自動 分區(Cluster)提供高可用性(high availability)。 String(字符串)

String

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> set key1 v1    設置值
OK
127.0.0.1:6379> get key1          獲取值
"v1"
127.0.0.1:6379> keys *          獲取所有的key
1) "key1"
127.0.0.1:6379> exists key1          判斷一個key是否存在
(integer) 1
127.0.0.1:6379> append key1 "hello"     追加字符串,若key不存在,相當於set key
(integer) 7
127.0.0.1:6379> get kye1
(nil)
127.0.0.1:6379> strlen key1    獲取key的長度
(integer) 7
127.0.0.1:6379> append key1 ",kuangshen"
(integer) 17
127.0.0.1:6379> strlen key1
(integer) 17
127.0.0.1:6379> get key1
"v1hello,kuangshen"

127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views  自動增長
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> get views
"2"
127.0.0.1:6379> decr views  自動遞減
(integer) 1
127.0.0.1:6379> get views
"1"
127.0.0.1:6379> incrby views 10  以步長爲10進行增長
(integer) 11
127.0.0.1:6379> get views
"11"
127.0.0.1:6379> decrby views 8  以步長爲8進行遞減
(integer) 3
127.0.0.1:6379> get views
"3"

127.0.0.1:6379> set key1 "hello,fly"
OK
127.0.0.1:6379> get key1
"hello,fly"
127.0.0.1:6379> getrange key1 0 4   字符串截取
"hello"
127.0.0.1:6379> getrange key1 0 -1
"hello,fly"

127.0.0.1:6379> setex key3 30 "hello"   設置過期時間
OK
127.0.0.1:6379> ttl key3
(integer) 26
127.0.0.1:6379> get key3
(nil)
127.0.0.1:6379> ttl key3
(integer) -2

127.0.0.1:6379> setnx mykey redis   mykey不存在,設置成功
(integer) 1                    設置成功返回1,失敗返回0
127.0.0.1:6379> keys *
1) "key2"
2) "key1"
3) "mykey"
127.0.0.1:6379> setnx mykey mongodb  mykey存在,設置失敗
(integer) 0
127.0.0.1:6379> get mykey
"redis"

127.0.0.1:6379> mset key1 v1 key2 v2 key3 v3    設置多個值
OK
127.0.0.1:6379> keys *
1) "key2"
2) "key1"
3) "key3"
127.0.0.1:6379> mget key1 key2 key3   獲取多個值
1) "v1"
2) "v2"
3) "v3"
msetnx key1 v1 key4 v4
(integer) 0

127.0.0.1:6379> getset db redis          如果不存在,則返回nil
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db mongodb     如果存在,先返回當前的值,再將其設置爲新值
"redis"
127.0.0.1:6379> get db
"mongodb"

與CAS結構是相通的

拓展:
-----------
對象:
set user:1{name:zhangsan,age:3} 設置一個user:1 對象 值爲json字符串來保存一個對象
這裏的key是一個巧妙的設計: user:{id}:{filed} 如此設計在redis是完全ok的

127.0.0.1:6379> mset user:1:name zhangsan user:1:age 17
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "17"

String類似的使用場景:
value除了是字符串,也可以是數字
-計數器
-統計多單位的數量{uid:9282329:follow 0} 可以inc uid:9282329:follow
-----------

List (基本的數據類型)

在redis裏,可以將redis 玩成,棧,隊列,阻塞隊列等.所有的list命令都是 l開頭的


LPUSH RPUSH

127.0.0.1:6379> lpush list one   將一個值或多個值,插入列表頭部
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lrange list 0 1
1) "three"
2) "two"
127.0.0.1:6379> rpush list 1    將一個或多個值放入列表的尾部
(integer) 7
127.0.0.1:6379> rpush list 2
(integer) 8
127.0.0.1:6379> rpush list 3
(integer) 9
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "1"
5) "2"
6) "3"

LPOP RPOP

127.0.0.1:6379> rpop list  從後面移除一個
"3"
127.0.0.1:6379> lpop list  從前面移除一個
"three"

Lindex

127.0.0.1:6379> lindex list 1   獲取index位置的值
"one"

Llen

127.0.0.1:6379> Llen list
(integer) 7

移除指定的值:Lrem

127.0.0.1:6379> lrem list 1 one   移除 1個 "one"
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "3"
3) "2"
4) "1"
5) "1"
6) "2"

ltrim  修剪:list

 127.0.0.1:6379> lpush mylist hello1
(integer) 1
127.0.0.1:6379> lpush mylist hello2
(integer) 2
127.0.0.1:6379> lpush mylist hello3
(integer) 3
127.0.0.1:6379> ltrim mylist 1 2
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello2"
2) "hello1"

rpoplpush 移除列表的最後一個元素並將其移動到新的列表中

127.0.0.1:6379> lrange mylist 0 -1
1) "hello2"
2) "hello1"
127.0.0.1:6379> rpoplpush mylist myotherlist
"hello1"
127.0.0.1:6379> lrange mylist 0 -1
1) "hello2"
127.0.0.1:6379> lrange myotherlist 0 -1
1) "hello1"

LSET 指定下標更新值

127.0.0.1:6379> lset mylist 0 "hello3"
OK

linsert 往指定位置前或後面插入value值

127.0.0.1:6379> linsert mylist before(after) hello3 "other"
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "other"
2) "hello3"

小結:
list其實是一個鏈表,before Node after, left ,right都可以插入值
如果key不存在,則創建新的鏈表
key存在,新增內容
如果移除了key,爲空鏈表,則不存在
在兩邊插入,或者改動值,效率最高! 操作中間元素效率偏低
消息排隊!消息隊列(Lpush Rpop) 棧(Lpush lpop)

Set(集合)

set中的值不能重複

Sadd ,Smember , SisMember

127.0.0.1:6379> sadd myset "hello"   set集合添加元素
(integer) 1
127.0.0.1:6379> sadd myset "fly"
(integer) 1
127.0.0.1:6379> sadd myset "love fly"
(integer) 1
127.0.0.1:6379> SMEMBERS myset     查看指定set的所有值
1) "love fly"
2) "hello"
3) "fly"
127.0.0.1:6379> SISMEMBER myset hi     查看set是否包含該元素,有返回1 ,沒有返回0
(integer) 0
127.0.0.1:6379> SISMEMBER myset hello
(integer) 1

Scard

127.0.0.1:6379> scard myset    獲取set集合的中的個數
(integer) 3

Srem

127.0.0.1:6379> srem myset hello  移除set的元素
(integer) 1

Set無序,不重複集合,抽隨機

127.0.0.1:6379> SRANDMEMBER myset    隨機抽出一個元素
"love fly"
127.0.0.1:6379> SRANDMEMBER myset
"love fly"
127.0.0.1:6379> SRANDMEMBER myset
"love fly"
127.0.0.1:6379> SRANDMEMBER myset
"love fly"
127.0.0.1:6379> SRANDMEMBER myset
"fly"
127.0.0.1:6379> SRANDMEMBER myset 2   隨機抽出指定個數的元素
1) "love fly"
2) "fly"

Spop 刪除指定的key,隨即刪除key!

 127.0.0.1:6379> SPOP myset    隨機刪除set集合中的一些元素
"fly"

Smove  將一個指定的值移動到另一個集合中

127.0.0.1:6379> smove myset newset fly   如果沒有目標集合,會刪除第一個集合的元素,不會創建目標集合
(integer) 0
127.0.0.1:6379> SMEMBERS newset
(empty array)
127.0.0.1:6379> SMEMBERS myset
1) "love fly"

Set集合場景:
微博,B站,共同關注(交集)
微博:A用戶將所有關注的人放在一個set集合中!將粉絲也放在集合中
A用戶和B用戶的共同關注,共同愛好,二度好友(推薦好友)
數字集合類:
差集

127.0.0.1:6379> sadd key a
(integer) 1
127.0.0.1:6379> sadd key b
(integer) 1
127.0.0.1:6379> sadd key c
(integer) 1
127.0.0.1:6379> sadd key1 d
(integer) 1
127.0.0.1:6379> sadd key1 c
(integer) 1
127.0.0.1:6379> sadd key1 e
(integer) 1
127.0.0.1:6379> SDIFF key key1   求差集
1) "b"
2) "a"
    -交集
127.0.0.1:6379> SINTER key key1  求交集
1) "c"
    -並集
127.0.0.1:6379> SUNION key key1
1) "b"
2) "c"
3) "d"
4) "a"
5) "e"

Hash(哈希,Map集合)

存儲的是key - map !  value值爲map集合
Hash本質和String 沒有太大區別,還是一個key-value.只不過value值爲 map(key-value)!

127.0.0.1:6379> hset myhash field fly   設置key-map值
(integer) 1
127.0.0.1:6379> hget myhash field   獲取key-map值
"fly"
127.0.0.1:6379> hmset myhash field fly field hello 設置多個key-map值,重複設置會覆蓋掉
OK
127.0.0.1:6379> hget myhash field 
"hello"
127.0.0.1:6379> hmget myhash field field1 獲取多個key-map值
1) "fly"
2) "hello"
127.0.0.1:6379> hgetall myhash  獲取所有值
1) "field"     field-fly  屬於一個key-value 
2) "fly"
3) "field1"
4) "hello"
127.0.0.1:6379> hdel myhash field1   刪除指定的一個value值
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field"
2) "fly"
127.0.0.1:6379> hmset myhash field1 1 field2 2
OK
127.0.0.1:6379> hlen myhash      獲取長度
(integer) 3
127.0.0.1:6379> hexists myhash field    判斷字段是否存
(integer) 1
127.0.0.1:6379> hkeys myhash  只獲取key值
1) "field"
2) "field1"
3) "field2"
127.0.0.1:6379> hvals myhash  只獲取value值
1) "fly"
2) "1"
3) "2"
127.0.0.1:6379> hincrby myhash field1 10 以指定步長增長 
(integer) 11
127.0.0.1:6379> hincrby myhash field1 -1 以指定步長減少(值爲負值,就是遞減) 
(integer) 10
127.0.0.1:6379> hgetall myhash
1) "field"
2) "fly"
3) "field1"
4) "11"
5) "field2"
6) "2"
127.0.0.1:6379> hsetnx myhash field f  如果存在,則設置失敗,不存在則創建(分佈式鎖:成功version+1)
(integer) 0

hash存儲變更的數據:
user name age,尤其是用戶信息的保存,經常變動的信息
hash更適合對象的存儲,String更適合字符串存儲

Zset(有序集合:Sort Set)

在set的基礎上增加了一個值,set k1 v1 zset k1 score1 v1

添加值 zadd key score(根據score排序) value

127.0.0.1:6379> zadd myset 1 one
(integer) 1
127.0.0.1:6379> zadd myset 2 two 3 three
(integer) 2
127.0.0.1:6379> zrange myset 0 -1
1) "one"
2) "two"
3) "three"

排序 ZrangeByScore key min(最小值) max(最大值) withsocres(顯示socre)

127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf withscores  從小到大排序
1) "gou"
2) "2000"
3) "fly"
4) "2500"
5) "lei"
6) "2600"

Zrevrange key start stop 從大到小排序

127.0.0.1:6379> zrevrange salary 0 -1
1) "lei"
2) "gou"

移除元素 Zrem

127.0.0.1:6379> zrem salary fly
(integer) 1
查看元素個數 Zcard
127.0.0.1:6379> zcard salary
(integer) 2

查詢score在指定區間的數量 Zcount key min max

127.0.0.1:6379> zcount salary 0 2700
(integer) 2

應用場景:

如果工作中需要,可以查詢官方文檔!
*********************
set排序,可以存儲班級成績表,工資表排序,
普通消息(1),重要消息(2)
排行榜應用,TOP N測試
*********************

三種特殊數據類型

geospatial (地圖,地理位置)

朋友的定位,附近的人,打車距離實現
redis的Geo  可以推算地理位置的信息(兩地之間的距離,方圓幾裏的人)
可以查詢一些測試數據
主要有6個命令:

GEOADD(添加地理位置) geoadd key longitude(經度) latitude(緯度) member
規則:地球兩級(南北極)沒辦法添加,一般會下載城市數據,通過java程序讀取文件導入
參數:key(經度,緯度,名稱)
有效的經度 -85.05到85.05
有效的緯度 -180到 180

127.0.0.1:6379> geoadd china:city 116.40 39.30 beijing
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.32 shanghai
(integer) 1
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing
(integer) 1
127.0.0.1:6379> geoadd china:city 114.08 22.54 shenzhen
(integer) 1
127.0.0.1:6379> geoadd china:city 120.15 30.28 hangzhou
(integer) 1
127.0.0.1:6379> geoadd china:city 108.94 34.26 xian
(integer) 1

GEODIST(Geo distince:獲取給定兩個位置之間的距離)
單位: 
-m 單位米
-km 單位千米
-mi 單位英里
-ft 單位千尺

127.0.0.1:6379> geodist china:city beijing shanghai   北京到上海的直線距離 m
"1008342.6601"
127.0.0.1:6379> geodist china:city beijing shanghai km   北京到上海的直線距離 km
"1008.3427"
127.0.0.1:6379> geodist china:city beijing chongqing km  北京到重慶的距離 km
"1414.4224"

GEOHASH(返回一個或者多個位置的GeoHash表示)

127.0.0.1:6379> GEOHASH china:city beijing
1) "wwfz8drghe0"       代表當前城市經緯度的字符串11位的hash,如果兩個字符串越接近,那麼距離就越近
    GEOPOS(獲取指定地理位置的經度和緯度)
127.0.0.1:6379> geopos china:city xian
1) 1) "108.93999785184860229"
2) "34.25999964418929977"
127.0.0.1:6379> geopos china:city beijing
1) 1) "116.39999896287918091"
2) "39.30000117660147652"
127.0.0.1:6379> geopos china:city chongqing
1) 1) "106.49999767541885376"
2) "29.52999957900659211"
127.0.0.1:6379> geopos china:city shenzhen
1) 1) "114.08000081777572632"
2) "22.53999903789756587"
127.0.0.1:6379> geopos china:city hangzhou
1) 1) "120.15000075101852417"
2) "30.2800007575645509"
127.0.0.1:6379> 

GEORADIUS(以給定的經緯度爲中心,找出某一半徑內的元素)
微信找好友 附近的人?(獲取附近的人的地址,定位) 通過半徑來查詢!

127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km 以110 30爲中心,半徑1000km內的
1) "chongqing"
2) "shenzhen"
3) "hangzhou"
獲取指定數量的人 200人
127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km withcoord withdist count 1 獲取1人
1) 1) "chongqing"
2) "341.9374"
3) 1) "106.49999767541885376"
2) "29.52999957900659211"

所有的數據都應錄入 china:city中,纔會使結果更加精確

GEORADIUSBYMEMBER(找出指定範圍內的元素,中心點由給定的位置元素決定) 城市間的定位(導航)

127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km
1) "beijing"
2) "xian"
127.0.0.1:6379> GEORADIUSBYMEMBER china:city shanghai 400 km
1) "hangzhou"
2) "shanghai"

GEO底層的實現原理就是Zset!
127.0.0.1:6379> type china:city
zset
就可以使用Zset命令來操作Geo

127.0.0.1:6379> zrange china:city 0 -1   查看地圖全部元素
1) "chongqing"
2) "xian"
3) "shenzhen"
4) "hangzhou"
5) "shanghai"
6) "beijing"
127.0.0.1:6379> zrem china:city shenzhen  刪除指定地圖元素
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqing"
2) "xian"
3) "hangzhou"
4) "shanghai"
5) "beijing"

**

hyperloglog

什麼是基數?
A{1,3,5,7,5,9}
B{1,3,5,7,8}
基數(不重複的元素) = 5 簡介 redis2.8.9版本就更新了Hyperloglog數據結構! Redis Hyperloglog 基數統計的算法!
優點:佔用的內存是固定的 2^64不同元素非技術,只需要12KB內存.從內存角度出發,hyperloglog爲首選 網頁的UV(Uniqe
Visitor:獨立訪客數 一個人訪問一個網站多次,還是算作一個人)

傳統的方式:set 保存用戶的id,然後統計set中的元素數量作爲標準判斷
這個方式如果保存大量的用戶id,佔用內存過多,就會很麻煩!目的是爲了計數,而不是保存id
0.81%的錯誤率! 統計UV的任務是可以忽略不計

測試使用

127.0.0.1:6379> pfadd mykey a b c d e f g h i j  創建第一組元素集
(integer) 1
127.0.0.1:6379> pfcount mykey  統計第一組元素基數數量
(integer) 10
127.0.0.1:6379> pfadd mykey2 i j z x c v b n m
(integer) 1
127.0.0.1:6379> pfcount mykey2
(integer) 9
127.0.0.1:6379> PFMERGE mykey3 mykey2 mykey 合併兩組 mykey + mykey2 ->mykey3 
OK
127.0.0.1:6379> pfcount mykey3
(integer) 15

應用場景

進行頁面統計
如果允許容錯,一定可以使用Hyperloglog
不允許容錯,就是用set或者自己的數據類型即可!

bitmap(位圖)

位存儲:都是操作二進制位來進行記錄,非0即1 統計疫情感染人數: 0 0 0 0 0 1 1 0 (1爲感染者) 統計用戶信息,
活躍人數或者不活躍人數. 
登錄或者未登錄 學生365打卡. 365天=365bit 1字節=8bit 46個字節就可以存儲(節省內存)
只要是有兩個狀態的,都可以使用bitmap(位圖)

使用bitmaps記錄週一到週日的打卡  setbit key offest value
週一:1 週二:1 週三:0 …

127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 1 1
(integer) 0
127.0.0.1:6379> setbit sign 2 0
(integer) 0
127.0.0.1:6379> setbit sign 3 0
(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

查看某一天是否有打卡 getbit key offest

127.0.0.1:6379> getbit sign 1
(integer) 1
127.0.0.1:6379> getbit sign 3
(integer) 0
統計打卡的天數     bitcount key [start end]
127.0.0.1:6379> bitcount sign 0 6
(integer) 5

Redis事務操作

什麼是事務:一組命令一起執行的集合.
一個事務中的所有命令都會被序列化,在事務執行的時候,按照順序執行!一次性,順序性.排他性
---------------隊列 set set set 執行----------------

要麼同時成功,要麼同時失敗,原子性
redis事務不保證原子性!!!
redis單條命令是保證原子性的!!!
redis事務沒有隔離級別概念!(不會出現幻讀,髒讀,不可重複讀...)
所有的命令在事務中,並沒有直接被執行!只有發起執行命令時,纔會執行!

redis的事務:
-開啓事務(multi)
-命令入隊()
-執行事務(exec)

正常執行事務:

127.0.0.1:6379> multi  開啓事務
OK
127.0.0.1:6379> set key1 v1
QUEUED
127.0.0.1:6379> set key2 v2
QUEUED
127.0.0.1:6379> set key3 v3
QUEUED
127.0.0.1:6379> get key2
QUEUED
127.0.0.1:6379> get key1
QUEUED
127.0.0.1:6379> exec   執行事務
1) OK
2) OK
3) OK
4) "v2"
5) "v1"
127.0.0.1:6379> multi  開啓事務
OK
127.0.0.1:6379> set key1 v1
QUEUED
127.0.0.1:6379> set key2 v2
QUEUED
127.0.0.1:6379> set key4 v4
QUEUED
127.0.0.1:6379> DISCARD  取消事務
OK
127.0.0.1:6379> get key4 事務隊列中的命令不會被執行
(nil)

編譯異常(redis命令有誤):事務中所有的命令都不會被執行

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> getset k3 v3
QUEUED
127.0.0.1:6379> getset k4
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379> set k5 v5
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get v5   所有的命令都不會被執行
(nil) 

運行時異常(語法有誤):事務存在語法問題,在執行的時候其他命令可以正常執行,
錯誤命令拋異常(所以無原子性)

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k2 "v2"
QUEUED
127.0.0.1:6379> incr k2
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) ERR value is not an integer or out of range

鎖:Redis可以實現樂觀鎖, watch 監控!
悲觀鎖:很悲觀,認爲什麼時候都會出問題,無論做什麼都會加鎖!影響性能
樂觀鎖:很樂觀,認爲什麼時候都不會出問題,所以不會加鎖!在更新數據的時候判斷,在此期間是否有人修改過數據
1.獲取version
2.更新的時候比較version

Redis的監視測試  一旦事務執行成功,監控就會取消 
正常執行成功: 單線程

127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money  監視money對象
OK
127.0.0.1:6379> multi  事務正常結束,數據期間沒有發生變動
OK
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
127.0.0.1:6379> exec
1) (integer) 80
2) (integer) 20
127.0.0.1:6379> mget money out
1) "80"
2) "20"

多線程:多個客戶端操作

127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 10
QUEUED
127.0.0.1:6379> incrby out 10
QUEUED
//線程2進來修改了money
127.0.0.1:6379> get money
"80"
127.0.0.1:6379> set money 1000
OK
127.0.0.1:6379> exec  提交事務發現meney被修改了,就會失敗
(nil)

//事務執行失敗需要先解鎖,在獲取最新的值
127.0.0.1:6379> unwatch  1.發現事務執行失敗,先解鎖
OK
127.0.0.1:6379> watch money 2.獲取最新的值,再次監視,select version
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 80
QUEUED
127.0.0.1:6379> incrby out 80
QUEUED
127.0.0.1:6379> exec   3.每次執行前,都要比對監視的值有沒有發生變化
1) (integer) 920
2) (integer) 100

使用watch可以當做redis的樂觀鎖操作!

Jedis操作redis

使用java操作redis
什麼是jedis ? 
是官方推薦的java連接開發工具! 使用java操作redis

第一步:

<dependencies
<!-- 導入jedis的包-->>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>3.2.0</version>
    </dependency>

    <!--導入fastjson -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.62</version>
    </dependency>
</dependencies>

2.編碼測試:
 -連接數據庫
 -操作命令
 -斷開連接

public class TestPing {
    public static void main(String[] args) {
        //1.創建一個Jedis對象
        Jedis jedis = new Jedis("127.0.0.1",6379);
        //Jedis的所有命令都是之前學習redis的命令
        //操作String hash set ZSet list geo hyperloglog bitmap
        System.out.println(jedis.ping());

    }
}

java對五大數據類型操作常用的API

操作redis-keys

Jedis jedis = new Jedis("127.0.0.1", 6379);

System.out.println("清空數據:"+jedis.flushDB());
System.out.println("判斷某個值是否存在:"+jedis.exists("username"));
System.out.println("新增<username , fly>的鍵值對:"+jedis.set("username","fly"));
System.out.println("新增<password , 123>的鍵值對:"+jedis.set("password","123"));
System.out.print("系統的所有鍵如下:");
Set<String> keys = jedis.keys("*");
System.out.println("所有鍵:"+keys);
System.out.println("刪除鍵password:"+jedis.del("password"));
System.out.println("判斷鍵password是否存在:"+jedis.exists("password"));
System.out.println("查看username所存儲的值類型:"+jedis.type("username"));
System.out.println("隨機返回key空間的一個值:"+jedis.randomKey());
System.out.println("重命名key:"+jedis.rename("username","name"));
System.out.println("取出值:"+jedis.get("name"));
System.out.println("按索引查詢:"+jedis.select(0));
System.out.println("刪除當前數據庫所有key值:"+jedis.flushDB());
System.out.println("返回當前數據庫key值數目:"+jedis.dbSize());
System.out.println("刪除所有數據庫的key值:"+jedis.flushAll());

Sring:

Jedis jedis = new Jedis("127.0.0.1", 6379);

jedis.flushDB();
System.out.println("----增加數據----");
System.out.println(jedis.set("key1","value1"));
System.out.println(jedis.set("key2","value2"));
System.out.println(jedis.set("key3","value3"));
System.out.println("刪除key2:"+jedis.del("key2"));
System.out.println("獲取key2:"+jedis.get("key2"));
System.out.println("修改key1的值:"+jedis.set("key1","afterV1"));
System.out.println("獲取key1的值:"+jedis.get("key1"));
System.out.println("在key3後面加入值:"+jedis.append("key3",",hello"));
System.out.println("key3的值:"+jedis.get("key3"));
System.out.println("增加多個key-value值:"+jedis.mset("k1","v1","k2","v2","k3","v3"));
System.out.println("獲取多個key-value值:"+jedis.mget("k1","key1","k2","k3"));
System.out.println("刪除多個值:"+jedis.del("k1","k2"));
System.out.println("獲取多個值:"+jedis.mget("username","name","k3"));

jedis.flushDB();
System.out.println("----新增值防止覆蓋----");
System.out.println(jedis.setnx("key1","value1"));
System.out.println(jedis.setnx("key2","value2"));
System.out.println(jedis.setnx("key2","value2-new"));
System.out.println(jedis.get("key1"));
System.out.println(jedis.get("key2"));

System.out.println("---新增值並設置有效時間---");
System.out.println(jedis.setex("key3",10,"倒計時"));
System.out.println(jedis.get("key3"));
try {
    Thread.sleep(10000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
System.out.println(jedis.get("key3"));

System.out.println("---獲取原值,更新爲新值---");
System.out.println(jedis.getSet("key1", "newkey1"));
System.out.println(jedis.get("key1"));

System.out.println("獲取key2的字符串:"+jedis.getrange("key2",2,4));
System.out.println("刪除所有數據庫的key值:"+jedis.flushAll());

List:

Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.flushDB();
System.out.println("添加list元素:"+jedis.lpush("Collection","List","Map","Vector"));
System.out.println("添加list元素:"+jedis.lpush("Collection","HashMap"));
System.out.println("添加list元素:"+jedis.lpush("Collection","TreeSet"));
System.out.println("Collection的內容(全部):"+jedis.lrange("Collection",0,-1));
System.out.println("Collection的內容[0,3]:"+jedis.lrange("Collection",0,3));
System.out.println("-----刪除列表指定的值-----");
System.out.println("刪除指定元素個數:"+jedis.lrem("Collection",2,"HashMap"));
System.out.println("刪除下表[0,3]區間內的值:"+jedis.ltrim("Collection",0,3));
System.out.println("從列表左邊出棧:"+jedis.lpop("Collection"));
System.out.println("從列表右邊添加值:"+jedis.rpush("Collection","iterator"));
System.out.println("從列表右端出棧:"+jedis.rpop("Collection"));
System.out.println("獲取指定下標的內容:"+jedis.lindex("Collection",2));
System.out.println("修改Collection下標爲1的值"+jedis.lset("Collection",1,"ArrayList"));
System.out.println("------------------------");
System.out.println("Collection的長度:"+jedis.llen("Collection"));
System.out.println("獲取Collection下標爲2的值:"+jedis.lindex("Collection",2));
System.out.println("------------------------");
System.out.println("SortList:"+jedis.lpush("sortList","3","6","1","2","7","4"));
System.out.println("sortList排序(從小到大)排序前:"+jedis.lrange("sortList",0,-1));
System.out.println("sortList排序(從小到大)排序後:"+jedis.sort("sortList"));

Set:

Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.flushDB();

System.out.println("往集合中添加元素------");
System.out.println(jedis.sadd("eleSet", "e1", "e2", "e3", "e4", "e5", "e6"));
System.out.println("Set中所有元素爲:"+jedis.smembers("eleSet"));
System.out.println("刪除一個元素e1:"+jedis.srem("eleSet","e1"));
System.out.println("Set中所有元素爲:"+jedis.smembers("eleSet"));
System.out.println("刪除2個元素e3,e4:"+jedis.srem("eleSet","e3","e4"));
System.out.println("Set中所有元素爲:"+jedis.smembers("eleSet"));
System.out.println("隨機移除集合中的一個元素:"+jedis.spop("eleSet"));
System.out.println("集合中的元素個數:"+jedis.scard("eleSet"));
System.out.println("e1是否存在集合中:"+jedis.sismember("eleSet","e1"));
System.out.println("e2是否存在集合中:"+jedis.sismember("eleSet","e2"));
System.out.println("---------------------");
System.out.println(jedis.sadd("eleSet1","e1","e2", "e3", "e4", "e5", "e6"));
System.out.println(jedis.sadd("eleSet2","e1","e0", "e9", "e6"));
System.out.println("刪除eleSet1的e2,並移動到eleSet2中:"+jedis.smove("eleSet1","eleSet2","e2"));
System.out.println("eleSet1中的元素:"+jedis.smembers("eleSet1"));
System.out.println("eleSet2中的元素:"+jedis.smembers("eleSet2"));
System.out.println("----------集合運算--------");
System.out.println("eleSet1和eleSet2額交集:"+jedis.sinter("eleSet1","eleSet2"));
System.out.println("eleSet1和eleSet2額並集:"+jedis.sunion("eleSet1","eleSet2"));
System.out.println("eleSet1和eleSet2額差集:"+jedis.sdiff("eleSet1","eleSet2"));
jedis.sinterstore("eleSet3","eleSet1","eleSet2");
System.out.println("eleSet3的值:"+jedis.smembers("eleSet3"));

Hash:

Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.flushDB();
Map<String,String> map = new HashMap<String,String>();

map.put("key1","value1");
map.put("key2","value2");
map.put("key3","value3");
map.put("key4","value4");
//添加名(key)爲hash的hash元素

jedis.hset("hash",map);
jedis.hset("hash","key5","value5");
System.out.println("hash所有鍵值對爲:"+jedis.hgetAll("hash"));
System.out.println("hash的所有鍵爲:"+jedis.hkeys("hash"));
System.out.println("hash的所有值爲:"+jedis.hvals("hash"));
System.out.println("將key66保存的值加上一個整數,如果不存則創建key6:"+jedis.hincrBy("hash","key6",1));
System.out.println("hash所有鍵值對爲:"+jedis.hgetAll("hash"));
System.out.println("刪除一個或多個鍵值對:"+jedis.hdel("hash","key1","key6"));
System.out.println("hash所有鍵值對爲:"+jedis.hgetAll("hash"));
System.out.println("hash所有鍵值對個數爲:"+jedis.hlen("hash"));
System.out.println("判斷hash是否存在key2:"+jedis.hexists("hash","key2"));
System.out.println("判斷hash是否存在key3:"+jedis.hexists("hash","key3"));
System.out.println("獲取hash中的值:"+jedis.hmget("hash","key3"));
System.out.println("獲取hash中的值:"+jedis.hmget("hash","key3","key4"));

Redi緩存配置,持久化,訂閱發佈,主從複製和緩存相關問題以及解決

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章