Redis開發學習(2)_In-memory database跟On Disk(Relational) database比較_cli的基礎20大指令(資料型態介紹)


傳統的B/S 架構中


由於Server端餘後端進行資料存取過程會導致磁碟操作負載
那就有可能客戶端會反應系統更新處理資料變慢的可能
尤其當資料數達一定量後也會時常發生
以往可能處理方式會再多買幾台Server擴充硬碟等等

那在軟體上的問題解決方式則會有如下兩種
其基本核心思想都是在於避免直接對DB進行存取訪問

(1)網頁靜態化(對於網站、網頁應用)
這塊由於沒有很深入
大概意思應該是說
在進行資料庫訪問之前就先透過其他的process先把DB中的資料抓出來再生出靜態網頁
當客戶端要訪問這些資料時 Server就不再是直接去操作DB
而是去把應靜態化頁面展示出來
https://kknews.cc/zh-tw/other/5m8a5ql.html
https://www.youtube.com/watch?v=UxbiRCA6IBk


(2)將資料保存到記憶體中(常見的In-memory DB: MemoryCached , Redis)
而當客戶端需要資料更新處理時對於Server訪問後
Server會先去memory中判斷是否有該用戶要的資料若沒有才進行DB的I/O










基礎的cli指令

接下來我們要示範的是
基礎的cli指令

各位我們在上一次的範例透過C#嵌入StackExchanged.Redis
的小專案有新增一個key
這次我們要進行一個實驗
來讓你更加對In-memory這個詞有深刻體悟

這次我們將key替換成name
並透過API設置 value 為 Wang


你會發現在自開的cli  terminal中也同步更新了目前資料庫的key list




cli的基礎20大指令
(備註:對於指令部分是大小寫都可以的喔!!!
差別在於有些模糊字串比對的pattern會區分大小寫
輸入到一半打TAB會自動補齊 是很好用技巧
此外1在 redis cli command中大部分代表成功 反之就是0)

指令1. KEYS pattern   取出鍵名清單

查看目前存於記憶體中所有key
Redis指令如果想要查看目前的鍵值
可以在你啟動完cli後
輸入: keys *
會列出存於記憶體中所有key


你可以看到新增的name也呈現出來了



指令2. SELECT INDEX 切換資料庫


在Redis底層C語言中的定義是由struct中來定義資料庫的
C程式中定義在 redis.h 中就有定義到redis server這個結構
當中則有訂了一個redisDb的Array  (從index為0開始)
在用戶端則是定義了redisDb的指標指向當前用戶使用的DB
預設當Server初始化時Client端會設置為0


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
struct redisServer {  //Server  
    // ...
    redisDb *db;    // DB array
    int dbnum;    // db count
    // ...
}

typedef struct client { //Client
    // ...
    redisDb *db;    // the pointer to point current db 
    // ...
}

比方說我目前是在Index為0的 DB中列出鍵值
當我切成Index 為 1的時候
就會發現此時我們在次想列出所有鍵值時結果就不同了
目前Index為 1的 Redis DB不存在任何鍵值


此外跟剛剛不一樣的是多出中括號1的識別
這是因為每個redis用戶端都會有自己專屬的Target DB
每當用戶端執行完DB讀寫命令時, Target DB就會是目前的這些指令操作目標物件

那這個INDEX難不成沒有上限嗎???
我們實驗看看SELECT 999
會報錯的!!!  事實上Redis資料庫編號索引是從0到15(上限到15)
我們可以任選一個DB來進行利用






指令3.  SET KEY VALUE

如下我再多加如下幾個key-value
fruitA : apple
fruitA : Almond
fruitA : avocado
fruitB : banana
fruitB : Berry

在指令1中學到的keys pattern
keys * 是 for all列出目前鍵值
那 PATTERN 除了我們剛剛講的 *號之外
也有模糊搜尋的機制(是有大小寫區分的)


指令4. DEL key     刪除key


比方說我要刪除key1  (剛剛透過C#那裏應用程式塞入的測試record)
當執行完換行顯示1就代表成功0是失敗



指令5. GET KEY   獲取key對應的value

比方我要抓出fruitA 的value

這時你會發現一開始對於key 是 fruitA的我們其實設置了三種水果
fruitA : apple
fruitA : Almond
fruitA : avocado
最後被avocado覆蓋掉了

因此同樣的key一次只可以存在唯一一筆 value
當對相同key的再次set value的時候就會覆寫(在剛剛埋一個伏筆)

指令6. EXISTS  key 當前key是否存在

比方說我想要查找是否存在name這個鍵值(成功一樣回傳1)
在刪除目前的鍵值  name
再查檢一次就會返回0

指令7. TYPE key
檢查目前建值的data type

由於目前剩下來的key
fruitA , fruitB都是字串
我再多塞幾筆不同型態的key
那你可以發現原來key  還能負數 浮點數 甚至0

這時我們想打type去驗證的時候卻發現很詭異的事情
全部都是string!!!!!!

那如果你是打不存在的key則會回傳none


這是為何呢?
原因在於Redis的String 可包括任何數據
而且String的資料型態是屬於Binary-safe的
所以也可以存圖片或序列化後的物件

那幹嘛還要type這個指令???竟然回傳回來都是string

這部分主要是因為在Redis中定義的不同資料型態
跟以往我們程式語言中認知不太一樣
在Redis中若你是使用 SET 、 SETBIT、SETEX 、SETNX、MSET、....等等
Redis Strings Command 所操作的鍵值預設都會是String

Redis對於資料型態有區分的是如下幾種(超級重要的特徵!!!)
(1) String 
(2) Hash (command前綴會有H)
(3) list (command前綴會有L、B、R的)
(4) set (command前綴大部分會有S  除了set、setbit、setnx、setex)
(5) sorted set (command前綴會有Z)
(技巧:
String跟Hash的通常只要你下完後的command回傳會是OK,至於list , set ...回傳則是數字)


如下我們簡單示範一下(初心者不要把type搞成是辨別float 、int....了喔!!!!)

我們先小抄前一下
跟大家介紹一下LPUSH

他也是一種key-value只是可以讓你存一個list
不用擔心資料會像一開始介紹的用SET會覆蓋掉
而且是有順序的(通常塞入的回傳值到最後會相反過來->有點像堆疊)
塞入a 回傳1(a的index:0)
塞入b 回傳2(在a的上面-> b的index:0 a的index:1 )
塞入c 回傳3(在b的上面-> c的index:0 b的index:1 a的index:2)
塞入d 回傳4(在c的上面-> d的index:0 c的index:1 b的index:2 a的index:3))

