1. 程式人生 > 實用技巧 >navicat 連線 mysql 報1251錯誤

navicat 連線 mysql 報1251錯誤

redis五種常用的資料結構為string (字串)、list (列表)、set (集合)、hash (雜湊) 和 zset (有序集合)。小白易讀,建議收藏。

萬丈高樓平地起

reids是鍵值對結構的NoSql資料庫,key都是字串,常說的資料型別不同,說的都是value

redis所有的資料都會有一個dicEntry,眾多dicEntry組成一個連結串列。上方那個sds就是key,可以看出是一個字串。下方那個綠色的redisObject就是value。可以看出圖中給的例子就是string型別。redisObject會指向真實的資料(比如圖中的字串“world”)。後面我們說的資料型別特指value

部分。

string (字串)

Redis 的字串是動態字串,是可以修改的字串。當字串長度小於 1M 時,擴容都是加倍現有的空間,如果超過 1M,擴容時一次只會多擴 1M 的空間。一個字串最大可以承受512M。

常用指令

設定獲取值

127.0.0.1:6379> set name pjjlt
OK
127.0.0.1:6379> get name
"pjjlt"
127.0.0.1:6379> exists name
(integer) 1

設定使用set,獲取使用get,檢視某key是否存在用exists

設定過期時間

127.0.0.1:6379> setex company 10  gongsi
OK
127.0.0.1:6379> get company
"gongsi"
127.0.0.1:6379> get company
(nil)

可以在設定值的時候直接指定,keycompany可以存活10秒。此外,也可以將設定值設定過期時間分開,使用expire

127.0.0.1:6379> set company gongsi
OK
127.0.0.1:6379> expire company 10
(integer) 1
127.0.0.1:6379> get company
"gongsi"
127.0.0.1:6379> get company
(nil)

保證不覆蓋value

redis還提供了命令,在設定值的時候,如果發現key已存在,此次設定失敗,保證原始value不被覆蓋。使用setnx命令。

127.0.0.1:6379> setnx company gongsi
(integer) 1
# 可以看到第二次設定失敗,返回值為 0.
127.0.0.1:6379> setnx company haha
(integer) 0
127.0.0.1:6379> get company
"gongsi"

批量設定獲取值

127.0.0.1:6379> mset name pjjlt age 26 company gongsi
OK
127.0.0.1:6379> mget name age company
1) "pjjlt"
2) "26"
3) "gongsi"

批量設定使用mset,批量獲取使用mget。批量設定獲取,減少IO,提高效能,你值得擁有。

計數

redis還可以通過自增的方式計數。

127.0.0.1:6379> set key 10
OK
127.0.0.1:6379> incr key
(integer) 11
127.0.0.1:6379> incr key
(integer) 12
# 字串報錯
127.0.0.1:6379> set key2 haha
OK
127.0.0.1:6379> incr key2
(error) ERR value is not an integer or out of range
# 超出long的範圍
127.0.0.1:6379> set key3 9223372036854775807
OK
127.0.0.1:6379> incr key3
(error) ERR increment or decrement would overflow
# key4不存在
127.0.0.1:6379> incr key4
(integer) 1
127.0.0.1:6379> incr key4
(integer) 2

可以通過incr關鍵字自增,可以看出key自增了兩次。不能給字串自增,那樣會報錯,例如key2。不能超過long的範圍,那樣也會報錯,例如key3。如果初始key不存在,則增從0開始,例如key4。

追加值

127.0.0.1:6379> set name pj
OK
127.0.0.1:6379> append name jlt
(integer) 5
127.0.0.1:6379> get name
"pjjlt"

字串長度

127.0.0.1:6379> get name
"pjjlt"
127.0.0.1:6379> strlen name
(integer) 5

設定並返回原先值

127.0.0.1:6379> get name
"pjjlt"
127.0.0.1:6379> getset name mj
"pjjlt"
127.0.0.1:6379> get name
"mj"

設定指定位置的字元

127.0.0.1:6379> get name
"mj"
127.0.0.1:6379> setrange name 0 p
(integer) 2
127.0.0.1:6379> get name
"pj"

