目錄
一、關系型數據庫和非關系型數據庫
1.關系型數據庫
2.非關系型數據庫
3.關系型數據庫和非關系型數據庫區別
二、Redis
1.Redis簡介
2.Redis 的優點
3.Redis 使用場景
4.Redis的數據類型
5.哪些數據適合放入緩存中?
6.Redis為什么這么快?
三、Redis 安裝部署
四、Redis 命令工具
1.redis-cli 命令行工具
2.redis-benchmark 測試工具
3.Redis 數據庫常用命令
4.Redis 多數據庫常用命令
一、關系型數據庫和非關系型數據庫
1.關系型數據庫
●一個結構化的數據庫,創建在關系模型基礎上
●一般面向于記錄
●包括Oracle、MySQL、SQLServer、Microsoft Access、DB2等
2.非關系型數據庫
●除了主流的關系型數據庫外的數據庫,都認為是非關系型
●包括Redis、MongBD、Hbase、Memcached等
3.關系型數據庫和非關系型數據庫區別
1)數據存儲方式不同
關系型和非關系型數據庫的主要差異是數據存儲的方式。關系型數據天然就是表格式的,因此存儲在數據表的行和列中。數據表可以彼此關聯協作存儲,也很容易提取數據。
與其相反,非關系型數據不適合存儲在數據表的行和列中,而是大塊組合在一起。非關系型數據通常存儲在數據集中,就像文檔、鍵值對或者圖結構。你的數據及其特性是選擇數據存儲和提取方式的首要影響因素。
2)擴展方式不同
SQL和NoSQL數據庫最大的差別可能是在擴展方式上,要支持日益增長的需求當然要擴展。
要支持更多并發量,SQL數據庫是縱向擴展,也就是說提高處理能力,使用速度更快速的計算機,這樣處理相同的數據集就更快了。因為數據存儲在關系表中,操作的性能瓶頸可能涉及很多個表,這都需要通過提高計算機性能來克服。雖然SQL數據庫有很大擴展空間,但最終肯定會達到縱向擴展的上限。
而NoSQL數據庫是橫向擴展的。因為非關系型數據存儲天然就是分布式的,NoSQL數據庫的擴展可以通過給資源池添加更多普通的數據庫服務器(節點)來分擔負載。
3)對事務性的支持不同
關系型數據庫遵循ACID規則(原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability))。
NoSQL數據庫遵循BASE原則(基本可用(Basically Availble)、軟/柔性事務(Soft-state)、最終一致性(Eventual Consistency))。
由于關系型數據庫的數據強一致性,所以對事務的支持很好。關系型數據庫支持對事務原子性細粒度控制,并且易于回滾事務。
NoSQL數據庫是在CAP(一致性、可用性、分區容忍度)中任選兩項,因為基于節點的分布式系統中,不可能同時全部滿足,所以對事務的支持不是很好。
二、Redis
1.Redis簡介
Redis(遠程字典服務器) 是一個開源的、使用 C 語言編寫的 NoSQL 數據庫。
Redis 基于內存運行并支持持久化,采用key-value(鍵值對)的存儲形式,是目前分布式架構中不可或缺的一環。
Redis服務器程序是單進程模型,也就是在一臺服務器上可以同時啟動多個Redis進程,Redis的實際處理速度則是完全依靠于主進程的執行效率。若在服務器上只運行一個Redis進程,當多個客戶端同時訪問時,服務器的處理能力是會有一定程度的下降;若在同一臺服務器上開啟多個Redis進程,Redis在提高并發處理能力的同時會給服務器的CPU造成很大壓力。即:在實際生產環境中,需要根據實際的需求來決定開啟多少個Redis進程。若對高并發要求更高一些,可能會考慮在同一臺服務器上開啟多個進程。若CPU資源比較緊張,采用單進程即可。
2.Redis 的優點
1)具有極高的數據讀寫速度:數據讀取的速度最高可達到 110000 次/s,數據寫入速度最高可達到 81000 次/s。
2)支持豐富的數據類型:支持 key-value、Strings、Lists、Hashes、Sets 及 Sorted Sets 等數據類型操作。
3)支持數據的持久化:可以將內存中的數據保存在磁盤中,重啟的時候可以再次加載進行使用。
4)原子性:Redis 所有操作都是原子性的。
5)支持數據備份:即 master-salve 模式的數據備份。
3.Redis 使用場景
Redis作為基于內存運行的數據庫,是一個高性能的緩存,一般應用在Session緩存、隊列、排行榜、計數器、最近最熱文章、最近最熱評論、發布訂閱等。
Redis 適用于數據實時性要求高、數據存儲有過期和淘汰特征的、不需要持久化或者只需要保證弱一致性、邏輯簡單的場景。
4.Redis的數據類型
類型 | 簡介 | 特性 | 場景 |
string(字符串) | 二進制安全 | 可以包含任何數據,比如jpg圖片或者序列化對象 | ... |
hash(字典) | 鍵值對集合,即編程語言中 的map類型 | 適合存儲對象,并且可以像數據庫中的update一個屬性一樣只修改某一項屬性值 | 存儲、讀取、修改用戶屬性 |
List(列表) | 鏈表(雙向鏈表) | 增刪快,提供了操作某一元素的api | 最新消息排行;消息隊列 |
set(集合) | hash表實現,元素不重復 | 添加,刑除,查找的復雜度都是 O(1),提供了求交集,并集、差集的塌作 | 共同好友;利用唯一性:統計訪問網站的所有IP |
sorted set(有序集合) | 將set中的元素增加一個權重參數score;元素按score有序排列 | 教據插入集合時,已經進行了天然排序 | 排行榜:帶權重的消息隊列 |
5.哪些數據適合放入緩存中?
1)即時性。例如查詢最新的物流狀態信息。
2)數據一致性要求不高。例如門店信息,修改后,數據庫中已經改了,五分鐘后緩存中才是最新的,但不影響功能使用。
3)訪問量大且更新頻率不高,例如網站首頁的廣告信息,訪問量大,但是不會經常變化。
6.Redis為什么這么快?
1)Redis是一款純內存結構,避免了磁盤I/O等耗時操作。
2)Redis命令處理的核心模塊為單線程,不存在多線程切換而消耗CPU,不用考慮各種鎖的問題,不存在加鎖、釋放鎖的操作,沒有因為可能出現死鎖而導致性能消耗。
3)采用了 I/O 多路復用機制,大大提升了并發效率。
注意:在 Redis 6.0 中新增加的多線程也只是針對處理網絡請求過程采用了多線性,而數據的讀寫命令,仍然是單線程處理的。
三、Redis 安裝部署
1.環境準備
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i 's/enforcing/disabled/' /etc/selinux/config
2.修改內核參數
vim /etc/sysctl.conf
vm.overcommit_memory = 1 ? ? ? ? ? ? ? ? ? ? #內核允許超量使用內存直到用完為止,防止OOM殺死進程
net.core.somaxconn = 2048 ? ? ? ? ? ? ? ? ? ?#指定處于監聽狀態的連接請求隊列的最大長度sysctl -p
3.安裝redis
這里需要提前準備redis-7.0.9.tar.gz安裝包
yum install -y gcc gcc-c++ maketar zxvf /opt/redis-7.0.9.tar.gz -C /opt/
cd /opt/redis-7.0.9
make
make PREFIX=/usr/local/redis install
#由于Redis源碼包中直接提供了 Makefile 文件,所以在解壓完軟件包后,不用先執行 ./configure 進行配置,可直接執行 make 與 make install 命令進行安裝。
4.創建redis工作目錄
mkdir /usr/local/redis/{conf,log,data}cp /opt/redis-7.0.9/redis.conf /usr/local/redis/conf/useradd -M -s /sbin/nologin redis
chown -R redis.redis /usr/local/redis/
5.環境變量
vim /etc/profile?
PATH=$PATH:/usr/local/redis/bin?? ??? ?#增加一行source /etc/profile
6.修改配置文件
vim /usr/local/redis/conf/redis.confbind 127.0.0.1 192.168.80.10?? ??? ??? ??? ??? ?#87行,添加 監聽的主機地址
protected-mode no?? ??? ??? ??? ??? ?#111行,將本機訪問保護模式設置no。如果開啟了,那么在沒有設定bind ip且沒有設密碼的情況下,Redis只允許接受本機的響應
port 6379?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?#138行,Redis默認的監聽6379端口
daemonize yes?? ??? ??? ??? ??? ??? ??? ??? ??? ?#309行,設置為守護進程,后臺啟動
pidfile /usr/local/redis/log/redis_6379.pid?? ??? ?#341行,指定 PID 文件
logfile "/usr/local/redis/log/redis_6379.log"?? ?#354行,指定日志文件
dir /usr/local/redis/data?? ??? ??? ??? ??? ??? ?#504行,指定持久化文件所在目錄
requirepass abc123?? ??? ??? ??? ??? ??? ??? ??? ?#1037行,增加一行,設置redis密碼
7.定義systemd服務管理腳本
vim /usr/lib/systemd/system/redis-server.service
[Unit]
Description=Redis Server
After=network.target[Service]
User=redis
Group=redis
Type=forking
TimeoutSec=0
PIDFile=/usr/local/redis/log/redis_6379.pid
ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true[Install]
WantedBy=multi-user.target
8.啟動服務
systemctl start redis-server
systemctl enable redis-servernetstat -lntp | grep 6379
四、Redis 命令工具
redis-server:Redis 服務器啟動命令
redis-benchmark:性能測試工具,用于檢測 Redis 在本機的運行效率
redis-check-aof:修復有問題的 AOF 持久化文件
redis-check-rdb:修復有問題的 RDB 持久化文件
redis-cli:Redis 客戶端命令行工具
redis-sentinel:Redis 哨兵集群使用
1.redis-cli 命令行工具
語法:redis-cli -h host -p port [-a password]
-h :指定遠程主機
-p :指定 Redis 服務的端口號
-a :指定密碼,未設置數據庫密碼可以省略-a 選項
若不添加任何選項表示,則使用 127.0.0.1:6379 連接本機上的 Redis 數據庫
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 :通過管道傳輸<numreq>請求。
-q :強制退出 redis。僅顯示 query/sec 值。
--csv :以 CSV 格式輸出。
-l :生成循環,永久執行測試。
-t :僅運行以逗號分隔的測試命令列表。
-I :Idle 模式。僅打開 N 個 idle 連接并等待。
#向 IP 地址為 192.168.80.10、端口為 6379 的 Redis 服務器發送 100 個并發連接與 100000 個請求測試性能
redis-benchmark -h 192.168.80.10 -p 6379 -c 100 -n 100000#測試存取大小為 100 字節的數據包的性能
redis-benchmark -h 192.168.80.10 -p 6379 -q -d 100#測試本機上 Redis 服務在進行 set 與 lpush 操作時的性能
redis-benchmark -t set,lpush -n 100000 -q
3.Redis 數據庫常用命令
set:存放數據,命令格式為 set key value
get:獲取數據,命令格式為 get key
1)keys 命令可以取符合規則的鍵值列表,通常情況可以結合*、?等選項來使用。
127.0.0.1:6379> set k1 1
127.0.0.1:6379> set k2 2
127.0.0.1:6379> set k3 3
127.0.0.1:6379> set v1 4
127.0.0.1:6379> set v5 5
127.0.0.1:6379> set v22 5
127.0.0.1:6379> KEYS *? ? ? ? ? #查看當前數據庫中所有鍵
127.0.0.1:6379> KEYS v*? ? ? ? ?#查看當前數據庫中以 v 開頭的數據
127.0.0.1:6379> KEYS v?? ? ? ??#查看當前數據庫中以 v 開頭后面包含任意一位的數據
127.0.0.1:6379> KEYS v???? ???#查看當前數據庫中以 v 開頭 v 開頭后面包含任意兩位的數據
2)exists 命令可以判斷鍵值是否存在。
127.0.0.1:6379> exists teacher?? ??? ?#判斷 teacher 鍵是否存在
(integer) 1?? ??? ??? ??? ??? ??? ??? ?# 1 表示 teacher 鍵是存在
127.0.0.1:6379> exists tea
(integer) 0?? ??? ??? ??? ??? ??? ??? ?# 0 表示 tea 鍵不存在
3)del 命令可以刪除當前數據庫的指定 key。
127.0.0.1:6379> keys *
127.0.0.1:6379> del v5
127.0.0.1:6379> get v5
4)type 命令可以獲取 key 對應的 value 值類型。
127.0.0.1:6379> type k1
string
5)expire 命令可以為已存在的 key 設置過期時間
127.0.0.1:6379> expire k1 10?? ??? ?#設置 k1 鍵的過期時間為 10 秒
6)ttl 命令可以查看 key 還有多少秒過期,-1表示永不過期,-2表示已過期
127.0.0.1:6379> ttl k1
7)expire 命令創建 key 和 值,并設置過期時間
127.0.0.1:6379> setex k11 15 hello
8)rename 命令是對已有 key 進行重命名。(覆蓋)
命令格式:rename 源key 目標key
注意:使用rename命令進行重命名時,無論目標key是否存在都進行重命名,且源key的值會覆蓋目標key的值。在實際使用過程中,建議先用 exists 命令查看目標 key 是否存在,然后再決定是否執行 rename 命令,以避免覆蓋重要數據。
127.0.0.1:6379> keys v*
1) "v1"
2) "v22"
127.0.0.1:6379> rename v22 v2
OK
127.0.0.1:6379> keys v*
1) "v1"
2) "v2"
127.0.0.1:6379> get v1
"4"
127.0.0.1:6379> get v2
"5"
127.0.0.1:6379> rename v1 v2
OK
127.0.0.1:6379> get v1
(nil)
127.0.0.1:6379> get v2
"4"
9)renamenx 命令的作用是對已有 key 進行重命名,并檢測新名是否存在,如果目標 key 存在則不進行重命名。(不覆蓋)
命令格式:renamenx 源key 目標key
127.0.0.1:6379> keys *
127.0.0.1:6379> get teacher
"zhangsan"
127.0.0.1:6379> get v2
"4"
127.0.0.1:6379> renamenx v2 teacher
(integer) 0
127.0.0.1:6379> keys *
127.0.0.1:6379> get teacher
"zhangsan"
127.0.0.1:6379> get v2
"4"
10)dbsize 命令的作用是查看當前數據庫中 key 的數目。
127.0.0.1:6379> dbsize
11)使用config set requirepass yourpassword命令設置密碼
127.0.0.1:6379> config set requirepass 123456
12)使用config get requirepass命令查看密碼(一旦設置密碼,必須先驗證通過密碼,否則所有操作不可用)
127.0.0.1:6379> auth 123456
127.0.0.1:6379> config get requirepass
4.Redis 多數據庫常用命令
Redis 支持多數據庫,Redis 默認情況下包含 16 個數據庫,數據庫名稱是用數字 0-15 來依次命名的。
多數據庫相互獨立,互不干擾。
1)多數據庫間切換
命令格式:select 序號
注意:使用 redis-cli 連接 Redis 數據庫后,默認使用的是序號為 0 的數據庫。
127.0.0.1:6379> select 10?? ??? ??? ?#切換至序號為 10 的數據庫
127.0.0.1:6379[10]> select 15?? ??? ?#切換至序號為 15 的數據庫
127.0.0.1:6379[15]> select 0?? ??? ??? ?#切換至序號為 0 的數據庫
2)多數據庫間移動數據
格式:move 鍵名 序號
127.0.0.1:6379> set k1 100
OK
127.0.0.1:6379> get k1
"100"
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> get k1
(nil)
127.0.0.1:6379[1]> select 0?? ??? ??? ?#切換至目標數據庫 0
OK
127.0.0.1:6379> get k1?? ??? ??? ??? ?#查看目標數據是否存在
"100"
127.0.0.1:6379> move k1 1?? ??? ??? ?#將數據庫 0 中 k1 移動到數據庫 1 中
(integer) 1
127.0.0.1:6379> select 1?? ??? ??? ??? ?#切換至目標數據庫 1
OK
127.0.0.1:6379[1]> get k1?? ??? ??? ?#查看被移動數據
"100"
127.0.0.1:6379[1]> select 0
OK
127.0.0.1:6379> get k1?? ??? ??? ??? ?#在數據庫 0 中無法查看到 k1 的值
(nil)
3)清除數據庫內數據
FLUSHDB :清空當前數據庫數據
FLUSHALL :清空所有數據庫的數據,慎用!