iT邦幫忙

2021 iThome 鐵人賽

DAY 17
0
Software Development

Redis還在學系列 第 17

Day17 Redis應用實戰-GEO/HyperLogLog/Transaction操作

  • 分享至 

  • xImage
  •  

Redis 資料型態GEO

  • 儲存地理空間資訊.

  • 可用指令

    • GEOADD
    • GEOPOS
    • GEODIST
    • GEORADIUS
    • GEORADIUSBYMEMBER
    • GEOHASH
  • 資料結構

    • GEO底層使用ZSET作為儲存結構.

GEOADD

新增member包含位置到geo.

127.0.0.1:6379> geoadd cities 121.5598 25.09108 taipei
(integer) 1

127.0.0.1:6379> geoadd cities 121.2168 24.93759 taoyuan
(integer) 1

GEOPOS

取得geo中member的位置.

127.0.0.1:6379> geopos cities taipei
1) 1) "121.55980199575424194"
   2) "25.09107928759889461"

GEODIST

取得geo中兩個member的距離.

# 預設單位為m
127.0.0.1:6379> geodist cities taipei taoyuan
"38557.7088"

# 單位為km
127.0.0.1:6379> geodist cities taipei taoyuan km
"38.5577"

# 單位為ft
127.0.0.1:6379> geodist cities taipei taoyuan ft
"126501.6694"

# 單位為mi
127.0.0.1:6379> geodist cities taipei taoyuan mi
"23.9587"

GEORADIUS

取得geo中指定位置半徑內的所有member.

127.0.0.1:6379> geoadd cities 121.5598 25.09108 taipei
(integer) 1
127.0.0.1:6379> geoadd cities 121.2168 24.93759 taoyuan
(integer) 1
127.0.0.1:6379> geoadd cities 120.666 23.01087 kaohsiung
(integer) 1
127.0.0.1:6379> geoadd cities 120.2513 23.1417 tainan
(integer) 1

# 取得cities中距離在121.52250 25.03715 半徑120 km 的member
127.0.0.1:6379> georadius cities 121.52250 25.03715 120 km
1) "taoyuan"
2) "taipei"

# 取得cities中距離在121.52250 25.03715 半徑120 km 的member並加上位置
127.0.0.1:6379> georadius cities 121.52250 25.03715 120 km withcoord
1) 1) "taoyuan"
   2) 1) "121.21680110692977905"
      2) "24.93758924779512398"
2) 1) "taipei"
   2) 1) "121.55980199575424194"
      2) "25.09107928759889461"
# 取得cities中距離在121.52250 25.03715 半徑120 km 的membe並加上距離
127.0.0.1:6379> georadius cities 121.52250 25.03715 120 km withdist
1) 1) "taoyuan"
   2) "32.7483"
2) 1) "taipei"
   2) "7.0785"
# 取得cities中距離在121.52250 25.03715 半徑120 km 的member並將提供位置hash
127.0.0.1:6379> georadius cities 121.52250 25.03715 120 km withhash
1) 1) "taoyuan"
   2) (integer) 4050139696016711
2) 1) "taipei"
   2) (integer) 4050152556288054

GEORADIUSBYMEMBER

取得geo中指定member半徑內的所有member.

127.0.0.1:6379> geoadd cities 121.5598 25.09108 taipei
(integer) 1
127.0.0.1:6379> geoadd cities 121.2168 24.93759 taoyuan
(integer) 1
127.0.0.1:6379> geoadd cities 120.666 23.01087 kaohsiung
(integer) 1
127.0.0.1:6379> geoadd cities 120.2513 23.1417 tainan
(integer) 1

# 取得cities中距離tainan 半徑120 km的member
127.0.0.1:6379> georadiusbymember cities tainan 120 km
1) "tainan"
2) "kaohsiung"

GEOHASH

取得指定member的geo hash值.

127.0.0.1:6379> geohash cities taipei
1) "wsqqwptnhs0"

Redis 資料型態HyperLogLog

  • 當作進行基數統計的演算法.

    • 優點-當輸入的元素或key很大時,計算基數所需要的空間永遠固定,而且很小,每個HyperLogLog的key只需要12kb的記憶體,就能夠計算接近2^64個不同元素的基數.
    • 缺點-只能用來計算元素的個數,不儲存元素value,所以不能回傳元素value.
  • 可用指令

    • PFADD
    • PFCOUNT
    • PFMERGE
  • 資料結構

    • GEO底層使用ZSET作為儲存結構.

PFADD

新增元素到hyperloglog中.

127.0.0.1:6379> pfadd mytest abc def ghi jkl
(integer) 1

PFCOUNT

取得目前hyperloglog中元素的個數.

127.0.0.1:6379> pfadd mytest abc def ghi jkl
(integer) 1

127.0.0.1:6379> pfcount mytest
(integer) 4

PFMERGE

合併多個hyperloglog並寫入到新的hyperloglog.

127.0.0.1:6379> pfadd mylog abc def ghi jkl
(integer) 1