獲取部分字串

127.0.0.1:6379> set name pjjlt
OK
127.0.0.1:6379> getrange name 0 2
"pjj"

總結

命令 解釋
set 設定值
get 獲取值
setex 設定值並新增過期時間
setnx 保證不覆蓋value
mset 批量設定值
mget 批量獲取值
incr 計數
append 追加值
strlen 字串長度
getset 設定並返回原先值
setrange 設定指定位置的字元
getrange 獲取部分字串

內部編碼

雖然某種資料型別的value名稱是一致的,比如都是string,但是根據資料量的大小,會採用不同的內部編碼,這樣可以更高效的利用空間嘛。內部編碼型別也儲存在redisObject中。利用object encoding key可檢視內部編碼型別。

int:長整型,超越長整型或者是字串會升級。

embstr:小於等於44個位元組的字串。筆者用的是redis5.0.9,有人說這個位元組範圍是39,親測是44。查了一下,原始碼確實改了,現在是44.

raw:大於44個位元組的字串。

127.0.0.1:6379> set name 1234567890
OK
127.0.0.1:6379> object encoding name
"int"
# 這裡設定44個字元
127.0.0.1:6379> set name qwertyuiopqwertyuiopqwertyuiopqwertyuiopqwer
OK
127.0.0.1:6379> object encoding name
"embstr"
# 這裡設定45個字元
127.0.0.1:6379> set name qwertyuiopqwertyuiopqwertyuiopqwertyuiopqwert
OK
127.0.0.1:6379> object encoding name
"raw"

使用場景

可以用於計數,比如網站訪問量。
可以共享Session,比如分散式系統,多個例項驗證使用者是否登入。
可以限速,比如控制一個ip或者一個使用者一定時間內訪問次數。

list (列表)

Redis 的列表相當於 Java 語言裡面的 LinkedList,注意它是連結串列而不是陣列。這意味著list 的插入和刪除操作非常快,時間複雜度為 O(1),但是索引定位很慢,時間複雜度為O(n)。list的兩端都可以彈入彈出資料,所以可以做佇列

棧與佇列

棧如同一個死衚衕,只有一個出口,後進來的先出,先進來的後出。

127.0.0.1:6379> rpush books python java golong
(integer) 3
127.0.0.1:6379> rpop books
"golong"
127.0.0.1:6379> rpop books
"java"
127.0.0.1:6379> rpop books
"python"
127.0.0.1:6379> rpop books
(nil)

資料從右邊進(rpush),右邊出(rpop),先進去的最後出來。

佇列

佇列如同排隊打飯的同學們,先進先出。

127.0.0.1:6379> rpush books python java golong 
(integer) 3
127.0.0.1:6379> lpop books
"python"
127.0.0.1:6379> lpop books
"java"
127.0.0.1:6379> lpop books
"golong"
127.0.0.1:6379> lpop books
(nil)

資料從右邊進(rpush),左邊出(lpop),先進先出。

常用命令

向佇列任意位置加入元素

剛才演示的rpushlpush都是從兩頭加入元素,這兩個命令不再演示。還可以使用linsert在某指定元素前或後插入新的元素。

127.0.0.1:6379> rpush books python java golong
(integer) 3
# 在java前面插入 ruby
127.0.0.1:6379> linsert books before java ruby
(integer) 4
# 在java後面插入 c#
127.0.0.1:6379> linsert books after java c#
(integer) 5
# 檢視所有元素
127.0.0.1:6379> lrange books 0 -1
1) "python"
2) "ruby"
3) "java"
4) "c#"
5) "golong"

根據上面在java前後插入了rubyc#

查詢元素

127.0.0.1:6379> lrange books 0 -1
1) "python"
2) "ruby"
3) "java"
4) "c#"
5) "golong"
127.0.0.1:6379> lindex books 2
"java"
127.0.0.1:6379> llen books
(integer) 5

