Redis的單機模式、主從模式、哨兵模式

一、單機模式

1. 單機模式的安裝方式

如果是CentOS,那么安裝就很簡單了,可以通過命令yum install redis -y進行安裝,如下圖所示:

image.png

然后可以通過whereis redis-server查看redis安裝在哪里;安裝完在/etc目錄下有redis.conf文件,這是一個生成的配置文件。
image.png

接下來通過一個簡單的配置之后就啟動Redis。vim /etc/redis.conf

# 綁定的網卡IP,這個默認只能通過127.0.0.1訪問,如果要公網可以訪問,則需要綁定公網的IP,或者bind 0.0.0.0;但不推薦將redis綁定公網IP,也不推薦設置root用戶啟動;一般綁定為程序可以訪問的內網IP就可以了
bind 127.0.0.1
# 端口號,如果公網可以訪問呢,不建議設置為默認的6379
port 6379
# 日志文件
logfile /data/redis/logs/redis-6379.log
# 數據文件存放的文件夾
dir /data/redis/data
# 數據文件名
dbfilename dump.rdb
# 是否為守護進行啟動
daemonize yes

簡單的配置完這些,就可以啟動redis了。因為是yum安裝的,可以直接通過下面的命令進行啟動:

redis-server /etc/redis.conf

因為是守護進程的啟動,所以不會有redis的那個圖標什么的。如果沒有使用守護進程,需要后臺啟動,可以在啟動命令后面加上&來啟動。啟動完了可以通過ps -ef|grep redis來查看進程是否存在。

那可能會有不是CentOS的系統,或者不使用yum安裝的,那可以通過下載包來進行安裝。
可以到https://redis.io/download官網上,下載下來上傳到主機上(有的主機外網不能訪問),或者直接在主機上下載。在官網上有對應的教程。

2. 單機模式在SpringBoot中的使用

單機模式在SpringBoot中的使用就非常簡單了,只需要在配置文件里配置上redis的地址、端口,有密碼就配置上密碼就可以進行連接了。連接之后可以通過StringRedisTemplate或者RedisTemplate進行訪問。注意如果用的是Linux主機,本地測試的時候需要注意bind的IP地址,以及防火墻是不是放開了對應的端口(云主機需要去查看配置安全策略)。

spring.redis.host=48.106.128.154
spring.redis.port=6379
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Test
    public void test00() {
        stringRedisTemplate.opsForValue().set("username", "hugh");
    }

二、主從復制模式

1. 主從模式配置

單節點可能會遇到節點掛掉的情況,那么就沒法用了,尤其是redis里面有數據的情況,要找回數據需要通過redis的持久化來找回數據(持久化再寫一個文來說明持久化機制)。所以可以通過主從配置來實現一個備份(當然這有缺點,待會說)。
主從配置其實很簡單,就是啟動兩個redis,配置個主從,可以是一主一從,也可以是一主多從的結構模型。因為線上環境都是有密碼的,所以模擬一個有密碼的主從模式。

配置文件和上面的單機模式的配置幾乎是一樣的,只是要改端口、數據文件幾個內容,簡要配置如下:

主配置:redis-6380.conf
bind 0.0.0.0
port 6380
logfile /data/redis/logs/redis-6380.log
dir /data/redis/data/6380
dbfilename dump.rdb
daemonize yes
# 線程
pidfile /var/run/redis_6380.pid
# 密碼
requirepass 123456

從配置1: redis-6381.conf
bind 0.0.0.0
port 6381
logfile /data/redis/logs/redis-6381.log
dir /data/redis/data/6381
dbfilename dump.rdb
daemonize yes
pidfile /var/run/redis_6381.pid
requirepass 123456
# 設置主節點和主節點密碼
slaveof 127.0.0.1 6380
masterauth 123456
# 從節點只讀
slave-read-only yes

從配置2: redis-6382.conf
bind 0.0.0.0
port 6382
logfile /data/redis/logs/redis-6382.log
dir /data/redis/data/6382
dbfilename dump.rdb
daemonize yes
pidfile /var/run/redis_6382.pid
requirepass 123456
# 設置主節點和主節點密碼
slaveof 127.0.0.1 6380
masterauth 123456
# 從節點只讀
slave-read-only yes

