1. 程式人生 > 資訊 >紫米 TWS 真無線耳機團隊產品銷量突破 100 萬

紫米 TWS 真無線耳機團隊產品銷量突破 100 萬

一、NoSQL

1. 概述

NoSQL(NoSQL = Not Only SQL ),意即“不僅僅是SQL”,泛指非關係型的資料庫,NoSQL 不依賴業務邏輯方式儲存。

2. 適用場景

用不著sql的和用了sql也不行的情況,請考慮用NoSql

  • 對資料高併發的讀寫
  • 海量資料的讀寫
  • 對資料高可擴充套件性的

3. 常見的NoSQL資料庫

3.1 Memcache

  • 資料都在記憶體中,一般不持久化
  • 支援簡單的 key-value 模式,支援型別單一
  • 一般是作為快取資料庫輔助持久化的資料庫

3.2 Redis

  • 資料都在記憶體中,支援持久化,主要用作備份恢復
  • 除了支援簡單的 key-value 模式,還支援多種資料結構的儲存,比如 list、set、hash、zset等。
  • 一般是作為快取資料庫輔助持久化的資料庫

3.3 MongoDB

  • 高效能、開源、模式自由(schema free)的文件型資料庫
  • 資料都在記憶體中, 如果記憶體不足,把不常用的資料儲存到硬碟
  • key-value 模式,對value(尤其是json)提供了豐富的查詢功能
  • 支援二進位制資料及大型物件
  • 可以根據資料的特點替代RDBMS ,成為獨立的資料庫。或者配合RDBMS,儲存特定的資料。

二、Redis的安裝

Redis是一個開源的 key-value 儲存系統

它支援儲存的value型別相對更多,包括 string、list、set、zset(sorted set --有序集合)和 hash

這些資料型別都支援 push/pop、add/remove 及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。

在此基礎上,Redis支援各種不同方式的排序

為了保證效率,資料都是快取在記憶體中

Redis會週期性的把更新的資料寫入磁碟或者把修改操作寫入追加的記錄檔案

並且在此基礎上實現了master-slave(主從)同步

1. 應用場景

1.1 配合關係型資料庫做快取記憶體

  • 高頻次,熱門訪問的資料,降低資料庫IO
  • 分散式架構,做session共享

1.2 多樣的資料結構儲存持久化資料

  • 通過 list 實現最新的N個數據
  • 通過 zset 實現TopN
  • 通過 set 去除大量資料中的重複資料
  • 利用原子性實現計數器、秒殺等
  • ...

2. Redis安裝

2.1 使用docker安裝

2.1.1 安裝Redis

docker pull redis	# 安裝最新版本的redis

2.1.2 在主機寫配置檔案

# 在 data/redis/redis.conf 配置檔案中寫配置內容:
appendonly yes

2.1.3 啟動Redis

# 配置檔案掛載,/data/redis目錄下有redis.conf配置檔案,主機中的 /data/redis 目錄對應容器中的 /usr/local/etc/redis 
# 持久化資料掛載
# 後臺執行  起別名
# 埠對映
# 啟動容器中的redis
docker run -v /data/redis:/usr/local/etc/redis \
-v /data/redis/data:/data \
-d --name myredis \
-p 6379:6379 \
redis:latest redis-server /usr/local/etc/redis/redis.conf

2.1.4 使用客戶端連線Redis

docker exec -it CONTAINER redis-cli

2.1.5 驗證是否連線成功

ping

3. Redis相關知識

3.1 基本情況

  • 預設16個數據庫,從0開始,初始預設使用0號庫
  • 使用命令 select <dbid>來切換資料庫。如: select 8
  • 統一密碼管理,所有庫同樣密碼

3.2 基本原理

Redis 是單執行緒+多路IO複用技術

多路複用是指使用一個執行緒來檢查多個檔案描述符(Socket)的就緒狀態,比如呼叫select和poll函式,傳入多個檔案描述符,如果有一個檔案描述符就緒,則返回,否則阻塞直到超時。得到就緒狀態後進行真正的操作可以在同一個執行緒裡執行,也可以啟動執行緒執行(比如使用執行緒池)

三、資料型別

Redis有5種常用資料型別,它們是key-value中的value,對於key來說有一些通用命令:

set k1 v1	# 存入鍵值對
keys *		# 檢視當前庫所有key
exists key	# 判斷某個key是否存在
type key 	# 檢視你的key是什麼型別
del key     # 刪除指定的key資料
unlink key  # 根據value選擇非阻塞刪除,僅將keys從keyspace元資料中刪除,真正的刪除會在後續非同步操作。
expire key 10	# 設定key10秒後過期,過期後自動刪除
ttl key 	# 檢視還有多少秒過期,-1表示永不過期,-2表示已過期
select		# 命令切換資料庫
dbsize		# 檢視當前資料庫的key的數量
flushdb		# 清空當前庫
flushall	# 通殺全部庫

1. String

String是Redis最基本的型別,key都是字串型別,其他幾種資料結構都是在String基礎上構建的。String的值實際可以是字串(簡單字串、複雜字串如Json、XML)、數字(整數、浮點數),甚至是二進位制(圖片、音視訊),最大不能超過512M

1.1 常用命令

1.1.1 設定value

  1. 單個設定值
SET key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET]

# EX seconds:設定key的秒級過期時間
# PX milliseconds:設定key的毫秒級過期時間,與EX互斥
# NX:key必須不存在才能設定成功,用於新增
# XX:key必須存在才能設定成功,用於更新

# return value:set執行正確返回OK,指定了NX/XX但沒有正確執行,返回(nil)


SETNX key value	# 相當於 SET key value NX
SETEX key seconds value	# 相當於 SET key value EX seconds
  1. 批量設定值
MSET key value [key value ...]	# 原子操作

1.1.2 獲取value

  1. 獲取單個值
GET key

# return value:key存在返回對應的value,不存在返回(nil)
  1. 批量獲取值
MGET key [key ...]

1.1.3 計數

  1. 自增
INCR key	# value為String型別的數字時才能自增1,是原子操作
INCRBY key increment	# value自增increment
  1. 自減
DECR key
DECRBY key increment

1.1.4 追加value

APPEND key value

# return value:返回value的長度

1.1.5 獲取value長度

STRLEN key

1.1.6 設定並返回value

GETSET key value

# return value:返回舊值

1.1.7 設定value指定位置的字元

SETRANGE key offset value

# 用value覆蓋從offset開始的字串,返回新字串的長度

1.1.8 獲取value指定位置的字串

GETRANGE key start end	# 左閉右閉

1.2 內部編碼

String 的內部編碼有3種:

  • int:8個位元組的長整型(必須是String型別的數字)
  • embstr:<=39 個位元組的字串
  • raw:>39 個位元組的字串

1.3 資料結構

String 的資料結構為簡單動態字串(Simple Dynamic String,縮寫SDS)。是可以修改的字串,內部結構實現上類似於 Java 的 ArrayList,採用預分配冗餘空間的方式來減少記憶體的頻繁分配。

當字串長度小於 1M 時,擴容都是加倍現有的空間,如果超過 1M,擴容時一次只會多擴 1M 的空間。需要注意的是字串最大長度為 512M

1.4 使用場景

  • 快取功能
  • 計數
  • 共享 Session
  • 限速/限制次數

2. List

List 是插入有序的字串列表。底層是雙向連結串列,可以新增一個元素到列表的頭部或者尾部,能充當棧和佇列。一個列表可以儲存 231 - 1 個元素。

2.1 常用命令

2.1.1 新增元素

  1. 從右邊插入元素
RPUSH key element [element ...]

# return value:返回列表中元素的個數
  1. 從左邊插入元素
LPUSH key element [element ...]
  1. 向某個元素前/後插入元素
LINSERT key BEFORE|AFTER pivot element

2.1.2 查詢元素

  1. 根據範圍查詢元素
LRANGE key start stop	# 左閉右閉
# 索引下標從左到右是 0 到 n-1,從右到左是 -1 到 -n
# lrange mylist 0 -1 表示查詢所有
  1. 根據索引查詢元素
LINDEX key index
  1. 獲取列表長度
LLEN key

2.1.3 刪除元素

  1. 從右邊彈出元素
RPOP key
  1. 從左邊彈出元素
LPOP key
  1. 刪除指定的元素
LREM key count element

# count > 0,從左到右,刪除最多count個元素
# count < 0,從右到左,刪除最多-count個元素
# count == 0,刪除所有value為element的元素
  1. 保留指定範圍的元素
LTRIM key start stop	# 左閉右閉

2.1.4 修改元素

LSET key index element

2.1.5 阻塞操作

BRPOP key [key ...] timeout
BLPOP key [key ...] timeout

# key對應的列表為空,客戶端等待timeout後返回,返回值為(nil)和阻塞時間timeout,若timeout==0,客戶端一直等待下去
# 列表不為空,客戶端會立即返回,返回值是彈出元素的key和彈出的元素