指令簡單,索性寫一塊吧。
lrange可以遍歷列表,引數為startend。這裡0 -1,是指從第一個到最後一個,即遍歷列表。
lindex查詢指定位置的元素,引數是下標值。這個命令是慢查詢,需要遍歷連結串列。
llen可以檢視列表元素個數。

刪除資料

剛才演示的rpoplpop可以彈出一個元素,不再演示。

可以使用lrem 刪除多個同一元素
count > 0:從左到右,刪除最多 count 個元素。
count < 0:從右到左,刪除最多 count 絕對值 個元素。
count = 0,刪除所有。

# 從左刪除a元素,刪除了3個
127.0.0.1:6379> rpush char a a b b a a c 
(integer) 7
127.0.0.1:6379> lrem chae 3 a
(integer) 0
127.0.0.1:6379> lrem char 3 a
(integer) 3
127.0.0.1:6379> lrange char 0 -1
1) "b"
2) "b"
3) "a"
4) "c"
# 從右刪除 3 個a元素
127.0.0.1:6379> rpush char1 a a b b a a c 
(integer) 7
127.0.0.1:6379> lrem char1 -3 a
(integer) 3
127.0.0.1:6379> lrange char1 0 -1
1) "a"
2) "b"
3) "b"
4) "c"
# 刪除所有 a 元素
127.0.0.1:6379> rpush char2 a a b b a a c
(integer) 7
127.0.0.1:6379> lrem char2 0 a
(integer) 4
127.0.0.1:6379> lrange char2 0 -1
1) "b"
2) "b"
3) "c"

還可以使用ltrim擷取一部分資料,刪除其餘資料

127.0.0.1:6379> rpush char3 a b c d e f g
(integer) 7
127.0.0.1:6379> ltrim char3 1 3
OK
127.0.0.1:6379> lrange char3 0 -1
1) "b"
2) "c"
3) "d"

修改

127.0.0.1:6379> lrange books 0 -1
1) "python"
2) "ruby"
3) "java"
4) "c#"
5) "golong"
127.0.0.1:6379> lset books 2 javaScript
OK
127.0.0.1:6379> lrange books 0 -1
1) "python"
2) "ruby"
3) "javaScript"
4) "c#"
5) "golong"

可以用lset更改某個位置上的元素,這也是個慢查詢,時間複雜度為O(n)。

阻塞操作

blpopbrpoplpoprpop基礎上增加了阻塞時間,如果直接獲取,發現列表中沒有資料,那麼會阻塞等待一段時間,如果該段時間內還是無法得到資料,就返回等待時長。若設定的時間是0的話,即為無限等待。這裡需要兩個終端做配合。

# 終端1 
127.0.0.1:6379> lpop books
(nil)
127.0.0.1:6379> blpop books 5
(nil)
(5.06s)
# 這裡需要在終端1 執行blpop後插入一條資料
127.0.0.1:6379> blpop books 20
1) "books"
2) "java"
(4.61s)
# 這裡需要在終端1 執行blpop後插入一條資料
127.0.0.1:6379> blpop books 0
1) "books"
2) "python"
(9.66s)
# 除此之外,還可以同時阻塞多個佇列,先有資料的那個彈出
127.0.0.1:6379> blpop books schools 0
1) "schools"
2) "hzsy"
(26.75s)

總結

命令 解釋
rpush lpush 彈入資料
rpop lpop 彈出資料
brpop blpop 阻塞彈出資料
linsert 向佇列任意位置加入元素
lrange 遍歷列表
lindex 查詢指定位置上元素
llen 列表長度
lrem 刪除多個同一元素
ltrim 擷取指定列表
lset 修改列表指定位置元素

內部編碼

ziplist:當列表的元素個數小於list-max-ziplist-entries配置(預設 512 個),同時列表中每個元素的值都小於list-max-ziplist-value 配置時(預設 64 位元組),Redis 會選用ziplist 來作為 列表 的內部實現來減少記憶體的使用。
linkedlist:當列表型別無法滿足ziplist的條件時,Redis會使用linkedlist作為列表的內部實現。

使用場景

可以做或者佇列
還可以利用阻塞功能做訊息佇列