然后分別通過命令

redis-server /etc/redis/redis-6380.conf 
redis-server /etc/redis/redis-6381.conf 
redis-server /etc/redis/redis-6382.conf

分別啟動redis。因為我是在同一臺機子上做的,如果在多臺機子上做,需要修改設置主節點的IP,這里要注意安全策略的配置,可能端口連不上什么的。如果是不同的機子,那么多臺redis的端口設置成一樣也是可以的。
啟動之后用redis-cli連接一臺,去查看狀態

# 連接
redis-cli -h 127.0.0.1 -p 6030
# 密碼驗證
auth 123456
# 查看狀態
info replication

# 顯示的內容
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=996,lag=0
slave1:ip=127.0.0.1,port=6382,state=online,offset=996,lag=0
master_repl_offset:996
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:995

可以看到當前是角色是master,還有兩個slave。這時候在master節點存儲數據后,會同步到slave節點,但是不會從slave節點同步到master節點。

2. 主從模式切換

主從模式有哪些好處或者說使用場景呢?

  1. 我們可以實現讀寫分寫,寫數據都是往主節點去寫入,讀數據在從節點讀取。但是這必須要接受網絡延遲或者一些其他原因可能導致的主從之間數據的延遲;
  2. 讀寫都是主節點,從節點用于主節點發生故障的時候的備用節點。那么這時候問題就來了,主從模式需要我們自己去切換主從節點的角色,還要手動的修改配置文件。
    這合理嗎?這肯定不合理。有這個時間修改,可能重啟redis,持久化文件恢復都做好了(當然有一種情況是主機直接壞掉了,或者這臺主機的網絡直接不通了,這時候切到從節點還是有用的)
    那就簡單說一下怎么切換節點吧。
    現在我們假設主節點的機器直接壞掉了,也就是我們直接kill掉主節點的線程, 這時候到從節點上info replication查看狀態,發現會顯示主節點已經down了:
    image.png

    切換主節點步驟:
#1. 斷開復制
slaveof no one
#2. 從節點晉升為主節點(斷開復制后就自己切換為master了)
#3. 切換其他從節點的主節點
redis-cli -h 127.0.0.1 -p 6382
auth 123456
slaveof 127.0.0.1 6381

說了上面的主從復制,其實問題很多,比如手動的切換啊,還要去改程序啊等等,所以就有了哨兵模式,哨兵模式能實現幫我們自己察覺哪個節點掛了,并切換主節點。

三、哨兵模式(Redis Sentinel)

當主節點出現故障時,Redis Sentinel能自動完成故障發現和故障轉移,并通知應用方,從而實現真正的高可用。
Redis Sentinel是一個分布式架構,其中包含若干個Sentinel節點和Redis 數據節點,每個Sentinel節點會對數據節點和其余Sentinel節點進行監控,當 它發現節點不可達時,會對節點做下線標識。如果被標識的是主節點,它還 會和其他Sentinel節點進行“協商”,當大多數Sentinel節點都認為主節點不可 達時,它們會選舉出一個Sentinel節點來完成自動故障轉移的工作,同時會 將這個變化實時通知給Redis應用方。

Redis Sentinel與主從復制模式只是多了若干Sentinel節點,并沒有對Redis節點做特殊處理

1. 幾個名詞

主節點(master): 一個redis服務,獨立進程
從節點(slave):redis服務,獨立進程
Redis數據節點: 主節點和從節點
Sentinel節點:監控Redis的數據節點
Sentinel節點集合: 若干個Sentinel節點的抽象組合

2. 哨兵模式的部署方式
2.1 部署Redis節點

Redis節點的部署和主從模式是一樣的,可以參照上面的主從復制部署,同樣是部署一個主節點和兩個從節點。

2.2 部署Sentinel節點

Sentinel節點的配置文件都類似的,基本就是端口不同,如下所示:

