springboot 與 redis 的集成、主從複製、redis集羣、redis哨兵模式

SpringBoot 整合Redis

構建springboot項目;項目結構

一、springboot整Redis

1、pom.xml文件添加redis依賴

       <!--
            說明:在SpringBoot2.x之後,原來使用的Jedis被替換爲了lettuce
            Jedis:採用的直連,多個線程操作的話,是不安全的,如果想要避免不安全的,使用Jedis pool 連接池 ! 更像BIO模式
            lettuce:採用netty,實例可以再多個線程中進行共享,不存在線程不安全的情況,可以減少線程數據了,更像NIO模式
        -->
        <!--redis 依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>

2、application.properties文件配置redis

# springboot所有的配置類,都有一個自動配置類,RedisAutoConfiguration
# 自動配置類都會綁定一個properties配置文件,RedisProperties

#配置redis
spring.redis.host=192.168.122.1
spring.redis.port=6379
spring.redis.password=redisRoot

3、在test類測試,操作redis

@SpringBootTest
class SpbApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate; //注入RedisTemplate

    @Test
    void contextLoads() {
        redisTemplate.opsForValue().set("key","studyRedis");
        String result = (String)redisTemplate.opsForValue().get("key");
        System.out.println(result);//studyRedis
    }

}

二:自定義RedisTemplate

1、創建新的包config包,並創建RedisConfig類

@Configuration
public class RedisConfig {

    //自定義RedisTemplate,固定寫法
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<String, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);

        //Json序列化配置
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        //String 的序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        //key 採用String 的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        //hash的key也採用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);

        //value序列化方式採用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //hash的value序列化採用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template;
    }
}

2、測試

@SpringBootTest
class SpbApplicationTests {

    //@Autowired
    //private RedisTemplate redisTemplate; //注入原RedisTemplate

    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate redisTemplate ;//注入自定義的RedisTemplate

    @Test
    void contextLoads() {
        redisTemplate.opsForValue().set("key","studyRedis");
        String result = (String)redisTemplate.opsForValue().get("key");
        System.out.println(result);
    }
}

三:Redis.conf詳解

 

1、配置文件unit單位對大小寫不敏感
2、多個配置文件組成一個
3、網絡配置
	bind 127.0.0.1 #綁定的ip
	protected-mode yes #保護模式
	port 6379 #端口設置
4、通用配置
daemonize yes #以守護進程的方式運行,默認爲no,需要改爲yes
pidfile /var/run/redis_6379.pid #如果以守護進程運行 ,我需要指定一個pid文件

# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel notice
logfile "" #日誌文件的位置名
databases 16 #數據庫的數量,默認16個
always-show-logo yes #是否顯示logo,默認開啓

5、快照SNAPSHOTTING:持久化是會用到,在規定的時間內,執行了多少次操作,則會持久化到文件.rdb和.aof 
#save 時間(s) 
save 900 1 #如果在900s內,至少有1個key進行了修改,就進行持久化操作
save 300 10#如果在300s內,至少有10個key進行了修改,就進行持久化操作
save 60 10000#如果在60s內,至少有1w個key進行了修改,就進行持久化操作

stop-writes-on-bgsave-error yes #持久化出錯,是否還需要繼續工作
rdbcompression yes #是否壓縮rdb文件,需要消耗CPU資源
rdbchecksum yes #保存rdb文件時,進行錯誤的檢查校驗
dir ./ #rdb 文件保存的目錄

6、REPLICATION複製(主從複製)
7、SECURITY 安全
requirepass redisRoot #設置redis密碼 :redisRoot
config set requirepass "redisRoot" #配置redis密碼
auth redisRoot #使用密碼登錄
config get requirepass #查看密碼
8、CLIENTS 限制
maxclients 10000 #最大的客戶端連接數爲1w
maxmemory <bytes> #最大內存設置
maxmemory-policy noeviction #內存到達上限之後的處理策略 
	1、volatile-lru:只對設置了過期時間的key進行LRU(默認值) 
	2、allkeys-lru : 刪除lru算法的key 
	3、volatile-random:隨機刪除即將過期key 
	4、allkeys-random:隨機刪除   
	5、volatile-ttl : 刪除即將過期的 
	6、noeviction : 永不過期,返回錯誤
	
