2.NoSQL之Redis設定與優化

2022-06-19 21:01:58

一、關係型資料庫與非關聯式資料庫

關係型資料庫:

關係型資料庫是一個結構化的資料庫,建立在關係模型(二維表格模型)基礎上,一般面向於記錄。
sQL語句(標準資料查詢語言)就是一種基於關係型資料庫的語言,用於執行對關係型資料庫中資料的檢索和操作主流的關係型資料庫包括 oracle、MySQ、sQI server、Microsoft Access、DB2、PostgresgI等。
以上資料庫在使用的時候必須先建庫建表設計表結構,然後儲存資料的時候按表結構去存,如果資料與表結構不匹配就會儲存失敗。

非關係型資料庫

NoSQL (NosgI = Not only sQL ),意思是"不僅僅是 sQL",是非關係型資料庫的總稱。除了主流的關係型資料庫外的資料庫,都認為是非關係型。
不需要預先建庫建表定義資料儲存表結構,每條記錄可以有不同的資料型別和欄位個數(比如微信群聊裡的文字、圖片、視訊、音樂等)。主流的 NosQT資料庫有 Redis、MongBD、Hbase、Memcached、Elasticsearch、TSDB等。

NoSQL(非關係型資料庫)和SQL(關係型資料庫)的主要區別有如下區別:

1、資料儲存方式不同

  • 關係模型的資料結構使用簡單易懂的二維資料表,因此儲存在表的行和列中。他們之間很容易關聯共同作業儲存,提取資料很方便。

關聯式資料庫的儲存結構是二維表格,關係型資料庫大部分將資料存放到硬碟中,可以將有關係的表放在一個庫中

在每個二維表格中

每一行稱為一條記錄,用來描述一個物件的資訊

每一列稱為一個欄位,用來描述物件的一個屬性

  • NoSQL資料庫則與其相反,它是大塊的組合在一起。通常儲存在資料集中,就像檔案、鍵值對或者圖結構。

2、擴充套件方式不同

  1. 關係型資料庫資料儲存在關係表中,操作的效能瓶頸可能涉及到多個表,需要通過提升計算機效能來克服,因此更多是採用縱向擴充套件(提升伺服器的效能)
  2. NoSQL資料庫是橫向擴充套件的,它的儲存天然就是分散式的,可以通過給資源池新增更多的普通資料庫伺服器來分擔負載

3、對事務性的支援不同

關係型資料庫遵循ACID規則(原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、永續性(Durability))。

NoSQL資料庫遵循BASE原則(基本可用(Basically Availble)、軟/柔性事務(Soft-state)、最終一致性(Eventual Consistency))。

由於關係型資料庫的資料強一致性,所以對事務的支援很好。關係型資料庫支援對事務原子性細粒度控制,並且易於回滾事務。

NoSQL資料庫是在CAP (一致性、可用性、分割區容忍度)中任選兩項,因為基於節點的分散式系統中,不可能同時全部滿足,所以對事務的支援不是很好。

非關係型資料庫產生背景

可用於應對web2.0純動態網站型別的三高問題。

(1) High performance——對資料庫高並行讀寫需求

(2) Huge storage——對海量資料高效儲存與存取需求
(3) High scalability && High Availability—對資料庫高可延伸性與高可用性需求
關係型資料庫和非關係型資料庫都有各自的特點與應用場景,兩者的緊密結合將會給Web2.06的資料庫發展帶來新的思路。讓關係型資料庫關注在關係上和對資料的一致性保障,非關係型資料庫關注在儲存和高效率上。例如,在讀寫分離的uysgL資料庫環境中,可以把經常存取的資料儲存在非關係型資料庫中,提升存取速度。
總結:
關係型資料庫:
範例-->資料庫-->表(table)-->記錄行(row)、資料欄位(column)
非關係型資料庫:
範例-->資料庫-->集合(collection)-->鍵值對(key-value)非關係型資料庫不需要手動建資料庫和集合(表)。

二、Redis

Redis簡介

  • Redis 是一個開源的、使用 C 語言編寫的 NoSQL 資料庫。

  • Redis 基於記憶體執行並支援持久化,採用key-value(鍵值對)的儲存形式,是目前分散式架構中不可或缺的一環。

  • Redis伺服器程式是單程序模型,也就是在一臺伺服器上可以同時啟動多個Redis程序,Redis的實際處理速度則是完全依靠於主程序的執行效率。

  • 若在伺服器上只執行一個Redis程序,當多個使用者端同時存取時,伺服器的處理能力是會有一定程度的下降.若在同一臺伺服器上開啟多個Redis程序,Redis在提高並行處理能力的同時會給伺服器的CPU造成很大壓力.所以在實際生產環境中,需要根據實際的需求來決定開啟多少個Redis程序。