# /etc/redis/sentinel-27001.conf
# 哨兵的端口
port 27001
# 綁定的IP,和redis的一樣
bind 0.0.0.0
# 放置的文件夾
dir "/data/redis/sentinel/27001"
# 守護進程啟動
daemonize yes
# 哨兵的密碼,可以和redis的配置不一樣,但是,只有redis5以后的版本才支持
# requirepass 123123
# 日志文件
logfile "/data/redis/sentinel/sentinel-27001.log"
# 意思是sentinel監控一個別名是mymaster的主節點,IP是46.115.158.124端口是6380,2則表示判斷主節點不可達需要的票數,一般是sentinel/2+1
# 這行可以配置多條,用來表示監聽多個redis主從服務
# 注意這里配置的IP地址是要程序能訪問的,要是配置個127.0.0.1是可以啟動,但是程序會訪問不了,那也是扯淡
sentinel monitor mymaster 46.115.158.124 6380 2
# redis主節點的密碼
sentinel auth-pass mymaster 123456
# 每個Sentinel節點都要通過定期發送ping命令來判斷Redis數據節點和其 余Sentinel節點是否可達,如果超過了down-after-milliseconds配置的時間且沒 有有效的回復,則判定節點不可達,單位是毫秒
sentinel down-after-milliseconds mymaster 30000
# parallel-syncs是用來限制在一次故障轉移之后,每次向新的主節 點發起復制操作的從節點個數
sentinel parallel-syncs mymaster 1
# failover-timeout通常被解釋成故障轉移超時時間
sentinel failover-timeout mymaster 180000

# /etc/redis/sentinel-27002.conf
port 27002
bind 0.0.0.0
# 放置的文件夾
dir "/data/redis/sentinel/27002"
daemonize yes
# requirepass 123123
logfile "/data/redis/sentinel/sentinel-27002.log"
sentinel monitor mymaster 46.115.158.124 6380 2
sentinel auth-pass mymaster 123456
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000

# /etc/redis/sentinel-27003.conf
port 27003
bind 0.0.0.0
# 放置的文件夾
dir "/data/redis/sentinel/27003"
daemonize yes
# requirepass 123123
logfile "/data/redis/sentinel/sentinel-27003.log"
sentinel monitor mymaster 46.115.158.124 6380 2
sentinel auth-pass mymaster 123456
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000

然后通過以下命令來啟動:

redis-sentinel /etc/redis/sentinel-27001.conf
redis-sentinel /etc/redis/sentinel-27002.conf
redis-sentinel /etc/redis/sentinel-27003.conf

這時候,整個哨兵模式就啟動了。啟動后配置文件會多一些內容,這個不用管也不用刪除。我們可以通過命令行來進行查看哨兵模式的狀態:

redis-cli -h 127.0.0.1 -p 27001 info Sentinel
# 顯示信息
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=46.115.158.124:6380,slaves=2,sentinels=3
3. 在SpringBoot使用哨兵模式

SpringBoot1.x默認使用的是Jedis作為Redis的客戶端,而在2.x已經是使用lettuce作為客戶端來連接和操作Redis。
在這里需要說明的是需要將springboot-starter-data-redis升級到2.2版本及以上,lettuce-core 升級到5.2.0及以上,這邊修飾了Sentinel密碼的一些大的問題。
SpringBoot中配置很簡單,首先將之前配置的關于單機的redis的配置全部刪掉,然后在配置文件中添加:

# sentinel的節點信息,注意端口一定要打開
spring.redis.sentinel.nodes=46.115.158.124:27001,46.115.158.124:27002,46.115.158.124:27003
# 配置的sentinel設置的別名
spring.redis.sentinel.master=mymaster
# sentinel的密碼,在上面的sentinel里面注釋的那部分;注意,redis5.x之后才支持Sentinel配置密碼,yum默認安裝的是3.x,是不支持密碼的,你配置了這個會一直報錯
# spring.redis.sentinel.password=123123
# redis 數據庫的密碼
spring.redis.password=123456

Java代碼同樣是使用RedisTemplate或者StringRedisTemplate就可以操作了:

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Test
    public void test00() {
        stringRedisTemplate.opsForValue().set("username", "hugh");
    }

這時候我們直接將6380所在的那個redis服務殺了之后,過一會(不會立即,因為有ping和判斷的時間),再去看sentinel服務,會發現主節點已經切換了:

# redis-cli -h 127.0.0.1 -p 27001 info Sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=47.105.178.104:6382,slaves=2,sentinels=3