9、APPEND ONLY MODE aof配置
appendonly no #默認是不開啓的,默認是使用rdb方式持久化,在大部分所有的情況下,rdb完全夠用
appendfilename "appendonly.aof" #持久化的文件的名字
# appendfsync always #每次修改都會同步,消耗性能
appendfsync everysec #每秒執行一次同步,可能會丟失這1s的數據
# appendfsync no #不執行同步,效率最高,一般不使用

Redis爲持久化

Redis爲持久化提供了兩種方式:

  • RDB:在指定的時間間隔能對你的數據進行快照存儲。
  • AOF:記錄每次對服務器寫的操作,當服務器重啓的時候會重新執行這些命令來恢復原始的數據。
RDB持久化配置:

# 時間策略
save 900 1
save 300 10
save 60 10000

# 文件名稱
dbfilename dump.rdb

# 文件保存路徑
dir /home/work/app/redis/data/

# 如果持久化出錯,主進程是否停止寫入
stop-writes-on-bgsave-error yes

# 是否壓縮
rdbcompression yes

# 導入時是否檢查
rdbchecksum yes
AOF的持久化配置

# 是否開啓aof
appendonly yes

# 文件名稱
appendfilename "appendonly.aof"

# 同步方式
appendfsync everysec

# aof重寫期間是否同步
no-appendfsync-on-rewrite no

# 重寫觸發配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# 加載aof時如果有錯如何處理
aof-load-truncated yes

# 文件重寫策略
aof-rewrite-incremental-fsync yes


appendfsync everysec 它其實有三種模式:
always:把每個寫命令都立即同步到aof,很慢,但是很安全
everysec:每秒同步一次,是折中方案
no:redis不處理交給OS來處理,非常快,但是也最不安全
一般情況下都採用 everysec 配置,這樣可以兼顧速度與安全,最多損失1s的數據。

aof-load-truncated yes 如果該配置啓用,在加載時發現aof尾部不正確是,會向客戶端寫入一個log,但是會繼續執行,如果設置爲 no ,發現錯誤就會停止,必須修復後才能重新加載。


RDB方式原理:當redis需要做持久化時(執行SAVA或者BGSAVA命令,或者是達到配置條件時執行),redis會fork一個子進程,子進程將數據寫到磁盤上一個臨時RDB文件中,當子進程完成寫臨時文件後,將原來的RDB替換掉(默認文件名爲dump.rdb)
RDB優缺點:
定時備份,Redis效率高,但是容易造成數據丟失,丟失的多少和備份策略有關

AOF方式原理:AOF就可以做到全程持久化,Redis每執行一個修改數據的命令,都會把這個命令添加到AOF文件中,當Redis重啓時,將會讀取AOF文件進行“重放”以恢復到 Redis關閉前的最後時刻。
AOF優缺點
AOF基本可以保證數據不丟失,但是AOF持久化文件會變的越來越大。例如我們調用incr test命令100次,文件中必須保存全部的100條命令,其實有99條都是多餘的。

redis 發佈訂閱
redis發佈訂閱(pub/sub)是一種消息通信模式:發送者(pub)發送消息,訂閱者(sub)接收消息.

訂閱端(訂閱者:subscribe):
    127.0.0.1:6379> subscribe redis-world #訂閱redis-world頻道
    1) "subscribe"
    2) "redis-world"
    3) (integer) 1
    1) "message" #消息
    2) "redis-world" #頻道
    3) "welcome redis world" #消息內容

發送端(發送者:publish):
    127.0.0.1:6379> publish redis-world "welcome redis world" #發佈者發佈消息到頻道
    (integer) 1

使用場景:
1、實時消息
2、在線聊天
3、關注、訂閱
更爲複雜的使用消息中間件來實現


Redis主從複製
主從複製,是指 將一臺Redis服務器的數據,複製到其他的Redis服務器。前者稱爲主節點(master/leader),後者稱爲從節點(slave/follower);數據的複製是單向的,只能由主節點到從節點。master以寫爲主,slave以讀爲主。大部分情況下80%的操作是讀數據。

主從複製的作用主要包括:
1、數據冗餘:主從複製實現了數據的熱備份,是持久化之外的一種數據冗餘方式。
2、故障恢復:當主節點出現問題時,可以由從節點提供服務,實現快速的故障恢復;實際上是一種服務的冗餘。
3、負載均衡:主從複製的基礎上,配合讀寫分離,可以由主節點提供寫服務,從節點提供讀服務,分擔服務器負載,可以提高服務器的併發量。
4、高可用基石:除上述作用外,主從複製還是哨兵和集羣能夠實施的基礎,因此主從複製是Redis的高可用的基礎。