2.2 內部編碼

List 的內部編碼如下:

  • 快速列表(quicklist)

    列表的節點是ziplist,雙指標將ziplist串起來組成quicklist

2.3 使用場景

lpush + lpop = stack

lpush + rpop = queue

lpush + ltrim = capped collection(有限集合)

lpush + brpop = message queue(訊息佇列)

  • 訊息佇列
  • 文章列表

3. Set

Set 是無序去重的,底層是 value 為 null 的 Hash 表

3.1 常用命令

3.1.1 新增元素

SADD key member [member ...]

# 重複元素不新增,自動去重
# return value:返回集合中新增成功的元素個數

3.1.2 獲取元素

  1. 獲取所有元素
SMEMBERS key
  1. 隨機獲取指定個數的元素
SRANDMEMBER key [count]	# count不寫預設為1

3.1.3 獲取元素個數

SCARD key

3.1.4 判斷元素是否在集合中

SISMEMBER key member

# 在返回1,不在返回0

3.1.5 刪除元素

  1. 刪除指定元素
SREM key member [member ...]

# return value:返回成功刪除的元素個數
  1. 隨機彈出指定個數的元素(並刪除)
SPOP key [count]

3.1.6 移動集合中的元素

SMOVE source destination member	# 將一個元素從source移動到destination

3.1.7 求多個集合的交集

SINTER key [key ...]

SINTERSTORE destinationkey key [key ...]	# 將多個集合交集儲存到destinationkey集合中

3.1.8 求多個集合的並集

SUNION key [key ...]

SUNIONSTORE destinationkey key [key ...]

3.1.9 求多個集合的差集

SDIFF key [key ...]

SDIFFSTORE destinationkey key [key ...]

3.2 內部編碼

Set 的內部編碼有2種:

  • intset:集合中的元素都是整數,且元素個數小於set-max-intset-entries配置(預設512個)時,使用intset
  • hashtable:不滿足上述條件時,使用hashtable

3.3 使用場景

  • 標籤:sadd
  • 生成隨機數:spop/srandmember
  • 共同愛好:sadd + sinter

4. Hash

Hash 是鍵值對(field-value)集合,類似於 Java 中的 Map,field不能重複

4.1 常用命令

4.1.1 新增元素

HSET key field value [field value ...]

# field去重
# return value:返回Hash中新增成功的元素個數,若為覆蓋操作則返回0

HSETNX key field value	# 當且僅當field不存在時生效

4.1.2 獲取元素

  1. 獲取field對應的value
HGET key field
  1. 批量獲取field對應的value
HMGET key field [field ...]
  1. 獲取所有的field
HKEYS key
  1. 獲取所有的value
HVALS key

4.1.3 獲取元素個數

HLEN key

4.1.4 判斷field是否存在

HEXISTS key field

4.1.5 刪除field

HDEL key field [field ...]

# return value:返回成功刪除的field個數

4.1.6 獲取所有的field-value

HGETALL key

4.1.7 計數(自增)

HINCRBY key field increment

4.1.8 獲取value長度

HSTRLEN key field

4.2 內部編碼

Hash 的內部編碼有2種:

  • ziplist

    當 Hash 型別的元素個數小於hash-max-ziplist-entries(預設512個),且所有值的空間大小小於hash-max-ziplist-value(預設64位元組)時,使用ziplist

  • hashtable

    無法滿足上述條件時,使用hashtable

4.3 使用場景

使用者資訊的儲存:hset user:1 name dxx age 25 city lanzhou

5. Sorted Set

Sorted Set 是有序去重的,它給每個元素設定一個分數(score),並以此為依據進行排序(分數升序)。

5.1 常用命令

5.1.1 新增元素

ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...]

# 重複元素不新增,自動去重
# return value:返回集合中新增成功的元素個數,若為更改則返回0;可通過CH引數將返回值改變為 新增和更改的元素個數

5.1.2 獲取元素

  1. 獲取指定排名範圍的元素
ZRANGE key start stop [WITHSCORES]		# 分數從低到高排名
ZREVRANGE key start stop [WITHSCORES]	# 分數從高到低排名
  1. 獲取指定分數範圍的元素
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count] # min和max反著寫一下

# [LIMIT offset count] 限制輸出的起始位置和輸出個數
# (min (max 表示左開右開,不寫括號表示左閉右閉
# -inf 表示無窮小,+inf 表示無窮大

5.1.3 獲取元素個數

  1. 獲取所有元素個數