127.0.0.1:6379> pfadd mylog2 mno pqr
(integer) 1

127.0.0.1:6379> pfcount mylog
(integer) 4

127.0.0.1:6379> pfcount mylog2
(integer) 2 

# 合併mylog與mylog2並寫入mylog3
127.0.0.1:6379> pfmerge mylog3 mylog mylog2
OK

127.0.0.1:6379> pfcount mylog3
(integer) 6

Redis 資料型態BloomFilter

  • 由一組很長的二進位向量所組成,其中所儲存的資料為0 or 1.主要用途在於快速判斷某個元素是否存在於集合中,可以確定一定不存在,但不能確定一定存在.

    • 優點-記憶體耗用量小,新增與查詢速度很快.
    • 缺點-隨著資料量增加,誤判率將會隨之增高,且無法刪除資料.
  • 可用指令

    • 需搭配RedisBloom或Guava模組

Redis Transaction

  • Redis伺服器可以一次執行多個操作,執行過程部會被其他操作插入執行順序.
  • 交易過程使用方式
    • 交易開始-mutli
    • 依照設計的交易順序進行操作
    • 交易結束-exec

Transaction操作

實際上就是交易開始時會把所有的操作存放到QUEUE後在交易結束時一次執行.

127.0.0.1:6379> set bankaccountA 300
OK

127.0.0.1:6379> set bankaccountB 500
OK

# 帳戶A原本有300
# 帳戶B原本有500
127.0.0.1:6379> mget bankaccountA bankaccountB
1) "300"
2) "500"

# 交易開始
127.0.0.1:6379> multi
OK

# 從帳戶B轉帳到帳戶A
127.0.0.1:6379(TX)> decrby bankaccountB 100
QUEUED

127.0.0.1:6379(TX)> incrby bankaccountA 100
QUEUED

# 交易結束
127.0.0.1:6379(TX)> exec
1) (integer) 400
2) (integer) 400

# 確認結果-成功
127.0.0.1:6379> mget bankaccountA bankaccountB
1) "400"
2) "400"

取消Transaction

  • 當開始交易後需要取消交易可以透過discard進行.
# 延續上面操作
127.0.0.1:6379> mget bankaccountA bankaccountB
1) "400"
2) "400"

127.0.0.1:6379> multi
OK

# 從帳戶B轉帳到帳戶A
127.0.0.1:6379(TX)> decrby bankaccountB 200
QUEUED

127.0.0.1:6379(TX)> incrby bankaccountA 200
QUEUED

# 取消交易
127.0.0.1:6379(TX)> discard
OK

# 確認結果-無異動
127.0.0.1:6379> mget bankaccountA bankaccountB
1) "400"
2) "400"

異常Transaction

  • 當開始交易後執行異常時會發生錯誤,只有錯誤的指令不會執行,其餘的指令還是會正常執行.
# 延續上面操作
127.0.0.1:6379> mget bankaccountA bankaccountB
1) "400"
2) "400"

127.0.0.1:6379> multi
OK

# 從帳戶B轉帳到帳戶A與C各100
127.0.0.1:6379(TX)> decrby bankaccountB 200
QUEUED

# 開啟帳戶C給予string value
127.0.0.1:6379(TX)> set bankaccountC abc
QUEUED

# 此指令會引發失敗
127.0.0.1:6379(TX)> incrby bankaccountC 100
QUEUED

127.0.0.1:6379(TX)> incrby bankaccountA 100
QUEUED

# 交易結束
127.0.0.1:6379(TX)> exec
1) (integer) 200
2) OK
3) (error) ERR value is not an integer or out of range
4) (integer) 500

# 確認結果-非預期的失敗造成結果異常
127.0.0.1:6379> mget bankaccountA bankaccountB bankaccountC
1) "500"
2) "200"
3) "abc"

失敗Transaction

  • 當開始交易後執行操作發生異常時,會取消所有的操作.
# 延續上面操作
127.0.0.1:6379> mget bankaccountA bankaccountB bankaccountC
1) "500"
2) "200"
3) "abc"

127.0.0.1:6379> multi
OK

# 從帳戶A轉帳到帳戶C與B各100
127.0.0.1:6379(TX)> decrby bankaccountA 200
QUEUED

# 操作指令錯誤,不會被放到QUEUE
127.0.0.1:6379(TX)> setstring bankaccountC def
(error) ERR unknown command `setstring`, with args beginning with: `bankaccountC`, `def`, 

127.0.0.1:6379(TX)> incrby bankaccountC 100
QUEUED

127.0.0.1:6379(TX)> incrby bankaccountB 100
QUEUED

# 交易結束
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.

# 確認結果-由上而下執行,當錯誤已發生則會取消所有操作
127.0.0.1:6379> mget bankaccountA bankaccountB bankaccountC
1) "500"
2) "200"
3) "abc"

上一篇
Day16 Redis應用實戰-SortedSet操作
下一篇
Day18 Redis架構實戰-持久化RDB
系列文
Redis還在學30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言