一般來說,至少3臺服務器,一主二從。(單個redis的內存不好超過20G,最好搭建集羣)

環境配置:(只配置從庫,因爲redis默認爲主庫)
127.0.0.1:6379> info replication #當前庫的信息
# Replication
role:master #當前庫的角色
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

複製3個配置文件:
1、端口(端口的話,自己記得就好)
2、pid名
3、log日誌文件名
4、dump.rdb名

配置完成後,分別啓動數據庫。當前3臺數據庫默認都是主節點,只配置充當從節點的數據庫,對它們配置主節點的信息。
slaveof ip port  #配置主機的ip和端口號

當前從節點的配置是通過命令行進行配置的,是暫時的。在實際應用是在redis配置文件中配置的,永久有效,當從節點啓動服務就爲扮演從節點的角色。

#replicaof <masterip> <masterport> 在配置文件中解注這行,添加主機的ip和端口號即可.
從機只可讀,不可寫。

主從模式結構1是這樣子的:
             |
             |--slave1(從機)
master--|
             |--slave2(從機)
             |

測試:
主機斷開連接,從機會依然連接到主機,但是沒有寫操作了。主機服務正常了,從機可以正常獲取到主機寫入的數據。如果從機宕機,主機進行了寫操作,從機再次開啓服務,數據會立馬同步到數據。(如果從機是使用命令配置的,開啓服務後會變爲主機,需要再次配置主機信息使自己變爲從機,主機的數據會同步到當前從機)

複製原理:
slave(從機)啓動成功連接到master(主機)後會發送一個sync(同步)命令,
主機接到命令,啓動後臺的存盤進程,同時收集所有接收到的用於修改數據集命令,在後臺進程執行完畢之後,主機將傳送整個數據文件到從機,並完成一次完全同步。
全量複製:而從機服務在接收到數據庫文件數據後,將其存盤並加載到內存中。
增量複製:主機繼續新的所有收集到的修改命令一次傳給從機,完成同步,但是隻要是重新連接主機,一次完全同步(全量複製)將自動執行

主從模式結構2是這樣子的:
(主機)  (從機/主機) (從機)   
master--|--slave1--|slave2
如果master斷開了,slave1和slave2沒有了主節點,現在可以手動在slave1上配置slaveof no one,是自己成爲主機

意思兩種模式,在實際開發的過程中都不用。不夠靈活,所以,就引出了哨兵模式。


Redis哨兵模式
監控後臺主機是否存活,如果不存活了就需要在從機中選舉一個作爲主機。
哨兵模式是一種特殊的模式,首先Redis提供了哨兵的命令,哨兵是一個獨立的進程,作爲進程,單獨運行。哨兵通過發送命令,等待redis服務器響應,從而監控運行的多個Redis實例。

哨兵的兩個作用:
1、通過發送命令,讓Redis服務器返回監控其運行狀態,包括服務器和從服務器。
2、當哨兵檢測到主機宕機,會自動將從機切換成主機。

一般保證系統的能正常的選舉主機,一個哨兵是不夠的,一般會設計多個哨兵進行監控,各個哨兵之間還會進行監控,形成多哨兵模式。

多個哨兵模式:當一個哨兵檢測到主機不可用,這個現象稱爲主觀下線;當所有的哨兵檢測到主機不可用,才認爲主機不可用了;哨兵之間會進行一次投票,投票結果由一個哨兵發起,進行failover(故障轉移)操作。切換成功後,就會通過發佈訂閱模式,讓各個哨兵把自己監控的從服務器實現切換主機,這個過程稱爲客觀下線。

哨兵配置(單個)(默認30秒後會選舉出一個主機)
1、創建sentinel.conf文件
sentinel monitor myredis 127.0.0.1 6379 1 (主機 端口 1:代表主機不可用,哨兵通過投票得到的最多票數從從機中選出一臺作爲主機)
2、啓動哨兵 redis-sentinel 配置文件sentinel.conf 

當選取主機後,原主機如果正常服務,只能作爲當前的主機的從機。

哨兵模式的優缺點:
優點:1)哨兵集羣,基於主從複製模式,所有的主從配置優點;
      2)主從可以切換,故障可以轉移,系統的可用性會更好
      3)哨兵模式就是主從模式的升級,由手動到自動,功能更加靈活,強大
缺點: 1)Redis在線擴容繁瑣,集羣容量一旦到達上限,擴容困難
      2)實現哨兵模式的配置繁瑣,配置選擇項太多

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章