實際上咱們使用Redis的初衷就是爲了優化數據庫,當咱們用戶的行爲增長了,咱們數據庫的IO就增長了,Redis的數據是存儲在內存中,而咱們的傳統的數據的數據是存儲在磁盤中,就存儲在內存這一方面Redis就優化了數據的讀取速度。本篇中聊一聊經常使用的Redis數據結構、不一樣的存儲數據帶來的性能提高、經常使用的數據庫優化手段html
【池化技術】:實現鏈接資源的複用(本質上是下降資源建立和銷燬的開銷),當咱們去連接數據庫的會發送一個TCP請求到數據庫上,若是使用池化技術,那就節省了不少時間,提高了性能。c++
【數據庫自己層面的優化】:redis
【索引】:當沒有索引的時候,咱們去查詢數據,他會去掃描磁盤軌道,有了索引就至關於經過一個點直接進行定位,這樣速度就快了不少shell
【數據量的傳輸】:咱們能夠儘可能減小數據量的傳輸,少查詢一些沒必要要的數據,確定就提升性能。數據庫
【數據庫的讀寫分離】:若是沒有作讀寫分離,每一個數據在進行事務操做的時候就會加鎖,從而影響了查詢的速度centos
數據庫的發展歷史是->關係型數據庫->NOSQL->NEWSQL數組
【KV數據庫】:緩存
- 鍵值形式
- 數據存儲在內存中(沒法支持海量存儲)
- 時間複雜度是O(1)
【列式數據庫】:好比一些實時報表、監控數據等場景適合安全
- 統計數據速度快(相同的數據存儲在一塊兒)
- 事務處理速度慢(須要在加載不一樣的存儲塊中數據進行處理,由於處理的是一條數據中的不用類型)
【 文檔型】:把相關的一系列數據存儲在一個文檔中,日常咱們查詢用戶、文章、用戶評論三張表才能獲得一個完整的信息,如今把這些都存儲在一塊兒,一下就能檢索出來。bash
【NEWSQL】:NOSQL的下一個階段衍生出來的一種思想;擁有傳統的關係型數據庫的的核心特性,也擁有NOSQL的特性
【圖形數據庫】:傳統數據庫中,可能在一個給定實體中有不少關係,好比一個專家評分,牽扯到標書表,招標表、投標表、專家組長表、專家類型表等等,而在圖形數據庫中這些就抽象成一個個節點,建立相應的關係便可,這些組合成專家評分的數據所需的表只是節點集中的節點。
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咱們就能夠計算出排行