hash (雜湊)

Redis 的字典相當於Java語言裡面的HashMap,它是無序字典。內部實現結構上同Java的HashMap也是一致的,同樣的陣列 + 連結串列二維結構。擴容rehash的時候,採用漸進式。在rehash時,保留兩個新舊hash結構,查詢的時候都查,再根據定時任務,一點點將舊hash上的資料遷移到新的hash上,遷移完畢,舊hash被刪除,並收回記憶體。我們預設key為hashKey,filed為小key

常用命令

設定值

127.0.0.1:6379> hset user name pjjlt
(integer) 1
127.0.0.1:6379> hset user age 26
(integer) 1
127.0.0.1:6379> hset user company gongsi
(integer) 1

獲取值

127.0.0.1:6379> hget user name
"pjjlt"

刪除field

127.0.0.1:6379> hdel user company
(integer) 1

計算field個數

127.0.0.1:6379> hlen user
(integer) 2

批量設定獲取值

127.0.0.1:6379> hmset user name pjjlt age 26 city shijiazhuang
OK
127.0.0.1:6379> hmget user name age
1) "pjjlt"
2) "26"

判斷filed是否存在

127.0.0.1:6379> hexists user name
(integer) 1

獲取所有filed或者value

127.0.0.1:6379> hkeys user
1) "name"
2) "age"
3) "city"
127.0.0.1:6379> hvals user
1) "pjjlt"
2) "26"

獲取所有filed和value

127.0.0.1:6379> hgetall user
1) "name"
2) "pjjlt"
3) "age"
4) "26"
5) "city"
6) "shijiazhuang"

自增

127.0.0.1:6379> hincrby user age -8
(integer) 18
127.0.0.1:6379> hset user scroe 99.6
(integer) 1
127.0.0.1:6379> hincrbyfloat user scroe 0.4
"100"

hincrbyhincrbyfloat分別增加或者減少整型浮點型

計算值的長度

127.0.0.1:6379> hget user name
"pjjlt"
127.0.0.1:6379> hstrlen user name
(integer) 5

總結

命令 解釋
hset 設定值
hget 獲取值
hdel 刪除值
hlen 計算field個數
hmset 批量設定值
hmget 批量獲取值
hexists 判斷field是否存在
hkeys 獲取所有field
hvals 獲取所有value
hgetall 獲取所有filed和value
hincrby 增加整型數值
hincrbyfloat 增加浮點型數值
hstrlen 計算值的長度

內部編碼

ziplist:當列表的元素個數小於list-max-ziplist-entries配置(預設 512 個),同時列表中每個元素的值都小於list-max-ziplist-value 配置時(預設 64 位元組),Redis 會選用ziplist 來作為 列表 的內部實現來減少記憶體的使用。

hashtable:當雜湊型別無法滿足ziplist的條件時,Redis會使用hashtable作為雜湊的內部實現,因為此時ziplist的讀寫效率會下降,而hashtable的讀寫時間複雜度為O(1)。

使用場景

hash很適合快取物件,比如商城系統可以存放商品,hashkey為商品id,field為各種屬性,value為資料。當然string也可以存放商品,只不過它的value,時json串,還需要解析,從程式碼角度和網路代價來講都不如hash

set (集合)

set相當於Java語言裡面的 HashSet,它內部的鍵值對是無序的唯一的。它的內部實現相當於一個特殊的字典,字典中所有的value都是一個值NULL。

常用命令

增加元素

127.0.0.1:6379> sadd books java python python ruby java
(integer) 3

sadd可以新增一個或者多個元素,並且去重。

刪除元素

127.0.0.1:6379> srem books python ruby
(integer) 2

srem可以刪除一個或者多個元素。

計算元素個數

127.0.0.1:6379> sadd books python ruby c#
(integer) 3
127.0.0.1:6379> scard books
(integer) 4

判斷元素是否在集合中

127.0.0.1:6379> sismember books java
(integer) 1
127.0.0.1:6379> sismember books c
(integer) 0

隨機返回一定數量的元素