透過LRANGE指令還可以打印特定範圍




這時我們在去透過  TYPE  指令去驗證
就會發現被指令判定為   list型態


指令8. RENAME key newkey
重新命名  key



這裡來進行一個實驗
由於在剛剛我們有建立一個list型態的key-value record
如果我把 fruitB 這個string型態的key重新命名的名稱
剛好故意跟listOfAlphabet撞名會發生捨麼事情呢???

list的key就被蓋掉了  原本list型態的listOfAlphabet也不存在了
所以在重命名時也要注意這點


指令9. DBSIZE  查看目前DB中key的總數量


指令10. MOVE key db 將目前資料庫中某一key移動至其他資料庫



我們目前有兩個DB各自塞的key如下

我們用MOVE 從Db0  中把key為listOfAlphabet的record移動到Db1


指令11. INFO 獲取Redis Server資訊(OS/CPU/MEMORY...)和統計內容


完整訊息(有點長...)


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
# Server
redis_version:3.2.100
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:dd26f1f93c5130ee
redis_mode:standalone
os:Windows
arch_bits:64
multiplexing_api:WinSock_IOCP
process_id:13680
run_id:43b59fef0b1954bb1fd20168f6e8b94b29b617ca
tcp_port:6379
uptime_in_seconds:19529
uptime_in_days:0
hz:10
lru_clock:10972020
executable:D:\JobTools\RedisTool\Redis-x64-3.2.100\redis-server.exe
config_file:

# Clients
connected_clients:1
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0

# Memory
used_memory:690784
used_memory_human:674.59K
used_memory_rss:653008
used_memory_rss_human:637.70K
used_memory_peak:804656
used_memory_peak_human:785.80K
total_system_memory:0
total_system_memory_human:0B
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:0.95
mem_allocator:jemalloc-3.6.0

# Persistence
loading:0
rdb_changes_since_last_save:7
rdb_bgsave_in_progress:0
rdb_last_save_time:1554472314
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok

# Stats
total_connections_received:5
total_commands_processed:156
instantaneous_ops_per_sec:0
total_net_input_bytes:4903
total_net_output_bytes:5887018
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
evicted_keys:0
keyspace_hits:13
keyspace_misses:6
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:3114
migrate_cached_sockets:0

# Replication
role:master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

# CPU
used_cpu_sys:0.28
used_cpu_user:0.47
used_cpu_sys_children:0.00
used_cpu_user_children:0.00

# Cluster
cluster_enabled:0

# Keyspace
db0:keys=5,expires=0,avg_ttl=0
db1:keys=3,expires=0,avg_ttl=0


指令12. RANDOMKEY   隨機回傳key集合中任一key

每一次回傳都會有不一樣的key


指令13. INCR KEY    對鍵值相應的value進行加1計數


比方我現在建立一個key 叫做order 要用來計數的





指令14. INCRBY KEY  increment  對鍵值相應的value進行加特定整數的運算

如果不想固定都只加1則可透過INCRBY



指令15. DECR KEY    對鍵值相應的value進行減1計數





指令16. DECRBY KEY  decrement  對鍵值相應的value進行減特定整數的運算




指令17. STRLEN key
獲取特定key相應value的字串長




指令18. APPEND key value

對特定key相應value字串串接(於尾部)





指令19. MSET key value [key value…]

同時(一行)設定多個key value



在此會發現key集合的順序是不固定的而且
每當有新的record進入就隨機更新

指令20. MGET key [key…]

同時(一行)獲取多個key value








Reference:
Redis Tutorial
https://www.tutorialspoint.com/redis/redis_commands.htm

Redis - Data Types
https://www.tutorialspoint.com/redis/redis_data_types.htm

[Redis]-常用語法速查表
https://dotblogs.com.tw/colinlin/2017/06/26/180604

redis的數據類型講解相關命令
https://kknews.cc/zh-tw/other/kn3o9z8.html

MOVE:将当前数据库中的key移动到另外的数据库中
http://www.maiziedu.com/wiki/redis/key6/

数据库键空间
http://redisbook.com/preview/database/key_space.html

取得 Redis 中指定 key 條件的筆數
https://blog.yowko.com/redis-key-count/

頁面靜態化:
https://www.youtube.com/channel/UCqclmvmcwdKmQdAFEzZCbIQ/search?query=%E9%A1%B5%E9%9D%A2%E9%9D%99%E6%80%81%E5%8C%96

redis源码解读(九):redisDB
http://czrzchao.com/redisSourceDB


留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header