這時候再跑測試用例,還是可以通過的。
這時候我們再把6380的節點起起來,查看狀態,會發現他已經加入了,而且是作為從節點的:

127.0.0.1:6380> info replication
# Replication
role:slave
master_host:47.105.178.104
master_port:6382
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:1
master_link_down_since_seconds:1602589760
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

四、CentOs安裝redis5.x或者6.x

剛才說到了redis5.x才支持Sentinel配置自己的密碼,而我們的在使用的時候,其實還是應該有sentinel的密碼的,所以需要配置redis的服務密碼后才能使用,但是直接能連上sentinel終歸是有點不安全的,所以還是建議升級到redis5.x版本,配置上sentinel的密碼。但是yum安裝默認是3.x的,所以找了一下5.x和6.x的安裝方式,從網上找來的,并且已經實踐過5.x可用。
步驟如下:

# 安裝redis4/5版本通過IUS存儲庫(僅支持redhat/centos)
# 1. 安裝 epel repo
yum install -y epel-release bash-completion
# 2. 安裝 IUS repo
yum install -y https://repo.ius.io/ius-release-el7.rpm https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
# 3.  安裝 redis5
yum install -y redis5
# 安裝redis6/最新版本通過 remi 存儲庫
# 1. 安裝 remix repo
wget http://rpms.remirepo.net/enterprise/remi-release-7.rpm
rpm -ivh remi-release-7.rpm
# 2. 安裝 redis6
yum --enablerepo=remi install redis

五、SpringBoot配置Sentinel錯誤匯總

  1. Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException
Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 127.0.0.1:6380
org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 127.0.0.1:6380
    at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1534)
    at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1442)
    at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1228)
    at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1211)
    at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedConnection(LettuceConnectionFactory.java:975)
    at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getConnection(LettuceConnectionFactory.java:360)

請檢查sentinel中是不是使用的127.0.0.1或者防火墻端口沒打開,sentinel和redis的端口都需要打開,并且IP地址程序和方法

  1. Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: NOAUTH Authentication required.
Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: NOAUTH Authentication required.
org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: NOAUTH Authentication required.
    at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:54)
    at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:52)
    at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:41)
    at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:44)
    at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:42)
    at org.springframework.data.redis.connection.lettuce.LettuceConnection.convertLettuceAccessException(LettuceConnection.java:273)
    at org.springframework.data.redis.connection.lettuce.LettuceStringCommands.convertLettuceAccessException(LettuceStringCommands.java:799)
    at org.springframework.data.redis.connection.lettuce.LettuceStringCommands.set(LettuceStringCommands.java:148)

請檢查是不是沒有配置redis服務的密碼:spring.redis.password=123456,或者密碼是否正確

  1. Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Cannot connect to a Redis Sentinel:
Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Cannot connect to a Redis Sentinel: [RedisURI [host='46.115.158.124', port=27001], RedisURI [host='46.115.158.124', port=27002], RedisURI [host='46.115.158.124', port=27003]]
org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Cannot connect to a Redis Sentinel: [RedisURI [host='47.105.178.104', port=27001], RedisURI [host='47.105.178.104', port=27002], RedisURI [host='47.105.178.104', port=27003]]
    at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1534)
    at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1442)
    at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1228)
    at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1211)
    at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedConnection(LettuceConnectionFactory.java:975)
    at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getConnection(LettuceConnectionFactory.java:360)
    at org.springframew

檢查是不是配置了spring.redis.sentinel.password=123123但是redis的版本是5.x一下,不支持密碼配置。

總結:
連接只需要配置spring.redis.sentinel.nodesspring.redis.sentinel.master
如果redis服務配置了密碼,則需要配置spring.redis.password
如果sentinel要配置密碼,則redis需要是5.x或以上版本,通過spring.redis.sentinel.password=123123配置

六、其他

Sentinel其實是用來容災或者處理故障的,數據存儲還是單臺機子然后進行主從復制。如果數據量更大,那么就需要接入集群來進行處理了。
之后還要在寫一個專門介紹集群的內容。
在例子中的SpringBoot是要Redis都是默認的配置,如果要定制化,則需要去閱讀源碼的配置類,然后進行一些配置,比如CatchManager等。

有什么問題,希望提出與交流

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。