127.0.0.1:6379> srandmember books 2
1) "java"
2) "ruby"
127.0.0.1:6379> srandmember books 2
1) "c#"
2) "ruby"

隨機彈出一個元素

127.0.0.1:6379> spop books
"ruby"
127.0.0.1:6379> scard books
(integer) 3

獲取所有元素

127.0.0.1:6379> smembers books
1) "c#"
2) "java"
3) "python"

計算並查集

127.0.0.1:6379> sadd set1 a b c d e
(integer) 5
127.0.0.1:6379> sadd set2 d e f g
(integer) 4
# 計算兩個集合交集
127.0.0.1:6379> sinter set1 set2
1) "e"
2) "d"
# 計算兩個集合並集
127.0.0.1:6379> sunion set1 set2
1) "g"
2) "a"
3) "d"
4) "e"
5) "c"
6) "f"
7) "b"
# 計算兩個集合差集
127.0.0.1:6379> sdiff set1 set2
1) "c"
2) "b"
3) "a"

總結

命令 解釋
sadd 增加元素
srem 刪除元素
scard 計算元素個數
sismember 判斷元素是否在集合中
srandmember 隨機返回一定數量的元素
spop 隨機彈出一個元素
smembers 獲取所有元素
sinter 計算兩個集合交集
sunion 計算兩個集合並集
sdiff 計算兩個集合差集

內部編碼

intset:當集合中的元素都是整數且元素個數小於set-max-intset-entries配置(預設 512 個)時,Redis會選用intset來作為集合的內部實現,從而減少記憶體的使用。

hashtable:當集合型別無法滿足intset的條件時,Redis會使用hashtable作為集合的內部實現。

使用場景

利用並查集可以用於查詢使用者共同愛好。

利用不可重複性,可以用於抽獎,保證每個使用者只能中一次獎。

zset(有序集合)

zset可能是Redis提供的最為特色的資料結構。它類似於Java的SortedSet和HashMap的結合體,一方面它是一個set,保證了內部value的唯一性,另一方面它可以給每個value賦予一個score,代表這個value的排序權重。

常用命令

# 設定值
127.0.0.1:6379> zadd books 9 java
(integer) 1
127.0.0.1:6379> zadd books 8 python
(integer) 1
127.0.0.1:6379> zadd books 7 golang
(integer) 1
# 檢視一定範圍內的值
127.0.0.1:6379> zrange books 0 -1
1) "golang"
2) "python"
3) "java"
# 刪除某個值
127.0.0.1:6379> zrem books golang
(integer) 1
# 根據score 正序排
127.0.0.1:6379> zrange books 0 -1
1) "python"
2) "java"
# 根據score 倒敘排
127.0.0.1:6379> zrevrange books 0 -1
1) "java"
2) "python"
# 檢視元素個數
127.0.0.1:6379> zcard books
(integer) 2
# 檢視某元素分值
127.0.0.1:6379> zscore books java
"9"
# 正序排名,從0開始
127.0.0.1:6379> zrank books  python
(integer) 0
127.0.0.1:6379> zrank books java
(integer) 1
# 一定範圍內scor內的元素
127.0.0.1:6379> zrangebyscore books 0 8.8
1) "python"

總結

命令 解釋
zadd 設定值
zrange 檢視一定範圍內的值
zrem 刪除某個值
zrange 根據score正序排
zrevrange 根據score倒敘排
zcard 檢視元素個數
zscore 檢視某元素分值
zrank 正序排名,從0開始
zrangebyscore 一定範圍內scor內的元素

內部編碼

zset內部的排序功能是通過「跳躍列表」資料結構來實現的,它的結構非常特殊,也比較複雜。舉個例子吧,就好像一個公司,有9個員工,分為3各小組,每個小組算一個小組長(注意小組長還具備員工角色,只不過多了小組長角色)小組長再選出一個技術總監(技術總監同時具備員工、小組長、技術總監角色)

使用場景

適合排名性質的場景,比如微博熱搜,某技術網站熱門部落格等等。

總結不易,小夥伴給個贊再走吧。