Redis的優點

  1. 具有極高的資料讀寫速度:資料讀取的速度最高可達到110000次/s,資料寫入速度最高可達到81000次/s
  2. 持豐富的資料型別:支援key-value(鍵值對) 、 String、Lists、Hashes、Sets及Ordered Sets等資料型別操作
  3. 支援資料的持久化:可以將記憶體中的資料儲存在磁碟中,重啟的時候可以再次載入進行使用
  4. 原子性:Redis所有操作都是原子性的
  5. 支援資料備份:即master-slave模式的資料備份

Memcache和Redis的區別

Memcache Redis
型別 Key-value資料庫 Key-value資料庫
過期策略 支援 支援
資料型別 單一資料型別 五巨量資料型別
持久化 不支援 支援
主從複製 不支援 支援
虛擬記憶體 不支援 支援

Redis常見的資料結構

常見的5種

  • String:字串,最基礎的資料型別

  • List:列表

  • Hash:雜湊物件

  • Set:集合

  • Sorted Set:有序集合, Set 的基礎上加了個分值

Redis作為基於記憶體執行的資料庫,是一個高效能的快取,一般應用在session快取、佇列、排行榜、計數器、最近最熱文章、最近最熱評論、釋出訂閱等。

Redis適用於資料實時性要求高、資料儲存有過期和淘汰特徵的、不需要持久化或者需要保證一致性、邏輯簡單的場景。

Redis為什麼讀寫速度這麼快

  1. Redis 是一款純記憶體結構,避免了磁碟I/O等耗時操作
  2. Redis 命令處理的核心模組為單執行緒,減少了鎖競爭,以及頻繁建立執行緒和銷燬執行緒的代價,減少了執行緒上下文切換的消耗
  3. 採用了 I/O 多路複用機制,大大提升了並行效率

注:在Redis 6.0 中新增加的多執行緒也只是爭對處理網路請求過程採用了多執行緒,二資料的讀寫命令,仍然是單執行緒處理。

Redis的請求過程

三、Redis安裝部署

1.編譯安裝redis

#準備工作
systemctl stop firewalld
setenforce 0
#安裝依賴包
yum install -y gcc-c++ make
cd /opt/
#把解壓包放在opt下並解壓
tar zxvf redis-5.0.7.tar.gz
cd /opt/redis-5.0.7/
make
#編譯安裝指定安裝目錄
make PREFIX=/usr/local/redis install
#由於Redis原始碼包中直接提供了Makefile檔案,所以在解壓完軟體包後,不用先執行./configure進行設定,可直接執行make與make install命令進行安裝

2.執行軟體包自帶的install_server.sh指令碼檔案設定redis服務相關設定

cd /opt/redis-5.0.7/utils
./install_server.sh
#慢慢回車
Selected config:
Port #第一個設定預設偵聽埠6379
Config file #第二個設定組態檔路徑/etc/redis/6379.conf
Log file#第三個設定紀錄檔檔案路徑/var/log/redis_6379.log
Data dir#第四個設定資料檔案目錄/var/lib/redis/6379(持久化檔案在這裡)
Executable#第五個設定Redis執行命令的路徑手動設定一下/usr/local/redis/bin/redis-server
Cli Executable#使用者端命令工具/usr/local/bin/redis-cli

3.把redis的可執行程式放入路徑環境變數的目錄便於系統識別

