1. 程式人生 > 其它 >分散式儲存-Redis&常用資料庫(Profile)

分散式儲存-Redis&常用資料庫(Profile)

分散式儲存-Redis&常用資料庫(Profile)

實際上我們使用Redis的初衷就是為了優化資料庫,當我們使用者的行為增加了,我們資料庫的IO就增加了,Redis的資料是儲存在記憶體中,而我們的傳統的資料的資料是儲存在磁碟中,就儲存在記憶體這一方面Redis就優化了資料的讀取速度。本篇中聊一聊常用的Redis資料結構、不同的儲存資料帶來的效能提升、常用的資料庫優化手段

資料庫層面的優化手段

池化技術】:實現連線資源的複用(本質上是降低資源建立和銷燬的開銷),當我們去連結資料庫的會發送一個TCP請求到資料庫上,如果使用池化技術,那就節省了很多時間,提升了效能。

【資料庫本身層面的優化】

索引】:當沒有索引的時候,我們去查詢資料,他會去掃描磁碟軌道,有了索引就相當於通過一個點直接進行定位,這樣速度就快了很多

資料量的傳輸】:我們可以儘量減少資料量的傳輸,少查詢一些不必要的資料,肯定就提高效能。

資料庫的讀寫分離】:如果沒有做讀寫分離,每個資料在進行事務操作的時候就會加鎖,從而影響了查詢的速度

常見的資料庫型別

資料庫的發展歷史是->關係型資料庫->NOSQL->NEWSQL

KV資料庫】:

  • 鍵值形式
  • 資料儲存在記憶體中(無法支援海量儲存)
  • 時間複雜度是O(1)

列式資料庫】:比如一些實時報表、監控資料等場景適合

  • 統計資料速度快(相同的資料儲存在一起)
  • 事務處理速度慢(需要在載入不同的儲存塊中資料進行處理,因為處理的是一條資料中的不用型別)

文件型】:把相關的一系列資料儲存在一個文件中,平常我們查詢使用者、文章、使用者評論三張表才能得到一個完整的資訊,現在把這些都儲存在一起,一下就能檢索出來。

NEWSQL】:NOSQL的下一個階段衍生出來的一種思想;擁有傳統的關係型資料庫的的核心特性,也擁有NOSQL的特性

圖形資料庫】:傳統資料庫中,可能在一個給定實體中有很多關係,比如一個專家評分,牽扯到標書表,招標表、投標表、專家組長表、專家型別表等等,而在圖形資料庫中這些就抽象成一個個節點,建立相應的關係即可,這些組合成專家評分的資料所需的表只是節點集中的節點。

Redis(K-V 資料庫)http://doc.redisfans.com/(常用命令)

Redis已經是一個眾所周知的技術了,這裡就不講他的安裝以及介紹他的。安裝的時候有一個坑的地方就是我們的GCC必須是5.3版本以上,要不安裝Redis就會報錯。用YUM預設是4.*,使用以下命令可以升級他的版本到9,就可以解決報錯的問題

  • # 升級到gcc 9.3:
  • yum -y install centos-release-scl
  • yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
  • scl enable devtoolset-9 bash
  • # 需要注意的是scl命令啟用只是臨時的,退出shell或重啟就會恢復原系統gcc版本。
  • # 如果要長期使用gcc 9.3的話:
  • echo -e "\nsource /opt/rh/devtoolset-9/enable" >>/etc/profile

這裡用Jemeter壓測了兩個介面,一個是從資料庫直接讀取資料的,另外一個是把資料快取在Redis中然後讀取的,我們發現使用Redis查詢資料的介面每秒的吞吐量多了一倍。所以這是我們使用他的一個原因。

【資料型別】

String:Redis是用c開發的,C中並沒有string型別,所以他的底層實際上是使用了一個動態的sds(因為我們string的長度是不固定的,所以他用了一個動態的結構),在sds的結構中才使用了一個char陣列對我們的string進行儲存

【常見命令】:

這裡有一些特殊的命令

incr和 decr:這個命令是原子的,他可以保證執行緒安全的特性。因為Redis是單執行緒的,所以他可以保證原子性,那我們就可以用這個來做分散式id。

setnx: 我們可以用這個特性做我們的分散式鎖,我們知道鎖的特性是排他的,那當返回0的時候,則證明有一個數據已經存在了,這樣就巧妙的使用了這個功能。

使用場景

【快取應用】:快取熱點資料

【全域性id】:使用incr 進行遞增

【限流】:(比如設定一個key為一個使用者id,然後value的值的過期時間設定60s(根據自己需要),然後配合incr 進行遞增,當value的數值大於我們能接受的資料,我們就關閉訪問通道)

【分散式session】:他等於是一個全域性的視角,第三方的,所以我們的所有微服務都可以去這裡獲取資料。

List:是一個有序,且可重複的字串連結串列,是一個棧+堆結構,可以支援非or阻塞的FIFO/LIFO,

簡而言之:他是一個Quicklist結構(就是個雙向連結串列,每個節點中儲存的是一個ziplist(壓縮列表,前面的執行緒篇章我們講了cpu的做快取記憶體時候一次讀取的一個快取行的資料,為了防止偽共享,如果當前的位置不是滿的,則自動補0,壓縮列表就是讓每個位置都儲存有效的資料,而不是用0代替,這就讓效能大大提升,讓cpu每次讀取的都是有效的資料,並且節省記憶體))

【常見命令】

使用場景

【訊息佇列】:我們使用lpush入隊一個數據,用rpop從右邊出隊一個數據

【傳送紅包場景】:我們在傳送前面計算好紅包的個數和金額,用lpush入隊,然後抽取紅包的時候使用rpop出隊。其實秒殺也行,我們把庫存資料直接放在Redis中,然後還是相同的操作

hash:當hash個數小於512的時候,以及所有的數值都小於64個位元組的時候,預設情況下會通過ziplist儲存多個數據元素,因為資料量小的時候,使用ziplist去儲存可以節省記憶體空間,並且檢索不會太慢,但是超過這個閾值的時候,他就會採用hashtable進行儲存,因為hashtable的讀寫時間複雜度是o(1)

常見命令

使用場景

購物車、商品詳情資料、使用者資訊、計數器、so on

Set:是一個無序,並且唯一的集合 (https://www.cnblogs.com/xinhuaxuan/p/9256738.html)如果set中儲存的都會整形他都會使用intset進行儲存,否則用hashtable進行儲存

使用場景

使用者畫像、標籤管理

zset:他是一個有序的的集合,在每個value前面維護了一個score,基於每個score進行排序。看下面的命令我們發現,可以通過key和score進行檢索資料,他的底層實際上是使用了hashtable和跳錶進行儲存的,如果我想通過key去檢索資料,那就使用hashtable進行檢索(他的時間複雜度是0(1)),而當我們使用score去檢索的話,那就使用跳錶進行檢索(我們知道跳錶有等級,當我們要檢索某個資料的時候,他不在某個等級的話,就會跳到下一個等級去進行檢索,他的時間複雜度是o(log)),實際上不管使用跳錶還是hashtable他們都是一個指標指向原資料,這樣就可以防止記憶體浪費

【常見命令】

使用場景

使用者點贊排行、熱點話題排行,因為每個資料中都有score,用score我們就可以計算出排行