ZCARD key
  1. 獲取指定分數範圍的元素個數
ZCOUNT key min max

5.1.4 計算具體元素

  1. 計算某個元素的分數
ZSCORE key member
  1. 計算某個元素的排名
ZRANK key member
ZREVRANK key member
  1. 增加某個元素的分數
ZINCRBY key increment member

5.1.4 刪除元素

  1. 刪除指定元素
ZREM key member [member ...]

# return value:返回成功刪除的元素個數
  1. 刪除指定排名範圍的元素
ZREMRANGEBYRANK key start stop
  1. 刪除指定分數範圍的元素
ZREMRANGEBYSCORE key min max

5.1.5 求交集

ZINTER numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX] [WITHSCORES]
# numkeys:需要做交集計算鍵的個數
# [WEIGHTS weight]:每個key的權重,計算時每個key中的每個member會將自己的score乘以權重,預設是1
# [AGGREGATE SUM|MIN|MAX]:計算交集後,分數可以按照sum、min、max做彙總,預設是sum

ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
# destination:交集計算的結果儲存到這個key

5.1.6 求並集

ZUNION numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX] [WITHSCORES]

ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]

5.2 內部編碼

Sorted Set 內部編碼有2種:

  • ziplist

    當有序集合的元素個數小於zset-max-ziplist-entries(預設128個),且每個元素所佔空間大小小於zset-max-ziplist-value(預設64位元組)時,使用ziplist

  • skiplist

    上述條件不滿足時,會使用跳躍表

跳躍表是一種基於有序連結串列的擴充套件,簡稱跳錶。

分層建立多級索引,使得比較次數減少,時間複雜度降低到O(logn),屬於空間換時間。

5.3 使用場景

排行榜系統

6. Bitmaps

Bitmaps 本身不是一種資料型別,實際上它就是字串,但是它可以對字串的位進行操作。可以把 Bitmaps 想象成一個以位為單位的陣列,陣列的每個單元只能儲存0和1,陣列的下標在 Bitmaps 中叫做偏移量。

6.1 常用命令

6.1.1 設定值

SETBIT key offset value

6.1.2 獲取值

GETBIT key offset

6.1.3 獲取指定範圍內值為1的個數

BITCOUNT key [start end]

# start end 表示起始和結束的位元組數,1 byte = 8 bit

6.1.4 計算第一個值為targetBit的偏移量

BITPOS key bit [start] [end]

6.1.5 多個Bitmaps間的運算

BITOP operation destkey key [key ...]

# operation 包括 and、or、not、xor
# 將運算結果存放到destKey中

6.2 使用場景

記錄使用者是否訪問過網站時,每個使用者只佔用 1bit 的空間。具體操作如下:首先將所有使用者都儲存起來,用0表示沒訪問過,1表示訪問過。若活躍使用者很多時,使用 Bitmaps 可以節省空間。

使用者id會以一個較大的數字開始(比如10000),若直接將使用者id與偏移量對應必然會造成空間浪費,通常做法是將使用者id減去這個數字。

7. HyperLogLog

HyperLogLog 本身不是一種資料型別,實際上它是字串型別,是用來做基數統計的演算法,它可以利用極小的記憶體空間完成獨立總數的統計(近似值)。

7.1 常用命令

7.1.1 新增元素

PFADD key element [element ...]

7.1.2 計算獨立使用者數

PFCOUNT key [key ...]	# 簡單來說就是統計不重複的元素

7.1.3 合併

PFMERGE destkey sourcekey [sourcekey ...]

7.2 使用場景

只需要統計總數,不需要獲取具體的單條資料,且可以容忍一定的誤差。

8. GEO

GEO(Geographic),就是元素的二維座標,在地圖上就是經緯度。

8.1 常用命令

8.1.1 增加地理位置資訊

GEOADD key [NX|XX] [CH] longitude latitude member [longitude latitude member ...]

# longitude latitude member 分別是經度、緯度、所屬城市

8.1.2 獲取資訊

GEOPOS key member [member ...]

8.1.3 獲取兩個位置的距離

GEODIST key member1 member2 [m|km|ft|mi]

8.1.4 獲取指定範圍內的資訊

GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE key] [STOREDIST key]

GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE key] [STOREDIST key]

8.1.5 獲取 geohash

GEOHASH key member [member ...]

8.1.6 刪除資訊

ZREM key member [member ...]

# redis沒有提供刪除命令,但是GEO底層是zset,所以可以使用zrem刪除

8.2 使用場景

地理位置資訊