#做個軟連線
ln -s /usr/local/redis/bin/* /usr/local/bin/
#當install_server.sh 指令碼執行完畢,Redis服務就已經啟動,預設偵聽埠為6379
netstat -natp | grep redis

#redis服務控制
/etc/init.d/redis_6379 stop				#停止
/etc/init.d/redis_6379 start			#啟動
/etc/init.d/redis_6379 restart			#重啟
/etc/init.d/redis_6379 status			#狀態

4.修改設定/etc/redis/6379.conf

vim /etc/redis/6379.conf

#第70行;監聽的主機地址
bind 127.0.0.1 192.168.239.40
#93行;Redis預設的監聽埠
port 6379									
#137行;啟用守護行程
daemonize yes							
#159行;指定 PID 檔案
pidfile /var/run/redis_6379.pid				
#167行;紀錄檔級別
loglevel notice								
#172行;指定紀錄檔檔案
logfile /var/log/redis_6379.log	

/etc/init.d/redis_6379 restart
netstat -natp | grep redis

四、Redis命令工具

redis-server		用於啟動 Redis 的工具
redis-benchmark		用於檢測 Redis 在本機的執行效率
redis-check-aof		修復 AOF 持久化檔案
redis-check-rdb		修復 RDB 持久化檔案
redis-cli	 		Redis命令列工具

1.redis-cli命令列工具

#語法:redis-cli -h host -p port -a password

-h	指定遠端主機
-p	指定 Redis 服務的埠號
-a	指定密碼,未設定資料庫密碼可以省略-a 選項
#若不新增任何選項表示,則使用 127.0.0.1:6379 連線本機上的 Redis 資料庫
#例:
redis-cli -h 192.168.239.40 -p 6379
#此時無密碼,不需要-a直接登陸

2.redis-benchmark測試工具

redis-benchmark 是官方自帶的Redis效能測試工具,可以有效的測試Redis服務的效能。

基本的測試語法:redis-benchmark [選項] [選項值]
選項 引數
-h 指定伺服器主機名
-p 指定伺服器埠
-s 指定伺服器socket
-c 指定並行連線數
-n 指定請求數
-d 以位元組的形式指定 SET/GET值的資料大小
-k 1=keep alive 0=reconnect
-r SET/GET/INCR 使用隨機 key,SADD使用隨機值
-p 通過管道傳輸請求
-q 強制退出redis。僅顯示query/sec的值
-csv 以CSV格式輸出
-l 生成迴圈,永久執行測試
-t 僅執行以逗號分隔的測試命令列表
-i Idle 模式。僅開啟N個idle連線並等待
  • 向IP地址為192.168.239.40、埠為6379的Redis伺服器傳送100個並行連線和100000個請求測試效能
redis-benchmark -h 192.168.239.40 -p 6379 -c 100 -n 100000
  • 測試存取大小為100位元組的封包的效能
redis-benchmark -h 192.168.239.40 -p 6379 -q -d 100
  • 測試本機上Redis服務在進行set與lpush操作時的效能
redis-benchmark -t set,lpush -n 100000 -q

3.Redis資料庫常用命令

1、set/get存放/獲取資料

set		存放資料,命令格式為 set key value   #set 鍵  鍵所對應的值
get		獲取資料,命令格式為 get key         #get 鍵
#例子:
redis-cli -p 6379
192.168.239.40:6379> set name Davin
OK
192.168.239.40:6379> get name
"Davin"

2、 keys 取值

keys 命令可以取符合規則的鍵值列表,通常情況可以結合*、?等選項來使用
127.0.0.1:6379> set k1 1
OK
127.0.0.1:6379> set k2 2
OK
127.0.0.1:6379> set k3 3
OK
127.0.0.1:6379> set k4 4
OK
127.0.0.1:6379> set k5 5
OK
127.0.0.1:6379> set v1 6
OK
127.0.0.1:6379> set v22 7
OK
keys *   #檢視當前Redis資料庫中有多少個鍵 
keys k*  #檢視以k為開頭的鍵(0個或者多個任意字元)
keys k?  #檢視以k為開頭(1個任意字元)
keys v?? #檢視以v開頭且後面2個任意字元

3、 exists 判斷值是否存在

127.0.0.1:6379> EXISTS name
(integer) 1                    #1表示teacher鍵存在
127.0.0.1:6379> EXISTS ww
(integer) 0                    #0表示teacher不存在

4、 del刪除當前資料庫指定key

del  命令可以刪除當前資料庫指定key
127.0.0.1:6379> del k1 k2
(integer) 2
127.0.0.1:6379> KEYS k?
1) "k3"
2) "k5"
3) "k4"
127.0.0.1:6379> EXISTS k1
(integer) 0
127.0.0.1:6379> EXISTS k2
(integer) 0

5、 type獲取值的型別

type  命令可以獲取 key 對應 value 值型別
#例
1、
192.168.239.40:6379> TYPE name
string
2、
192.168.239.40:6379> hset myhash field1 "zhang"
(integer) 1
192.168.239.40:6379> TYPE myhash
hash

6、 rename重新命名

rename:命令是對已有key進行重新命名。(覆蓋)
命令格式:rename 源key 目標key

使用rename命令進行重新命名時,無論目標key是否存在都進行重新命名,且源key的值會覆蓋目標key的值。在實際使用過程中,建議先用 exists 命令檢視目標 key 是否存在,然後再決定是否執行 rename 命令,以避免覆蓋重要資料。

192.168.239.40:6379> get v22
"7"
192.168.239.40:6379> RENAME v22 v2 #直接改名,不存在v2
OK
192.168.239.40:6379> KEYS *
 1) "myhash"
 2) "k5"
 3) "v1"
 4) "k3"
 5) "k4"
 6) "counter:__rand_int__"
 7) "myset:__rand_int__"
 8) "v2"
 9) "key:__rand_int__"
10) "mylist"
11) "name"
192.168.239.40:6379> get v22  #返回空值
(nil)
192.168.239.40:6379> get v2  #
"7"
192.168.239.40:6379> get v1
"6"
192.168.239.40:6379> RENAME v2 v1
OK
192.168.239.40:6379> KEYS *
 1) "myhash"
 2) "k5"
 3) "v1"
 4) "k3"
 5) "k4"
 6) "counter:__rand_int__"
 7) "myset:__rand_int__"
 8) "key:__rand_int__"
 9) "mylist"
10) "name"
192.168.239.40:6379> get v1
"7"

7、 renamenx重新命名(不覆蓋)

renamenx 命令的作用是對已有 key 進行重新命名,並檢測新名是否存在,如果目標 key 存在則不進行重新命名。(不覆蓋)
命令格式:renamenx 源key 目標key
192.168.239.40:6379> get v1
"7"
192.168.239.40:6379> get k3
"3"
192.168.239.40:6379> RENAMENX v1 k3
(integer) 0          #renamenx重新命名,如果新名存在,則不執行重新命名
192.168.239.40:6379> get k3
"3"
192.168.239.40:6379> get v1
"7"

8、 dbsize 檢視庫中key的數量

dbsize 命令的作用是檢視當前資料庫中 key 的數目
192.168.239.40:6379> DBSIZE
(integer) 10

9、 設定密碼

使用config set requirepass password命令設定密碼
使用config get requirepass命令檢視密碼(一旦設定密碼,必須先驗證通過密碼,否則所有操作不可用)
#例
192.168.239.40:6379> config set requirepass 123456
OK
192.168.239.40:6379> get name
(error) NOAUTH Authentication required.
192.168.239.40:6379> auth 123456
OK
192.168.239.40:6379> get name
"Davin"
192.168.239.40:6379> quit
[root@localhost ~]# redis-cli -h 192.168.239.40 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.239.40:6379> KEYS *
 1) "myhash"
 2) "k5"
 3) "v1"
 4) "k3"
 5) "k4"
 6) "counter:__rand_int__"
 7) "myset:__rand_int__"
 8) "key:__rand_int__"
 9) "mylist"
10) "name"
192.168.239.40:6379> CONFIG GET requirepass  #檢視當前密碼
1) "requirepass"
2) "123456"

192.168.239.40:6379> config set requirepass ''#設定空密碼
OK
192.168.239.40:6379> CONFIG GET requirepass
1) "requirepass"
2) ""

4.Redis多資料庫常用命令

  • Redis支援多資料庫,Redis預設情況下包含16個資料庫,資料庫名稱時用數位0-15來依次命名的。多資料庫相互獨立,互不干擾。

(1)多資料庫間切換

命令格式:select 序號
使用 redis-cli 連線 Redis 資料庫後,預設使用的是序號為 0 的資料庫。
192.168.239.40:6379> select 10
OK
192.168.239.40:6379[10]> KEYS *
(empty list or set)
192.168.239.40:6379[10]> SELECT 15
OK
192.168.239.40:6379[15]> SELECT 0
OK
192.168.239.40:6379> KEYS *
 1) "myhash"
 2) "k5"
 3) "v1"
 4) "k3"
 5) "k4"
 6) "counter:__rand_int__"
 7) "myset:__rand_int__"
 8) "key:__rand_int__"
 9) "mylist"
10) "name"

(2)多資料庫間行動資料

格式:move 鍵值 序號

192.168.239.40:6379> move v1 10   #從0移動到10
(integer) 1
192.168.239.40:6379> SELECT 10    #切換到10
OK
192.168.239.40:6379[10]> KEYS *   #檢視所有的鍵
1) "v1"
192.168.239.40:6379[10]> get v1   #檢視v1鍵的值
"7"
192.168.239.40:6379[10]> SELECT 0 #切回0
OK
192.168.239.40:6379> get v1       #檢視v1值 為空
(nil)

(3)清除資料庫內資料

FLUSHDB :清空當前資料庫資料
FLUSHALL :清空所有資料庫的資料,慎用!

192.168.239.40:6379> SELECT 10    
OK
192.168.239.40:6379[10]> KEYS *
1) "v1"
192.168.239.40:6379[10]> set v2 20
OK
192.168.239.40:6379[10]> set v3 30
OK
192.168.239.40:6379[10]> KEYS *
1) "v2"
2) "v3"
3) "v1"
192.168.239.40:6379[10]> FLUSHDB   #清空當前資料庫
OK
192.168.239.40:6379[10]> KEYS *
(empty list or set)
192.168.239.40:6379[10]> SELECT 0
OK
192.168.239.40:6379> KEYS *
1) "myhash"
2) "k5"
3) "k3"
4) "k4"
5) "counter:__rand_int__"
6) "myset:__rand_int__"
7) "key:__rand_int__"
8) "mylist"
9) "name"
192.168.239.40:6379> SELECT 10
OK
192.168.239.40:6379[10]> set v2 20
OK
192.168.239.40:6379[10]> set v3 30
OK
192.168.239.40:6379[10]> KEYS *
1) "v2"
2) "v3"
192.168.239.40:6379[10]> FLUSHALL  #清空所有的資料庫資料
OK
192.168.239.40:6379[10]> KEYS *
(empty list or set)
192.168.239.40:6379[10]> SELECT 0
OK
192.168.239.40:6379> KEYS *
(empty list or set)

五、Redis高可用

在web伺服器中,高可用是指伺服器可以正常存取的時間,衡量的標準是在多長時間內可以提供正常服務(99.9%、99.99%、99.999%等等)。 但是在Redis語境中,高可用的含義似乎要寬泛一些,除了保證提供正常服務(如主從分離、快速容災技術),還需要考慮資料容量的擴充套件、資料安全不會丟失等。

在Redis中,實現高可用的技術主要包括持久化、主從複製、哨兵和叢集,下面分別說明它們的作用,以及解決了什麼樣的問題 。

  • 持久化:持久化是最簡單的高可用方法(有時甚至不被歸為高可用的手段),主要作用是資料備份,即將資料儲存在硬碟,保證資料不會因程序退出而丟失。

  • 主從複製:從複製是高可用Redis的基礎,哨兵和叢集都是在主從複製基礎上實現高可用的。主從複製主要實現了資料的多機備份,以及對於讀操作的負載均衡和簡單的故障恢復。

    • 缺陷:故障恢復無法自動化;寫操作無法負載均衡;儲存能力受到單機的限制。
  • 哨兵:在主從複製的基礎上,哨兵實現了自動化的故障恢復。

    • 缺陷:寫操作無法負載均衡;儲存能力受到單機的限制。
  • cluster叢集:通過叢集,Redis解決了寫操作無法負載均衡,以及儲存能力受到單機限制的問題,實現了較為完善的高可用方案。

六、Redis持久化

持久化的功能:Redis是記憶體資料庫,資料都是儲存在記憶體中,為了避免伺服器斷電等原因導致Redis程序異常退出後資料的永久丟失,需要定期將Redis中的資料以某種形式(資料或命令)從記憶體儲存到硬碟;當下次Redis重啟時,利用持久化檔案實現資料恢復。除此之外,為了進行災難備份,可以將持久化檔案拷貝到一個遠端位置。

Redis 提供兩種方式進行持久化

  • RDB 持久化:原理是將 Reids在記憶體中的資料庫記錄定時儲存到磁碟上。
  • AOF 持久化(append only file):原理是將 Reids 的操作紀錄檔以追加的方式寫入檔案,類似於MySQL的binlog。

總結:由於AOF持久化的實時性更好,即當程序意外退出時丟失的資料更少,因此AOF是目前主流的持久化方式,不過RDB持久化仍然有其用武之地。

1.RDB持久化

RDB持久化:指在指定的時間間隔內將記憶體中當前程序中的資料生成快照儲存到硬碟(因此也稱作快照持久化),用二進位制壓縮儲存,儲存的檔案字尾是rdb;當Redis重新啟動時,可以讀取快照檔案恢復資料。

(1)觸發條件
RDB持久化的觸發分為手動觸發自動觸發兩種。

①手動觸發

  • save命令和bgsave命令都可以生成RDB檔案。