Redis(Remote Dictionary Server) 是一個使用 C 語言編寫的,開源的(BSD許可)高性能非關系型(NoSQL)的鍵值對數據庫。
本篇內容包括:Redis 簡介(為什么快?為什么單線程?優點,缺點等),Redis 在 Java Web 中的應用,Redis 安裝(Win、Linux、Mac 場景下的安裝)等內容
文章目錄
- 一、Redis 簡介
- 1、Redis為什么快呢?
- 2、Redis為何選擇單線程?
- 3、那為什么Redis6.0之后又改用多線程呢?
- 4、Redis的優勢
- 5、Redis的缺點
- 二、Redis 在 Java Web 中的應用
- 1、Redis 的使用場景
- 2、緩存
- 3、高速讀/寫的場合
- 三、Redis 安裝
- 1、Windows 下安裝
- 2、Linux 下安裝
- 3、Mac 下安裝(使用Homebrew)
一、Redis 簡介
Redis 是 C 語言開發的一個開源的(遵從 BSD 協議)高性能鍵值對(key-value)的內存數據庫,可以用作數據庫、緩存、消息中間件等。
它是一種 NoSQL(not-only sql,泛指非關系型數據庫)的數據庫。是一種基于內存的數據庫,并且提供一定的持久化功能。
Redis 作為一個內存數據庫:性能優秀,數據在內存中,讀寫速度非常快,支持并發 10W QPS。單進程單線程,是線程安全的,采用 IO 多路復用機制。豐富的數據類型,支持字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。支持數據持久化。可以將內存中數據保存在磁盤中,重啟時加載。主從復制,哨兵,高可用。可以用作分布式鎖。可以作為消息中間件使用,支持發布訂閱。
1、Redis為什么快呢?
redis的速度非常的快,單機的redis就可以支撐每秒10幾萬的并發,相對于mysql來說,性能是mysql的幾十倍。速度快的原因主要有幾點:
- 完全基于內存操作
- C語言實現,優化過的數據結構,基于幾種基礎的數據結構,redis做了大量的優化,性能極高
- 使用單線程,無上下文的切換成本
- 基于非阻塞的IO多路復用機制
2、Redis為何選擇單線程?
- 避免過多的上下文切換開銷。程序始終運行在進程中單個線程內,沒有多線程切換的場景。
- 避免同步機制的開銷:如果 Redis選擇多線程模型,需要考慮數據同步的問題,則必然會引入某些同步機制,會導致在操作數據過程中帶來更多的開銷,增加程序復雜度的同時還會降低性能。
- 實現簡單,方便維護:如果 Redis使用多線程模式,那么所有的底層數據結構的設計都必須考慮線程安全問題,那么 Redis 的實現將會變得更加復雜。
3、那為什么Redis6.0之后又改用多線程呢?
Redis 使用多線程并非是完全摒棄單線程,Redis 還是使用單線程模型來處理客戶端的請求,只是使用多線程來處理數據的讀寫和協議解析,執行命令還是使用單線程。
這樣做的目的是因為redis的性能瓶頸在于網絡 IO 而非 CPU,使用多線程能提升 IO 讀寫的效率,從而整體提高 Redis 的性能。
4、Redis的優勢
- Redis支持保存多種數據結構(支持string,list,set,sorted set,hash),其單個value的最大限制是1GB,因此Redis可以用來實現很多有用的功能;
- 因為是純內存操作,Redis的性能非常出色,每秒可以處理超過 10萬次讀寫操作,是已知性能最快的Key-Value DB;
- Redis也可以對存入的Key-Value設置expire時間,因此也可以被當作一 個功能加強版的memcached來用;
- Redis可以將內存的數據利用快照和日志的形式保存到硬盤上,這樣在發生類似斷電或者機器故障的時 候,內存中的數據不會“丟失”;
- 除了上述功能以外,Redis還提供了鍵過期、發布訂閱、事務、流水線、Lua腳本等附加功能。
5、Redis的缺點
Redis的主要缺點是數據庫容量受到物理內存的限制,不能用作海量數據的高性能讀寫,因此Redis適合的場景主要局限在較小數據量的高性能操作和運算上。
總之,如果在合適的場景使用好Redis,它就會像一把瑞士軍刀一樣所向披靡、無往不利!!!
二、Redis 在 Java Web 中的應用
1、Redis 的使用場景
Redis 根據使用數據類型的不同,對應的使用場景有很多,例如:
- 緩存(String / Hash 類型):緩存如用戶信息,視頻信息等;
- 分布式鎖(String 類型):setnx 方法,「key不存在才插入」,可以用它來實現分布式鎖;
- 計數器(String 類型):incr/decr 方法,自增自減,由于是原子性,可以用來計數統計瀏覽數、點贊數等;
- 限制請求次數(String 類型):也是利用 incr 方法,限制請求次數訪問者的 ip 和其他信息作為 key,訪問一次增加一次計數,超過次數則返回 false;
- 數據共享分布式(String 類型):因為 Redis 是分布式的獨立服務,可以在多個應用之間共享,所有可以實現需要例如分布式 Session;
- 購物車(Hash 類型):類似存儲商品信息,大 key 為商家 id,小 key 是商品 id 即 goodsId,value 為該 goodsId 的詳細信息;
- 消息隊列(List / Stream 類型):二者都可以實現消息隊列,而 Redis5.0 新增的 Stream,解決了 List 實現的消息隊列不能持久化和不能重復消費的問題;
- 點贊、踩、收藏(Set 類型):Set 集合無需、不可重復,可以保證一個用戶只能點一個贊;
- 共同關注(Set 類型):Set 類型支持交集運算,所以可以用來計算共同關注的好友、公眾號等;
- 抽獎活動(Set 類型):存儲某活動中中獎的用戶名 ,Set 類型因為有去重功能,可以保證同一個用戶不會中獎兩次;
- 排行榜(ZSet 類型):有序集合保留了集合不能有重復成員的特性(分值可以重復),但不同的是,有序集合中的元素可以排序,所以可以用作排行榜功能的實現;
- 此外利用 Redis 的特殊數據類型也可以實現一些相應的功能:Bit 位運算用來簽到統計、HyperLogLogs 統計基數用來百萬級網絡 UV,還有 GEO 地理位置、用來打車等;
2、緩存
在日常對數據庫的訪問中,讀操作的次數遠超寫操作,比例大概在 1:9
到 3:7
,所以需要讀的可能性是比寫的可能大得多的。當我們使用SQL語句去數據庫進行讀寫操作時,數據庫就會去磁盤把對應的數據索引取回來,這是一個相對較慢的過程。
如果我們把數據放在 Redis 中,既直接放在內存之中,讓服務端直接去讀取內存中的數據,那么這樣速度明顯就會快上不少,并且會極大減小數據庫的壓力,但是使用內存進行數據存儲開銷也是比較大的,限于成本的原因,一般我們只是使用 Redis 存儲一些常用和主要的數據,比如用戶登錄的信息等。
一般而言在使用 Redis 進行存儲的時候,我們需要從以下幾個方面來考慮:
- 業務數據常用嗎?命中率如何?如果命中率很低,就沒有必要寫入緩存;
- 該業務數據是讀操作多,還是寫操作多?如果寫操作多,頻繁需要寫入數據庫,也沒有必要使用緩存;
- 業務數據大小如何?如果要存儲幾百兆字節的文件,會給緩存帶來很大的壓力,這樣也沒有必要。
在考慮了這些問題之后,如果覺得有必要使用緩存,那么就使用它!
使用 Redis 作為緩存的讀取邏輯如下圖所示:
從上圖我們可以知道以下兩點:
- 當第一次讀取數據的時候,讀取 Redis 的數據就會失敗,此時就會觸發程序讀取數據庫,把數據讀取出來,并且寫入 Redis 中;
- 當第二次以及以后需要讀取數據時,就會直接讀取 Redis,讀到數據后就結束了流程,這樣速度就大大提高了。
從上面的分析可以知道,讀操作的可能性是遠大于寫操作的,所以使用 Redis 來處理日常中需要經常讀取的數據,速度提升是顯而易見的,同時也降低了對數據庫的依賴,使得數據庫的壓力大大減少。
使用 Redis 作為緩存的寫入邏輯如下圖所示:
從流程可以看出,更新或者寫入的操作,需要多個 Redis 的操作,如果業務數據寫次數遠大于讀次數那么就沒有必要使用 Redis。
3、高速讀/寫的場合
在如今的互聯網中,越來越多的存在高并發的情況,比如天貓雙11、搶紅包、搶演唱會門票等,這些場合都是在某一個瞬間或者是某一個短暫的時刻有成千上萬的請求到達服務器,如果單純的使用數據庫來進行處理,就算不崩,也會很慢的,輕則造成用戶體驗極差用戶量流失,重則數據庫癱瘓,服務宕機,而這樣的場合都是不允許的!
所以我們需要使用 Redis 來應對這樣的高并發需求的場合,我們先來看看一次請求操作的流程圖:
我們來進一步闡述這個過程:
- 當一個請求到達服務器時,只是把業務數據在 Redis 上進行讀寫,而沒有對數據庫進行任何的操作,這樣就能大大提高讀寫的速度,從而滿足高速響應的需求;
- 但是這些緩存的數據仍然需要持久化,也就是存入數據庫之中,所以在一個請求操作完 Redis 的讀/寫之后,會去判斷該高速讀/寫的業務是否結束,這個判斷通常會在秒殺商品為0,紅包金額為 0 時成立,如果不成立,則不會操作數據庫;如果成立,則觸發事件將 Redis 的緩存的數據以批量的形式一次性寫入數據庫,從而完成持久化的工作。
三、Redis 安裝
1、Windows 下安裝
-
官方沒有 Windows版本的 Redis
-
Windows版本下載地址:https://github.com/MicrosoftArchive/redis/releases,下載 Redis-x64-3.2.100.msi
-
雙擊剛下載好的msi格式的安裝包(Redis-x64-3.2.100.msi):
-
開始安裝
-
選擇“同意協議”,點擊下一步繼續:
-
選擇“添加Redis目錄到環境變量PATH中”,這樣方便系統自動識別Redis執行文件在哪里:
-
端口號可保持默認的6379,并選擇防火墻例外,從而保證外部可以正常訪問Redis服務:
-
設定最大值為100M。作為實驗和學習,100M足夠了:
-
-
右擊“計算機”>選擇“管理”。在左側欄中依次找到并點擊“計算機管理(本地)”> 服務和應用程序 > 服務。再在右側找到Redis名稱的服務,查看啟動情況。如未啟動,則手動啟動之。正常情況下,服務應該正常啟動并運行了
-
最后來測試一下 Redis 是否正常提供服務。進入 Redis 的目錄使用
cmd
。輸入redis-cli
并回車。(redis-cli是客戶端程序)如圖正常提示進入,并顯示正確端口號,則表示服務已經啟動 -
實際測試一下讀寫。輸入
set mykey1 "I love you all!"
并回車,用來保存一個鍵值。再輸入get mykey1
,獲取剛才保存的鍵值
2、Linux 下安裝
-
Redis官網 https://redis.io/ 直接點擊下載得到:redis-6.2.4.tar.gz
-
把 redis-6.2.4.tar.gz 移動到/usr/local/ 目錄下 :
mv redis-6.2.4.tar.gz /usr/local/
-
解壓 redis-6.2.4.tar.gz :
tar -zxvf redis-6.2.4.tar.gz
-
由于redis是由C語言編寫的,它的運行需要C環境,因此我們需要先安裝gcc :
yum install gcc-c++
-
進入到 /usr/local/redis-6.2.4/ 目錄下,進行編譯與安裝 :
cd redis-6.2.4
、make
、cd ./src
、make install
-
Redis不是默認后臺啟動的,需要求改一下配置文件:
vi redis.conf
將daemonize
屬性改為yes
-
編輯 redis.conf配置文件,開啟redis遠程訪問服務:
- 配置文件中的
bind 127.0.0.1
這一行給注釋掉,這里的bind指的是只有指定的網段才能遠程訪問這個redis,注釋掉后,就沒有這個限制了 - 配置文件中的
protected-mode
設置成no
(默認是設置成yes的, 防止了遠程訪問,在redis3.2.3版本后)
- 配置文件中的
-
啟動redis服務:
redis-server redis.conf
-
啟動redis客戶端服務:
redis-cli -p 6379
-
打開RedisDesktopManager,測試服務是否開啟 以及 是否可以遠程訪問Redis\
3、Mac 下安裝(使用Homebrew)
- 沒有安裝Homebrew,首先安裝npm國內的吧,快一些:
/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"
; - 使用Homebrew安裝命令:
brew install redis
; - 查看安裝及配置文件位置:
- Homebrew安裝的軟件會默認在
/usr/local/Cellar/
路徑下 - redis的配置文件
redis.conf
存放在/usr/local/etc
路徑下
- Homebrew安裝的軟件會默認在
- 啟動redis服務:
redis-server /usr/local/etc/redis.conf
或brew services start redis
或redis-server
- 查看redis服務進程:
ps axu | grep redis
- redis-cli連接redis服務,redis默認端口號6379,默認auth為空:
redis-cli -h 127.0.0.1 -p 6379