欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

目錄

柚子快報(bào)邀請(qǐng)碼778899分享:緩存 Redis詳解

柚子快報(bào)邀請(qǐng)碼778899分享:緩存 Redis詳解

http://yzkb.51969.com/

目錄

一、NoSQL概述

1、為什么要使用NoSQL

2、什么是NoSQL

Not Only SQL —> 非關(guān)系型數(shù)據(jù)庫(kù)

NoSQL特點(diǎn)

了解:3V + 3高

3、NoSQL的四大分類

1.KV鍵值對(duì)

2.文檔型數(shù)據(jù)庫(kù)(bson格式)

3.列式存儲(chǔ)

4.圖關(guān)系數(shù)據(jù)庫(kù)

對(duì)比

二、Redis入門

1.Redis是什么

redis 與其他 key - value 緩存產(chǎn)品有以下三個(gè)特點(diǎn):

Redis優(yōu)勢(shì)

2.能干什么?

3.特性

4.安裝(因?yàn)镽edis更適合在linux下使用,所以只有l(wèi)inux的安裝版本)

5.性能測(cè)試

6.基本知識(shí)說(shuō)明(基本命令)

1.Redis 有16個(gè)數(shù)據(jù)庫(kù)(0~15),默認(rèn)使用第0個(gè)

2.查看數(shù)據(jù)庫(kù)大小

3.查看所有的key(當(dāng)前庫(kù))

4.清除當(dāng)前數(shù)據(jù)庫(kù)

5.清空所有數(shù)據(jù)庫(kù)

6.Redis是單線程的?

7.判斷key是否存在

8.移除key

9.設(shè)置key的過(guò)期時(shí)間

10.查看當(dāng)前key的類型

11.字符串追加(String)

12.獲取字符串長(zhǎng)度(String)

13.字符串i++操作(可用于閱讀量實(shí)現(xiàn))(String)

同理,i—

步長(zhǎng)設(shè)置

14.字符串片段 Range (String)

15.字符串替換 (String)

16.特殊set設(shè)置 (String)

setex(set with expire)

setnx(set if not exist)

17.批量設(shè)置、批量獲?。ㄔ有圆僮鳎?(String)

18.設(shè)置高階 (String)

1)getset

19.重命名key

20.返回一個(gè)隨機(jī)key

21.手動(dòng)持久化操作

22.獲取配置文件中用戶密碼

23.設(shè)置配置文件中用戶密碼(臨時(shí),重啟服務(wù)失效)

24.密碼認(rèn)證

25.關(guān)閉redis服務(wù)

26.查看rdb文件存放的目錄

27.查看服務(wù)器的信息

三、五大數(shù)據(jù)類型

String(字符串)

使用場(chǎng)景:

List(列表)

1.從頭部/尾部插入數(shù)據(jù),以及數(shù)據(jù)顯示

2.從頭部/尾部移除數(shù)據(jù)

3.獲取指定索引的值

4.獲取列表長(zhǎng)度

5.移除指定的值

6.列表修剪 trim

7.也可以使用set

8.插入指定的值

9.復(fù)雜操作

1)rpoplpush

使用場(chǎng)景:

Set(集合)

1.添加成員到集合中,并查看所有成員

2.判定成員是否存在

3.查看集合長(zhǎng)度(特別)

4.移除指定的成員

5.獲取集合中的隨機(jī)成員

6.隨機(jī)移除成員

7.移動(dòng)集合成員到其他集合

8.數(shù)字集合類:

Hash(哈希)

1.簡(jiǎn)單存儲(chǔ)Map和獲取Map

2.獲取所有Map字段及值

3.刪除Map中的字段

4.查看Map中某字段是否存在

5.獲取所有字段或者所有字段對(duì)應(yīng)的值

6.增量i++

7.不存在,就添加成功

8.適合存儲(chǔ)對(duì)象

Zset(有序集合)

1.添加 和 獲取

2.排序?qū)崿F(xiàn)(升序和降序)

3.移除指定的值

4.集合的長(zhǎng)度

5.指定區(qū)間的集合長(zhǎng)度

四、三種特殊數(shù)據(jù)類型

Geospatial

1.添加地理位置

2.獲取指定位置的地理位置

3.返回兩個(gè)給定位置之間的距離(直線距離)

4.以給定值為半徑,以經(jīng)度和維度為中心,查找

5.以給定值為半徑,以成員(城市名)為中心,查找

6.返回一個(gè)或多個(gè)位置元素的geohash表示

Hyperloglog

1.測(cè)試

Bitmaps

1.案例:一周打卡記錄

五、事務(wù)

正常事務(wù)的執(zhí)行

取消事務(wù)

異常執(zhí)行

1.編譯時(shí)(命令寫錯(cuò))

2.運(yùn)行時(shí)

監(jiān)控 Watch(面試常問(wèn))

樂(lè)觀鎖:實(shí)現(xiàn)秒殺

悲觀鎖

Redis實(shí)現(xiàn)樂(lè)觀鎖

執(zhí)行成功(單線程沒(méi)有干擾情況)

測(cè)試多線程修改值,使用watch可以當(dāng)作redis的樂(lè)觀鎖操作

小結(jié)

六、Jedis

1、什么是Jedis

2、使用

七、SpringBoot整合

①新建springboot項(xiàng)目

②?RedisAutoConfiguration源碼分析

③整合測(cè)試

④自定義RedisTemplate

⑤RedisUtils工具類

進(jìn)階

八、Redis.conf詳解

單位

包含

網(wǎng)絡(luò)

通用

快照

主從復(fù)制 REPLICATION

安全 SECURITY

客戶端限制

內(nèi)存管理

APPEND ONLY MODE (AOF配置)

九、Redis持久化(重點(diǎn))

1、RDB(Redis DataBase)

設(shè)置RDB文件保存條件

結(jié)果測(cè)試

RDB文件生成觸發(fā)機(jī)制

RDB文件恢復(fù)

優(yōu)缺點(diǎn)

2、AOF(Append Only File)

重啟redis后,appendonly.aof文件自動(dòng)生成

重寫規(guī)制

錯(cuò)誤修復(fù)

優(yōu)缺點(diǎn)

擴(kuò)展

十、Redis發(fā)布訂閱

命令

測(cè)試

原理

使用場(chǎng)景:

做訂閱的缺點(diǎn)

十一、主從復(fù)制

概念

主從復(fù)制的主要作用

環(huán)境配置

1、復(fù)制配置文件redis.conf到Redis安裝目錄下

2、再?gòu)脑撐募截惓?個(gè)文件

3、修改主配置文件

4、修改從配置文件

配置文件修改的信息

5、啟動(dòng)服務(wù)(單機(jī)多服務(wù))

6、登錄客戶端

7、一主二從

使用slaveof 指定 主節(jié)點(diǎn) ip 和 端口(臨時(shí)配置)

有密碼配置(+永久配置)

測(cè)試

復(fù)制原理

8、毛毛蟲(chóng)配置(主從)

9、宕機(jī)手動(dòng)配置主機(jī)

十二、哨兵模式

單哨兵模式

哨兵的作用:

多哨兵模式

測(cè)試(一主二從,單哨兵)

1、配置哨兵配置文件(文件名?sentinel.conf)

2、啟動(dòng)哨兵模式

3、關(guān)閉主機(jī),測(cè)試選舉情況

優(yōu)缺點(diǎn)

哨兵模式的全部配置

十三、緩存穿透和雪崩(面試高頻,工作常用)

1、緩存穿透(查不到)

解決方案

布隆過(guò)濾器

緩存空對(duì)象

2、緩存雪崩(集中失效)

解決方案

Redis高可用

限流降級(jí)

數(shù)據(jù)預(yù)熱

3、緩存擊穿(查詢量太大,緩存過(guò)期瞬間)

解決方案

設(shè)置熱點(diǎn)數(shù)據(jù)永不過(guò)期

加互斥鎖

一、NoSQL概述

1、為什么要使用NoSQL

現(xiàn)在是大數(shù)據(jù)時(shí)代(一般的數(shù)據(jù)庫(kù)已經(jīng)解決不了的數(shù)據(jù):大數(shù)據(jù)(海量存儲(chǔ)和并行計(jì)算))

SQL => NoSQL

1、單機(jī)時(shí)代(如MySQL)的瓶頸

數(shù)據(jù)量太大,一個(gè)機(jī)器存不下數(shù)據(jù)的索引(MySQL單表300萬(wàn)條數(shù)據(jù),一定要建立索引),一個(gè)機(jī)器內(nèi)存放不下訪問(wèn)量大(MySQL讀寫混合 — 性能降低),一個(gè)服務(wù)器承受不了

2、Memcached緩存(減輕服務(wù)器的壓力) + MySQL + 垂直拆分(讀寫分離,多個(gè)MySQL服務(wù)器,有的值負(fù)責(zé)讀,有的值負(fù)責(zé)寫)

發(fā)展過(guò)程:①優(yōu)化數(shù)據(jù)結(jié)構(gòu)和索引 => ②文件緩存(涉及IO操作)=> ③Memcached

3、分庫(kù)分表 + 水平拆分 + MySQL集群

用戶的個(gè)人信息(社交網(wǎng)絡(luò)、地理位置、用戶日志等)爆發(fā)是增長(zhǎng),無(wú)法使用關(guān)系型數(shù)據(jù)庫(kù)去存儲(chǔ),那么需要NoSQL數(shù)據(jù)庫(kù)

2、什么是NoSQL

Not Only SQL —> 非關(guān)系型數(shù)據(jù)庫(kù)

NoSQL特點(diǎn)

方便擴(kuò)展(數(shù)據(jù)之間沒(méi)有關(guān)系) 大數(shù)據(jù)高性能(Redis一秒寫8萬(wàn)次,讀取11萬(wàn)次,NoSQL的緩存記錄級(jí),是一種細(xì)粒度的緩存,性能比較高) 數(shù)據(jù)類型是多樣性的(不需要事先設(shè)計(jì)數(shù)據(jù)庫(kù)(因?yàn)閿?shù)據(jù)量大),隨取隨用) 傳統(tǒng)RDBMS和NoSQL

傳統(tǒng)RDBMS

結(jié)構(gòu)化組織SQL數(shù)據(jù)和關(guān)系都存在單獨(dú)的表中操作,數(shù)據(jù)定義語(yǔ)言嚴(yán)格的一致性基礎(chǔ)的事務(wù)… NoSQL

不僅僅是SQL沒(méi)有固定的查詢語(yǔ)句鍵值對(duì)存儲(chǔ),列存儲(chǔ),文檔存儲(chǔ),圖形數(shù)據(jù)庫(kù)(社交關(guān)系)最終一致性CAP定理和BASE高性能,高可用,高可擴(kuò)…

了解:3V + 3高

大數(shù)據(jù)時(shí)代的3V:主要是描述問(wèn)題的

海量Volume多樣Variety實(shí)時(shí)Velocity

大數(shù)據(jù)時(shí)代的3高:主要是對(duì)程序的要求

高并發(fā)高可拓(集群)高性能

電商網(wǎng)站:

# 1、商品的基本信息

名稱、價(jià)格、商家信息:

關(guān)系型數(shù)據(jù)庫(kù): MySQL / Oracle (王堅(jiān):阿里去IOE(IBM小型機(jī),Oracle數(shù)據(jù)庫(kù)、EMC存儲(chǔ)器))

# 2、商品的描述、評(píng)論(文字多)

文檔型數(shù)據(jù)庫(kù):MongoDB

# 3、圖片

分布式文件系統(tǒng):FastDFS、TFS(淘寶)、GFS(Google)、HDFS(Hadoop)、OSS云存儲(chǔ)(阿里云)

# 4、商品的關(guān)鍵字(搜索)

搜索引擎:solr、ElasticSearch、ISearch(阿里:多?。?/p>

# 5、商品熱門的波段信息

內(nèi)存數(shù)據(jù)庫(kù):Redis、Tair、Memcached、...

# 6、商品的交易、外部的接口

三方應(yīng)用

3、NoSQL的四大分類

1.KV鍵值對(duì)

新浪:Redis美團(tuán):Redis + Tair阿里、百度:Redis + Memcached

2.文檔型數(shù)據(jù)庫(kù)(bson格式)

MongoDB(必須掌握)

基于分布式文件存儲(chǔ)的數(shù)據(jù)庫(kù)(C++編寫)主要用于處理大量的文檔介于關(guān)系型數(shù)據(jù)庫(kù)和非關(guān)系型數(shù)據(jù)庫(kù)中的中間產(chǎn)品ConthDB

3.列式存儲(chǔ)

HBase分布式文件系統(tǒng)

4.圖關(guān)系數(shù)據(jù)庫(kù)

存關(guān)系的,不是存圖片的(比如,朋友圈社交網(wǎng)絡(luò),廣告推薦)Neo4j、InfoGrid

對(duì)比

分類Examples舉例典型應(yīng)用場(chǎng)景數(shù)據(jù)模型優(yōu)點(diǎn)缺點(diǎn)鍵值(key-value)Tokyo
Cabine/Tyrant
Redis
Voldemort
Oracle BDB內(nèi)容緩存,主要用于處理大量數(shù)據(jù)的高訪問(wèn)負(fù)載,也用于一些日志系統(tǒng)等等Key指向Value的鍵值對(duì),通常用hashtable來(lái)實(shí)現(xiàn)查找速度快數(shù)據(jù)無(wú)結(jié)構(gòu)化,通常只被當(dāng)作字符串或者二進(jìn)制數(shù)據(jù)列存儲(chǔ)數(shù)據(jù)庫(kù)Cassandra
HBase
Riak分布式的文件系統(tǒng)以列簇式存儲(chǔ),將同一列數(shù)據(jù)存在一起查找速度快,可擴(kuò)展性強(qiáng),更容易進(jìn)行分布式擴(kuò)展功能相對(duì)局限文檔型數(shù)據(jù)庫(kù)CouchDB
MongoDBWeb應(yīng)用(與Key-Value類似,Value是結(jié)構(gòu)化的,不同的是數(shù)據(jù)庫(kù)能夠了解Value的內(nèi)容)Key-Value對(duì)應(yīng)的鍵值對(duì),Value為結(jié)構(gòu)化數(shù)據(jù)數(shù)據(jù)結(jié)構(gòu)要求不嚴(yán)謹(jǐn),表結(jié)構(gòu)可變,不需要像關(guān)系型數(shù)據(jù)庫(kù)一樣需要預(yù)先定義表結(jié)構(gòu)查詢性能不高,而且缺乏統(tǒng)一的查詢語(yǔ)法圖形數(shù)據(jù)庫(kù)Neo4J
InfoGrid
Infinite Graph社交網(wǎng)絡(luò),推薦系統(tǒng)等。專注于構(gòu)建關(guān)系圖譜圖結(jié)構(gòu)利用圖結(jié)構(gòu)相關(guān)算法。比如最短路徑尋址,N度關(guān)系查找等很多時(shí)候需要對(duì)整個(gè)圖做計(jì)算才能得出需要的信息,而且這種結(jié)構(gòu)不太好做分布式的集群方案

二、Redis入門

1.Redis是什么

官網(wǎng):redis.io

中文網(wǎng):http://www.redis.cn/

Redis 是一個(gè)開(kāi)源(BSD許可)的,內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng),它可以用作數(shù)據(jù)庫(kù)、緩存消息中間件。 它支持多種類型的數(shù)據(jù)結(jié)構(gòu),如?字符串(strings),?散列(hashes),?列表(lists),?集合(sets),?有序集合(sorted sets)?與范圍查詢,?bitmaps,?hyperloglogs?和?地理空間(geospatial)?索引半徑查詢。 Redis 內(nèi)置了?復(fù)制(replication),LUA腳本(Lua scripting),?LRU驅(qū)動(dòng)事件(LRU eviction),事務(wù)(transactions)?和不同級(jí)別的?磁盤持久化(persistence), 并通過(guò)?Redis哨兵(Sentinel)和自動(dòng)?分區(qū)(Cluster)提供高可用性(high availability)。

redis 與其他 key - value 緩存產(chǎn)品有以下三個(gè)特點(diǎn):

Redis支持?jǐn)?shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保存在磁盤中,重啟的時(shí)候可以再次加載進(jìn)行使用。Redis不僅僅支持簡(jiǎn)單的key-value類型的數(shù)據(jù),同時(shí)還提供list,set,zset,hash等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)(多樣的數(shù)據(jù)結(jié)構(gòu))。Redis支持?jǐn)?shù)據(jù)的備份,即master-slave模式的數(shù)據(jù)備份。

Redis優(yōu)勢(shì)

性能極高?– Redis能讀的速度是110000次/s,寫的速度是81000次/s 。豐富的數(shù)據(jù)類型?– Redis支持二進(jìn)制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 數(shù)據(jù)類型操作。原子?– Redis的所有操作都是原子性的,意思就是要么成功執(zhí)行要么失敗完全不執(zhí)行。單個(gè)操作是原子性的。多個(gè)操作也支持事務(wù),即原子性,通過(guò)MULTI和EXEC指令包起來(lái)。(但是Redis事務(wù)多操作不支持原子性—當(dāng)我們執(zhí)行后有語(yǔ)句有錯(cuò),其他語(yǔ)句仍然可以正常執(zhí)行,詳情看事務(wù))豐富的特性?– Redis還支持 publish/subscribe, 通知, key 過(guò)期等等特性。Redis運(yùn)行在內(nèi)存中但是可以持久化到磁盤,所以在對(duì)不同數(shù)據(jù)集進(jìn)行高速讀寫時(shí)需要權(quán)衡內(nèi)存,因?yàn)閿?shù)據(jù)量不能大于硬件內(nèi)存。在內(nèi)存數(shù)據(jù)庫(kù)方面的另一個(gè)優(yōu)點(diǎn)是,相比在磁盤上相同的復(fù)雜的數(shù)據(jù)結(jié)構(gòu),在內(nèi)存中操作起來(lái)非常簡(jiǎn)單,這樣Redis可以做很多內(nèi)部復(fù)雜性很強(qiáng)的事情。同時(shí),在磁盤格式方面他們是緊湊的以追加的方式產(chǎn)生的,因?yàn)樗麄儾⒉恍枰M(jìn)行隨機(jī)訪問(wèn)。

2.能干什么?

內(nèi)存存儲(chǔ)、持久化(rdb,aof)效率高、可以用于高速緩存發(fā)布訂閱系統(tǒng)地圖信息分析計(jì)時(shí)器、計(jì)數(shù)器(瀏覽量)…

3.特性

多樣的數(shù)據(jù)結(jié)構(gòu)持久化集群事務(wù)…

4.安裝(因?yàn)镽edis更適合在linux下使用,所以只有l(wèi)inux的安裝版本)

linux 使用的系統(tǒng)是 Centos 7.3

你可使用 虛擬機(jī),也可已使用云服務(wù)器(學(xué)生機(jī)不貴),因?yàn)槲矣蟹?wù)器,這里就在服務(wù)器上安裝和學(xué)習(xí)Redis

①下載安裝包

http://www.redis.cn/

②加壓安裝包(提前使用xshell和xftp上傳壓縮包到服務(wù)器上)

壓縮包在 /app/目錄下

在/usr/local/ 下創(chuàng)建redis文件夾,并進(jìn)入到文件夾中

解壓壓縮包到該文件夾下

tar -zxvf /app/redis-6.0.6.tar.gz -C ./

③編譯并安裝(保證安裝了編譯環(huán)境)

沒(méi)有安裝編譯環(huán)境,需要 yum install gcc-c++

如果下面操作報(bào)錯(cuò):需要提升GCC的版本(redis6需要5.3+)

//升級(jí)gcc到9以上

yum -y install centos-release-scl

yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils

//臨時(shí)將此時(shí)的gcc版本改為9

scl enable devtoolset-9 bash

//或永久改變

echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile

cd redis-6.0.6

make && make install

編譯后,默認(rèn)安裝路徑在?/usr/local/bin

④安裝系統(tǒng)服務(wù)并后臺(tái)啟動(dòng)

可能會(huì)報(bào)錯(cuò):

解決方法:vim install_server.sh,注釋如下圖內(nèi)容

安裝系統(tǒng)服務(wù)(可以指定選項(xiàng),下面默認(rèn))?

cd utils

./install_server.sh

默認(rèn)的配置文件:/etc/redis/6379.conf(安裝成功后,默認(rèn)后臺(tái)自啟)

⑤開(kāi)啟redis服務(wù)

可以使用自定義的配置文件開(kāi)啟,這里使用systemctl

/redis安裝目錄/redis-server /配置文件目錄/redis.conf

# 關(guān)閉服務(wù)

/redis安裝目錄/redis-cli shutdown

systemctl start redis_6379.service

⑥客戶端連接測(cè)試

⑦設(shè)置遠(yuǎn)程連接

vim /etc/redis/6379.conf

然后重啟服務(wù)即可:?

systemctl restart redis_6379.service

⑧配置訪問(wèn)密碼

vim /etc/redis/6379.conf

重啟服務(wù)

systemctl restart redis_6379.service

客戶端連接測(cè)試

關(guān)閉連接

5.性能測(cè)試

使用自帶的redis-benchmark工具測(cè)試即可

redis-benchmark [option] [option value]

性能測(cè)試工具可選參數(shù):

序號(hào)選項(xiàng)描述默認(rèn)值1-h指定服務(wù)器主機(jī)名127.0.0.12-p指定服務(wù)器端口63793-s指定服務(wù)器 socket4-c指定并發(fā)連接數(shù)505-n指定請(qǐng)求數(shù)100006-d以字節(jié)的形式指定 SET/GET 值的數(shù)據(jù)大小37-k1=keep alive 0=reconnect18-rSET/GET/INCR 使用隨機(jī) key, SADD 使用隨機(jī)值9-P通過(guò)管道傳輸 \ 請(qǐng)求110-q強(qiáng)制退出 redis。僅顯示 query/sec 值11—csv以 CSV 格式輸出12-l生成循環(huán),永久執(zhí)行測(cè)試13-t僅運(yùn)行以逗號(hào)分隔的測(cè)試命令列表。14-IIdle 模式。僅打開(kāi) N 個(gè) idle 連接并等待。

測(cè)試

# 測(cè)試:100個(gè)并發(fā)連接 100000請(qǐng)求

redis-benchmark -c 100 -n 100000

6.基本知識(shí)說(shuō)明(基本命令)

如果覺(jué)得這里命令不太好看,去這個(gè)博客https://www.cnblogs.com/wlandwl/p/redis.html,或者?官網(wǎng):http://www.redis.cn/commands.html

注意:以下的所有key都表示對(duì)應(yīng)數(shù)據(jù)類型的?鍵的名稱?; value表示存儲(chǔ)的值(除非注釋中有特殊說(shuō)明)

1.Redis 有16個(gè)數(shù)據(jù)庫(kù)(0~15),默認(rèn)使用第0個(gè)

可以使用?select進(jìn)行切換

2.查看數(shù)據(jù)庫(kù)大小

使用?dbsize查看數(shù)據(jù)庫(kù)大小

3.查看所有的key(當(dāng)前庫(kù))

使用?keys *

4.清除當(dāng)前數(shù)據(jù)庫(kù)

flushdb

5.清空所有數(shù)據(jù)庫(kù)

flushall

6.Redis是單線程的?

Redis是很快的,官方表示,Redis是基于內(nèi)存操作,CPU不是Redis的性能瓶頸,Redis的性能瓶頸是根據(jù)機(jī)器的內(nèi)存網(wǎng)絡(luò)的帶寬,既然可以使用單線程,就不用使用多線程。(6.0后支持多線程)

7.判斷key是否存在

exists?key

8.移除key

move?key 1 // 1表示當(dāng)前數(shù)據(jù)庫(kù)

del?key // 刪除當(dāng)前數(shù)據(jù)庫(kù)的key(可以多個(gè))

9.設(shè)置key的過(guò)期時(shí)間

expire?key 時(shí)間 // 單位時(shí)間為s

ttl?key // 查看剩余存活時(shí)間

10.查看當(dāng)前key的類型

type?key

11.字符串追加(String)

append?key appendValue

如果當(dāng)前 key 不存在,作用相當(dāng)于 set key

12.獲取字符串長(zhǎng)度(String)

strlen?key

13.字符串i++操作(可用于閱讀量實(shí)現(xiàn))(String)

incr?key

同理,i—

decr?key

步長(zhǎng)設(shè)置

incrby?key 步長(zhǎng)

decrby?key 步長(zhǎng)

14.字符串片段 Range (String)

getrange?key startIndex endIndex

對(duì)應(yīng)java里的substring(但是這里會(huì)endIndex是一個(gè)閉區(qū)間)特例,endIndex = -1 時(shí),表示從startIndex 到最后

15.字符串替換 (String)

setrange?key index replaceString

對(duì)應(yīng)java里的replace注意,如果replaceString是一個(gè)字符串,那么會(huì)替換源字符串中index后replaceString長(zhǎng)度的片段,結(jié)果如下

16.特殊set設(shè)置 (String)

setex(set with expire)

setex?key 時(shí)間 value // 設(shè)置值,帶過(guò)期時(shí)間

setnx(set if not exist)

setnx?key value // 如果不存在,則設(shè)置

17.批量設(shè)置、批量獲?。ㄔ有圆僮鳎?(String)

mset?k1 v1 k2 v2 …

mget?k1 k2 …

特殊

msetnx?批量設(shè)置

18.設(shè)置高階 (String)

1)getset

getset?key value // 先get再set(如果不存在,先返回nil,在設(shè)置值;如果存在,就先返回原值,再設(shè)置新值)

19.重命名key

rename?key newName

20.返回一個(gè)隨機(jī)key

randomKey

21.手動(dòng)持久化操作

save?阻塞

SAVE 直接調(diào)用 rdbSave ,阻塞 Redis 主進(jìn)程,直到保存完成為止。在主進(jìn)程阻塞期間,服務(wù)器不能處理客戶端的任何請(qǐng)求。

bgsave?非阻塞

BGSAVE 則 fork 出一個(gè)子進(jìn)程,子進(jìn)程負(fù)責(zé)調(diào)用 rdbSave ,并在保存完成之后向主進(jìn)程發(fā)送信號(hào),通知保存已完成。 Redis 服務(wù)器在BGSAVE 執(zhí)行期間仍然可以繼續(xù)處理客戶端的請(qǐng)求。

命令savebgsaveIO類型同步異步阻塞?是是(阻塞發(fā)生在fock(),通常非??欤?fù)雜度O(n)O(n)優(yōu)點(diǎn)不會(huì)消耗額外的內(nèi)存不阻塞客戶端命令缺點(diǎn)阻塞客戶端命令需要fock子進(jìn)程,消耗內(nèi)存

22.獲取配置文件中用戶密碼

config get requirepass

23.設(shè)置配置文件中用戶密碼(臨時(shí),重啟服務(wù)失效)

config set requirepass password

24.密碼認(rèn)證

auth password?設(shè)置密碼后必須認(rèn)證才能使用客戶端功能

25.關(guān)閉redis服務(wù)

shutdown

26.查看rdb文件存放的目錄

27.查看服務(wù)器的信息

info?參數(shù)

參數(shù)列表:

server: Redis服務(wù)器的一般信息clients: 客戶端的連接部分memory: 內(nèi)存消耗相關(guān)信息persistence: RDB和AOF相關(guān)信息stats: 一般統(tǒng)計(jì)replication: 主/從復(fù)制信息cpu: 統(tǒng)計(jì)CPU的消耗commandstats: Redis命令統(tǒng)計(jì)cluster: Redis集群信息keyspace: 數(shù)據(jù)庫(kù)的相關(guān)統(tǒng)計(jì)

它也可以采取以下值:

all: 返回所有信息default: 值返回默認(rèn)設(shè)置的信息

如果沒(méi)有使用任何參數(shù)時(shí),默認(rèn)為default。

三、五大數(shù)據(jù)類型

Redis 是一個(gè)開(kāi)源(BSD許可)的,內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng),它可以用作數(shù)據(jù)庫(kù)、緩存消息中間件。 它支持多種類型的數(shù)據(jù)結(jié)構(gòu),如?字符串(strings),?散列(hashes),?列表(lists),?集合(sets),?有序集合(sorted sets)?與范圍查詢,?bitmaps,?hyperloglogs?和?地理空間(geospatial)?索引半徑查詢。 Redis 內(nèi)置了?復(fù)制(replication),LUA腳本(Lua scripting),?LRU驅(qū)動(dòng)事件(LRU eviction),事務(wù)(transactions)?和不同級(jí)別的?磁盤持久化(persistence), 并通過(guò)?Redis哨兵(Sentinel)和自動(dòng)?分區(qū)(Cluster)提供高可用性(high availability)。

單點(diǎn)登錄、

String(字符串)

略,具體看前面

使用場(chǎng)景:

計(jì)數(shù)器統(tǒng)計(jì)多單位的數(shù)量(uid:122:follow 10)粉絲數(shù)對(duì)象緩存存儲(chǔ)

List(列表)

1.從頭部/尾部插入數(shù)據(jù),以及數(shù)據(jù)顯示

lpush?key value

rpush?key value

lrange?key 0 -1

2.從頭部/尾部移除數(shù)據(jù)

lpop?key

rpop?key

3.獲取指定索引的值

lindex?key index

4.獲取列表長(zhǎng)度

llen?key

5.移除指定的值

lrem?key count(移除的個(gè)數(shù)) element

6.列表修剪 trim

ltrim?key startIndex endIndex

7.也可以使用set

lset?key index value // 將列表中 指定index的值替換為對(duì)應(yīng)的value

需要保證key和index都存在,否則報(bào)錯(cuò)

8.插入指定的值

linsert?key before|after pivot(那個(gè)單詞后) value

9.復(fù)雜操作

1)rpoplpush

rpoplpush?source destination(newList) // 先移除source最后的元素,再將該元素添加到newList中

使用場(chǎng)景:

棧(lpush、lpop)隊(duì)列(lpush、rpop)

消息隊(duì)列阻塞隊(duì)列

Set(集合)

集合中的值不能重復(fù)(無(wú)序)

1.添加成員到集合中,并查看所有成員

sadd?key member

smembers?key

2.判定成員是否存在

sismember?key member

3.查看集合長(zhǎng)度(特別)

scard?key

4.移除指定的成員

srem?key member

5.獲取集合中的隨機(jī)成員

srandmember?key [count]

6.隨機(jī)移除成員

spop?key [count]

7.移動(dòng)集合成員到其他集合

smove?source destination member(需要移動(dòng)的成員)

8.數(shù)字集合類:

差集?sdiff?key1 ,key2 …交集(共同好友)sinter?key1,key2 …并集?sunion?key1 ,key2 …

Hash(哈希)

key-Map or key-\,value是一個(gè)Map

Hash本質(zhì)和hash沒(méi)有區(qū)別,只是value變成了Map

用戶信息保存,經(jīng)常變動(dòng)的信息,適合對(duì)象的存儲(chǔ)

1.簡(jiǎn)單存儲(chǔ)Map和獲取Map

hset?key field value [k1 v1 [k2 v2 …]]

hget?key field

2.獲取所有Map字段及值

hgetall?key

3.刪除Map中的字段

hdel?key field

4.查看Map中某字段是否存在

hexists?key field

5.獲取所有字段或者所有字段對(duì)應(yīng)的值

hkeys?key // 此處的key是Map名

hvals?key

6.增量i++

hincrby?key field value

7.不存在,就添加成功

hsetnx?key field value // field 在map中不存在就添加這個(gè)值,否則不做改變

8.適合存儲(chǔ)對(duì)象

Zset(有序集合)

在Set基礎(chǔ)上增加了一個(gè)值(用于排序的值)

存儲(chǔ)班級(jí)成績(jī)表,工資表排序,

普通消息 = 1,重要消息 = 2,帶權(quán)重進(jìn)行判斷

排行榜應(yīng)用實(shí)現(xiàn)

1.添加 和 獲取

zadd?key n value

zrange?key startIndex endIndex

2.排序?qū)崿F(xiàn)(升序和降序)

zrangebyscore?key -inf +inf [withscores] // 升序

zrange?key 0 -1

zrevrangebyscore?key +inf -inf [withscores] // 降序

zrevrange?key 0 -1

zrangebyscore?key -inf 任意值n // 升序 + 顯示區(qū)間 [-inf,n]

3.移除指定的值

zrem?key value

4.集合的長(zhǎng)度

zcard?key

5.指定區(qū)間的集合長(zhǎng)度

zcount?key startIndex endIndex

四、三種特殊數(shù)據(jù)類型

Geospatial

朋友的定位,附近的人,打車距離計(jì)算

底層是?Zset,即可以使用Zset的命令操作Geospatial

Redis3.2就支持了

1.添加地理位置

兩極無(wú)法添加經(jīng)度:-180 ~ 180(度)緯度:-85.05112878 ~ 85.05112878(度)

geoadd?key 經(jīng)度 緯度 名稱

2.獲取指定位置的地理位置

geopos?key 名稱

3.返回兩個(gè)給定位置之間的距離(直線距離)

單位:

m :米km :千米mi : 英里ft :英尺

geodist?key

4.以給定值為半徑,以經(jīng)度和維度為中心,查找

附近的人(獲得所有附近的人的地址(開(kāi)啟定位))通過(guò)半徑查詢

georadius?key 經(jīng)度 緯度 半徑 單位

5.以給定值為半徑,以成員(城市名)為中心,查找

georadiusbymember?key 成員名 半徑 單位

6.返回一個(gè)或多個(gè)位置元素的geohash表示

如果兩個(gè)字符串越相似,表示兩個(gè)地方越近

geohash?key 成員1 成員2

Hyperloglog

基數(shù)統(tǒng)計(jì)的算法

優(yōu)點(diǎn)

占用內(nèi)存是固定的,264不同的元素的基數(shù),只需要12KB的內(nèi)存。(大數(shù)據(jù)情況下,有0.81%錯(cuò)誤率)

基數(shù):集合中元素的個(gè)數(shù)(先去重),如{1,2,2,3} 其基數(shù)為3(集合去重后為1,2,3 有3個(gè)元素)

網(wǎng)頁(yè)的UV(一個(gè)人訪問(wèn)訪問(wèn)一個(gè)網(wǎng)站多次,但是還是算作一個(gè)人)

傳統(tǒng)實(shí)現(xiàn)UV:Set保存用戶的Id,然后統(tǒng)計(jì)set中的元素的數(shù)量作為標(biāo)準(zhǔn)判斷(這種需要保存大量用戶的ID)

Redis2.8.9

1.測(cè)試

創(chuàng)建一組元素 :?pfadd?key ele1 ele2 ele3 …

統(tǒng)計(jì)對(duì)應(yīng)key的基數(shù):pfcount?key1 [key2 …] // 多個(gè)key 就是統(tǒng)計(jì)這些key并集的基數(shù)

合并:pfmerge?destkey sourceKey1 sourceKey2 [sourceKey3 …]

Bitmaps

位存儲(chǔ),位圖(操作二進(jìn)制)

統(tǒng)計(jì)用戶信息,活躍,不活躍!登錄、未登錄!打卡,365打卡!(兩個(gè)狀態(tài)都可以使用)

1.案例:一周打卡記錄

一周過(guò)去

setbit?key offset bit

查看單天打卡情況

getbit?key offset

統(tǒng)計(jì)所有打卡的天數(shù)

bitcount?key

五、事務(wù)

注意:Redis單條命令是保證原子性的;但是事務(wù)不保證原子性!

Redis事務(wù)沒(méi)有隔離級(jí)別的概念,所有的命令在事務(wù)中,并沒(méi)有直接被執(zhí)行,只有發(fā)起執(zhí)行命令時(shí)才執(zhí)行

Redis事務(wù)本質(zhì):一組命令的集合,一個(gè)事務(wù)中的所有命令都會(huì)別序列化,在事務(wù)執(zhí)行過(guò)程中,會(huì)按照順序執(zhí)行!

--- 隊(duì)列 set set set 執(zhí)行 ---

一次性、順序性、排他性!執(zhí)行一些列的命令

Redis的事務(wù):

開(kāi)啟事務(wù)(multi)命令入隊(duì)(其他命令)執(zhí)行事務(wù)(exec)

正常事務(wù)的執(zhí)行

取消事務(wù)

discard

異常執(zhí)行

1.編譯時(shí)(命令寫錯(cuò))

整個(gè)命令隊(duì)列都不會(huì)執(zhí)行

2.運(yùn)行時(shí)

報(bào)錯(cuò)語(yǔ)句,會(huì)拋出異常;其他語(yǔ)句照樣運(yùn)行

監(jiān)控 Watch(面試常問(wèn))

樂(lè)觀鎖:實(shí)現(xiàn)秒殺

顧名思義,很樂(lè)觀,認(rèn)為什么時(shí)候都不會(huì)出現(xiàn)問(wèn)題,所以不會(huì)加鎖?。ǜ聰?shù)據(jù)的時(shí)候去判斷一下,在此期間是否有人修改過(guò)這個(gè)數(shù)據(jù))

獲取version更新的時(shí)候比較version

悲觀鎖

顧名思義,很悲觀,認(rèn)為什么時(shí)候都會(huì)出現(xiàn)問(wèn)題,無(wú)論做什么都會(huì)加鎖!

Redis實(shí)現(xiàn)樂(lè)觀鎖

執(zhí)行成功(單線程沒(méi)有干擾情況)

測(cè)試多線程修改值,使用watch可以當(dāng)作redis的樂(lè)觀鎖操作

演示‘

①開(kāi)啟倆個(gè),客戶端,模擬多線程情況

②左邊支出20元(但是不執(zhí)行事務(wù)),然后右邊修改money的數(shù)值

③左邊執(zhí)行事務(wù),發(fā)現(xiàn)執(zhí)行操作返回nil,查看money和out,發(fā)現(xiàn)事務(wù)并沒(méi)有被執(zhí)行(確實(shí)有樂(lè)觀鎖的效果)

如果修改失敗獲取最新的值就好(exec、unwatch、`discard都可以清除連接時(shí)所有的監(jiān)視)

小結(jié)

使用Redis實(shí)現(xiàn)樂(lè)觀鎖(watch監(jiān)聽(tīng)某一個(gè)key,獲取其最新的value)

在提交事務(wù)時(shí),如果key的value沒(méi)有發(fā)生變化,則成功執(zhí)行在提交事務(wù)時(shí),如果key的value發(fā)生了變化,則無(wú)法成功執(zhí)行

六、Jedis

1、什么是Jedis

Jedis是一個(gè)用java寫的Redis數(shù)據(jù)庫(kù)操作的客戶端,通過(guò)Jedis,可以很方便的對(duì)redis數(shù)據(jù)庫(kù)進(jìn)行操作

2、使用

①新建空maven項(xiàng)目

②導(dǎo)入依賴

redis.clients

jedis

3.3.0

com.alibaba

fastjson

1.2.70

③編碼

下面使用遠(yuǎn)程連接需要的操作:Jedis遠(yuǎn)程連接redis詳解(密碼設(shè)置、防火墻端口6379開(kāi)啟、去掉保護(hù))_jedis忽略證書連接redis-CSDN博客

連接數(shù)據(jù)庫(kù)

public class PingTest {

public static void main(String[] args) {

// 1. new Jedis 對(duì)象

Jedis jedis = new Jedis("ip地址",6379);

// 如果設(shè)置密碼 需要認(rèn)證,沒(méi)有設(shè)置忽略下面這條語(yǔ)句

jedis.auth("密碼");

/// jedis 所有的命令(方法)都是之前學(xué)的命令

System.out.println(jedis.ping());// 測(cè)試連接

}

}

1.操作

// 連通

Jedis jedis = new Jedis("ip地址", 6379);

jedis.auth("密碼");

//基本操作

System.out.println("清空數(shù)據(jù):" + jedis.flushAll());

System.out.println("判斷key(name)是否存在:" + jedis.exists("name"));

System.out.println("設(shè)置name的value:" + jedis.setnx("name", "liuyou"));

System.out.println("設(shè)置pwd的value:" + jedis.setnx("pwd", "密碼"));

System.out.println("打印所有的key:" + jedis.keys("*"));

System.out.println("獲取該name的value:" + jedis.get("name"));

System.out.println("刪除pwd:" + jedis.del("pwd"));

System.out.println("重命名name為username:" + jedis.rename("name", "username"));

System.out.println("打印所有的key:" + jedis.keys("*"));

System.out.println("返回當(dāng)前數(shù)據(jù)庫(kù)中key的數(shù)目:" + jedis.dbSize());

清空數(shù)據(jù):OK

判斷key(name)是否存在:false

設(shè)置name的value:1

設(shè)置pwd的value:1

打印所有的key:[pwd, name]

獲取該name的value:liuyou

刪除pwd:1

重命名name為username:OK

打印所有的key:[username]

返回當(dāng)前數(shù)據(jù)庫(kù)中key的數(shù)目:1

?2 關(guān)閉連接

jedis.close()

1 事務(wù)

// 連通

Jedis jedis = new Jedis("IP地址", 6379);

jedis.auth("密碼");

JSONObject jsonObject = new JSONObject();

jsonObject.put("hello","world");

jsonObject.put("name","liuyou");

jsonObject.put("pwd","密碼");

String s = jsonObject.toJSONString();

jedis.flushAll();

/// 加監(jiān)聽(tīng) watch

// jedis.watch("user");

// 開(kāi)啟事務(wù)

Transaction multi = jedis.multi();

try {

multi.set("user",s);

// 其他語(yǔ)句

// 執(zhí)行事務(wù)

multi.exec();

} catch (Exception e) {

// 取消事務(wù)

multi.discard();

e.printStackTrace();

} finally {

System.out.println(jedis.get("user"));

// 關(guān)閉連接

jedis.close();

}

七、SpringBoot整合

在SpringBoot2.x之后,原來(lái)的jedis被替換為lettuce

jedis

采用的直連,多個(gè)線程操作的話,是不安全的,如果想要避免不安全,使用jedis pool連接池!BIOlettuce

采用netty,實(shí)例可以在多個(gè)線程**享,不存在線程不安全問(wèn)題,可以減少線程數(shù)據(jù)了,性能高,NIO

①新建springboot項(xiàng)目

②?RedisAutoConfiguration源碼分析

③整合測(cè)試

1、導(dǎo)入依賴

org.springframework.boot

spring-boot-starter-data-redis

2、配置Redis(application.xml)

# SpringBoot 整合Redis

spring.redis.host=xxx

spring.redis.port=6379

spring.redis.password=liuyou

3、編寫測(cè)試類

@SpringBootTest

class Redis02SpringbootApplicationTests {

@Autowired

RedisTemplate redisTemplate;

@Test

void contextLoads() {

//redisTemplate

// 1.使用redisTemplate.opsForxxx 操作對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)

// 2.可使用redisTemplate 進(jìn)行簡(jiǎn)單的key操作,如multi、move、watch、keys 等操作

/// 3.可使用獲取連接,通過(guò)連接進(jìn)行更多操作

// RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();

// RedisZSetCommands redisZSetCommands = connection.zSetCommands();

// 這里只使用1.演示

ValueOperations str = redisTemplate.opsForValue();

str.set("name","liuminkai劉民鍇");

System.out.println(str.get("name"));

}

}

但是存在問(wèn)題,沒(méi)有序列化,存儲(chǔ)在Redis中的中文會(huì)被轉(zhuǎn)義,如下圖

為啥會(huì)出現(xiàn)這個(gè)情況? RedisTemplate默認(rèn)序列化使用JDK的,我們需要使用JSON格式

如何解決?我們需要編寫自定義Redis配置類,自定義RedisTemplate

④自定義RedisTemplate

@Configuration

public class MyRedisConfig {

// 更改Key :Object ==> String 符合日常使用

// 自己定義了一個(gè) RedisTemplate

@Bean

@SuppressWarnings("all")

public RedisTemplate redisTemplate(RedisConnectionFactory factory) {

// 我們?yōu)榱俗约洪_(kāi)發(fā)方便,一般直接使用

RedisTemplate template = new RedisTemplate();

template.setConnectionFactory(factory);

// 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;

}

}

自定義RedisTemplate后,再啟動(dòng)③的測(cè)試類,結(jié)果Redis中正常顯示

RedisUtils工具類

日常開(kāi)發(fā)我們都不會(huì)使用原始的RedisTemplate,都會(huì)封裝一個(gè)RedisUtils工具類便于使用

package com.liuyou.utils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.stereotype.Component;

import org.springframework.util.CollectionUtils;

import java.util.Map;

import java.util.Set;

import java.util.List;

import java.util.concurrent.TimeUnit;

@Component

public final class RedisUtils {

@Autowired

private RedisTemplate redisTemplate;

// =============================common============================

/**

* 指定緩存失效時(shí)間

* @param key 鍵

* @param time 時(shí)間(秒)

*/

public boolean expire(String key, long time) {

try {

if (time > 0) {

redisTemplate.expire(key, time, TimeUnit.SECONDS);

}

return true;

} catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

* 根據(jù)key 獲取過(guò)期時(shí)間

* @param key 鍵 不能為null

* @return 時(shí)間(秒) 返回0代表為永久有效

*/

public long getExpire(String key) {

return redisTemplate.getExpire(key, TimeUnit.SECONDS);

}

/**

* 判斷key是否存在

* @param key 鍵

* @return true 存在 false不存在

*/

public boolean hasKey(String key) {

try {

return redisTemplate.hasKey(key);

} catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

* 刪除緩存

* @param key 可以傳一個(gè)值 或多個(gè)

*/

@SuppressWarnings("unchecked")

public void del(String... key) {

if (key != null && key.length > 0) {

if (key.length == 1) {

redisTemplate.delete(key[0]);

} else {

redisTemplate.delete(CollectionUtils.arrayToList(key));

}

}

}

// ============================String=============================

/**

* 普通緩存獲取

* @param key 鍵

* @return 值

*/

public Object get(String key) {

return key == null ? null : redisTemplate.opsForValue().get(key);

}

/**

* 普通緩存放入

* @param key 鍵

* @param value 值

* @return true成功 false失敗

*/

public boolean set(String key, Object value) {

try {

redisTemplate.opsForValue().set(key, value);

return true;

} catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

* 普通緩存放入并設(shè)置時(shí)間

* @param key 鍵

* @param value 值

* @param time 時(shí)間(秒) time要大于0 如果time小于等于0 將設(shè)置無(wú)限期

* @return true成功 false 失敗

*/

public boolean set(String key, Object value, long time) {

try {

if (time > 0) {

redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);

} else {

set(key, value);

}

return true;

} catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

* 遞增

* @param key 鍵

* @param delta 要增加幾(大于0)

*/

public long incr(String key, long delta) {

if (delta < 0) {

throw new RuntimeException("遞增因子必須大于0");

}

return redisTemplate.opsForValue().increment(key, delta);

}

/**

* 遞減

* @param key 鍵

* @param delta 要減少幾(小于0)

*/

public long decr(String key, long delta) {

if (delta < 0) {

throw new RuntimeException("遞減因子必須大于0");

}

return redisTemplate.opsForValue().increment(key, -delta);

}

// ================================Map=================================

/**

* HashGet

* @param key 鍵 不能為null

* @param item 項(xiàng) 不能為null

*/

public Object hget(String key, String item) {

return redisTemplate.opsForHash().get(key, item);

}

/**

* 獲取hashKey對(duì)應(yīng)的所有鍵值

* @param key 鍵

* @return 對(duì)應(yīng)的多個(gè)鍵值

*/

public Map hmget(String key) {

return redisTemplate.opsForHash().entries(key);

}

/**

* HashSet

* @param key 鍵

* @param map 對(duì)應(yīng)多個(gè)鍵值

*/

public boolean hmset(String key, Map map) {

try {

redisTemplate.opsForHash().putAll(key, map);

return true;

} catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

* HashSet 并設(shè)置時(shí)間

* @param key 鍵

* @param map 對(duì)應(yīng)多個(gè)鍵值

* @param time 時(shí)間(秒)

* @return true成功 false失敗

*/

public boolean hmset(String key, Map map, long time) {

try {

redisTemplate.opsForHash().putAll(key, map);

if (time > 0) {

expire(key, time);

}

return true;

} catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

* 向一張hash表中放入數(shù)據(jù),如果不存在將創(chuàng)建

*

* @param key 鍵

* @param item 項(xiàng)

* @param value 值

* @return true 成功 false失敗

*/

public boolean hset(String key, String item, Object value) {

try {

redisTemplate.opsForHash().put(key, item, value);

return true;

} catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

* 向一張hash表中放入數(shù)據(jù),如果不存在將創(chuàng)建

*

* @param key 鍵

* @param item 項(xiàng)

* @param value 值

* @param time 時(shí)間(秒) 注意:如果已存在的hash表有時(shí)間,這里將會(huì)替換原有的時(shí)間

* @return true 成功 false失敗

*/

public boolean hset(String key, String item, Object value, long time) {

try {

redisTemplate.opsForHash().put(key, item, value);

if (time > 0) {

expire(key, time);

}

return true;

} catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

* 刪除hash表中的值

*

* @param key 鍵 不能為null

* @param item 項(xiàng) 可以使多個(gè) 不能為null

*/

public void hdel(String key, Object... item) {

redisTemplate.opsForHash().delete(key, item);

}

/**

* 判斷hash表中是否有該項(xiàng)的值

*

* @param key 鍵 不能為null

* @param item 項(xiàng) 不能為null

* @return true 存在 false不存在

*/

public boolean hHasKey(String key, String item) {

return redisTemplate.opsForHash().hasKey(key, item);

}

/**

* hash遞增 如果不存在,就會(huì)創(chuàng)建一個(gè) 并把新增后的值返回

*

* @param key 鍵

* @param item 項(xiàng)

* @param by 要增加幾(大于0)

*/

public double hincr(String key, String item, double by) {

return redisTemplate.opsForHash().increment(key, item, by);

}

/**

* hash遞減

*

* @param key 鍵

* @param item 項(xiàng)

* @param by 要減少記(小于0)

*/

public double hdecr(String key, String item, double by) {

return redisTemplate.opsForHash().increment(key, item, -by);

}

// ============================set=============================

/**

* 根據(jù)key獲取Set中的所有值

* @param key 鍵

*/

public Set sGet(String key) {

try {

return redisTemplate.opsForSet().members(key);

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

/**

* 根據(jù)value從一個(gè)set中查詢,是否存在

*

* @param key 鍵

* @param value 值

* @return true 存在 false不存在

*/

public boolean sHasKey(String key, Object value) {

try {

return redisTemplate.opsForSet().isMember(key, value);

} catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

* 將數(shù)據(jù)放入set緩存

*

* @param key 鍵

* @param values 值 可以是多個(gè)

* @return 成功個(gè)數(shù)

*/

public long sSet(String key, Object... values) {

try {

return redisTemplate.opsForSet().add(key, values);

} catch (Exception e) {

e.printStackTrace();

return 0;

}

}

/**

* 將set數(shù)據(jù)放入緩存

*

* @param key 鍵

* @param time 時(shí)間(秒)

* @param values 值 可以是多個(gè)

* @return 成功個(gè)數(shù)

*/

public long sSetAndTime(String key, long time, Object... values) {

try {

Long count = redisTemplate.opsForSet().add(key, values);

if (time > 0){

expire(key, time);

}

return count;

} catch (Exception e) {

e.printStackTrace();

return 0;

}

}

/**

* 獲取set緩存的長(zhǎng)度

*

* @param key 鍵

*/

public long sGetSetSize(String key) {

try {

return redisTemplate.opsForSet().size(key);

} catch (Exception e) {

e.printStackTrace();

return 0;

}

}

/**

* 移除值為value的

*

* @param key 鍵

* @param values 值 可以是多個(gè)

* @return 移除的個(gè)數(shù)

*/

public long setRemove(String key, Object... values) {

try {

Long count = redisTemplate.opsForSet().remove(key, values);

return count;

} catch (Exception e) {

e.printStackTrace();

return 0;

}

}

// ===============================list=================================

/**

* 獲取list緩存的內(nèi)容

*

* @param key 鍵

* @param start 開(kāi)始

* @param end 結(jié)束 0 到 -1代表所有值

*/

public List lGet(String key, long start, long end) {

try {

return redisTemplate.opsForList().range(key, start, end);

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

/**

* 獲取list緩存的長(zhǎng)度

*

* @param key 鍵

*/

public long lGetListSize(String key) {

try {

return redisTemplate.opsForList().size(key);

} catch (Exception e) {

e.printStackTrace();

return 0;

}

}

/**

* 通過(guò)索引 獲取list中的值

*

* @param key 鍵

* @param index 索引 index>=0時(shí), 0 表頭,1 第二個(gè)元素,依次類推;index<0時(shí),-1,表尾,-2倒數(shù)第二個(gè)元素,依次類推

*/

public Object lGetIndex(String key, long index) {

try {

return redisTemplate.opsForList().index(key, index);

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

/**

* 將list放入緩存

*

* @param key 鍵

* @param value 值

*/

public boolean lSet(String key, Object value) {

try {

redisTemplate.opsForList().rightPush(key, value);

return true;

} catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

* 將list放入緩存

* @param key 鍵

* @param value 值

* @param time 時(shí)間(秒)

*/

public boolean lSet(String key, Object value, long time) {

try {

redisTemplate.opsForList().rightPush(key, value);

if (time > 0){

expire(key, time);

}

return true;

} catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

* 將list放入緩存

*

* @param key 鍵

* @param value 值

* @return

*/

public boolean lSet(String key, List value) {

try {

redisTemplate.opsForList().rightPushAll(key, value);

return true;

} catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

* 將list放入緩存

*

* @param key 鍵

* @param value 值

* @param time 時(shí)間(秒)

* @return

*/

public boolean lSet(String key, List value, long time) {

try {

redisTemplate.opsForList().rightPushAll(key, value);

if (time > 0){

expire(key, time);

}

return true;

} catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

* 根據(jù)索引修改list中的某條數(shù)據(jù)

*

* @param key 鍵

* @param index 索引

* @param value 值

* @return

*/

public boolean lUpdateIndex(String key, long index, Object value) {

try {

redisTemplate.opsForList().set(key, index, value);

return true;

} catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

* 移除N個(gè)值為value

*

* @param key 鍵

* @param count 移除多少個(gè)

* @param value 值

* @return 移除的個(gè)數(shù)

*/

public long lRemove(String key, long count, Object value) {

try {

Long remove = redisTemplate.opsForList().remove(key, count, value);

return remove;

} catch (Exception e) {

e.printStackTrace();

return 0;

}

}

}

使用該工具類直接@Autowired注入即可

進(jìn)階

學(xué)會(huì)前面的所有內(nèi)容 ==> Redis基礎(chǔ)

高級(jí)操作都在后面

八、Redis.conf詳解

我們啟動(dòng)Redis,一般都是通過(guò)Redis.conf啟動(dòng)(我前面是使用安裝服務(wù)的6379.conf啟動(dòng))

因此,我們必須了解Redis.conf的配置,才能更好理解和使用Redis

單位

大小寫不敏感

包含

可以包含多個(gè)配置文件(即,這些文件導(dǎo)入到主配置文件?Redis.conf?中)

網(wǎng)絡(luò)

bind 0.0.0.0 # IP(默認(rèn)127.0.0.1)

protected-mode no # 保護(hù)模式(默認(rèn)yes)

port 6379 # 端口設(shè)置(默認(rèn)6379)

通用

daemonize yes # 以守護(hù)進(jìn)程方式運(yùn)行,即后臺(tái)運(yùn)行(默認(rèn)no)

pidfile /var/run/redis_6379.pid # 如果以后臺(tái)運(yùn)行,必須指定一個(gè)pid文件

# 日志

# Specify the server verbosity level.

# This can be one of:

# debug (大量信息, 使用于測(cè)試或開(kāi)發(fā)階段)

# verbose (許多很少有用的信息,但不像調(diào)試級(jí)別那樣混亂)

# notice (比較冗長(zhǎng),你可能想在生產(chǎn)環(huán)境中使用)

# warning (只有非常重要/關(guān)鍵的消息被記錄下來(lái))

loglevel notice # 默認(rèn)notice

logfile "" # 日志的文件位置名

databases 16 # 數(shù)據(jù)庫(kù)的數(shù)量(默認(rèn)16)

always-show-logo yes # 是否開(kāi)啟 logo (默認(rèn)yes)

快照

持久化,在規(guī)定時(shí)間內(nèi),執(zhí)行了多少次操作,會(huì)被持久化到文件(.rdb,.aof)

save 900 1 # 900秒內(nèi)(15分鐘),如果至少有1個(gè)Key進(jìn)行修改,我們就進(jìn)行持久化操作

save 300 10 # 300秒內(nèi)(5分鐘),如果至少有10個(gè)Key進(jìn)行修改,我們就進(jìn)行持久化操作

save 60 10000 # 60秒內(nèi)(1分鐘),如果至少有10000個(gè)Key進(jìn)行修改,我們就進(jìn)行持久化操作

stop-writes-on-bgsave-error yes # 持久化如果出錯(cuò),是否還需要繼續(xù)工作(默認(rèn)yes)

rdbcompression yes # 是否壓縮rdb文件(默認(rèn)yes),會(huì)消耗一些CPU資源

rdbchecksum yes # 保存rdb文件時(shí),進(jìn)行錯(cuò)誤檢查檢驗(yàn)

dir ./ # rdb文件保存的目錄

主從復(fù)制 REPLICATION

安全 SECURITY

requirepass 你的密碼 # 設(shè)置密碼(默認(rèn)被注釋著需要自己解開(kāi)注釋)

當(dāng)然可以通過(guò)命令行配置(臨時(shí),服務(wù)重啟失效)

客戶端限制

# maxclients 10000 # 限制最多10000個(gè)客戶端訪問(wèn)(默認(rèn)注釋)

內(nèi)存管理

# maxmemory # 最大內(nèi)存設(shè)置(默認(rèn)注釋)

# maxmemory-policy noeviction # 內(nèi)存達(dá)到上限之后的處理策略(默認(rèn)noeviction)

# 1、volatile-lru:只對(duì)設(shè)置了過(guò)期時(shí)間的key進(jìn)行LRU(默認(rèn)值)

# 2、allkeys-lru : 刪除lru算法的key

# 3、volatile-random:隨機(jī)刪除即將過(guò)期key

# 4、allkeys-random:隨機(jī)刪除

# 5、volatile-ttl : 刪除即將過(guò)期的

# 6、noeviction : 永不過(guò)期,返回錯(cuò)誤

APPEND ONLY MODE (AOF配置)

appendonly no # 默認(rèn)是不開(kāi)啟aof的,默認(rèn)使用rdb方式持久化

appendfilename "appendonly.aof" # 持久化的文件名

# appendfsync always # 每次修改都會(huì)同步,銷耗性能

appendfsync everysec # 每秒執(zhí)行一次同步,可能會(huì)丟失這1秒的數(shù)據(jù)

# appendfsync no # 不同步,操作系統(tǒng)自己同步數(shù)據(jù),速度最快

九、Redis持久化(重點(diǎn))

Redis是內(nèi)存數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)狀態(tài)斷電及失,因此Redis提供了持久化功能(內(nèi)存數(shù)據(jù)寫入磁盤)

1、RDB(Redis DataBase)

RDB持久化是指在指定的時(shí)間間隔內(nèi)將內(nèi)存中的數(shù)據(jù)集快照寫入磁盤,實(shí)際操作過(guò)程是fork一個(gè)子進(jìn)程,先將數(shù)據(jù)集寫入臨時(shí)文件,寫入成功后,再替換之前的文件,用二進(jìn)制壓縮存儲(chǔ)。 保存文件格式?dump.rdb

設(shè)置RDB文件保存條件

重啟服務(wù)

systemctl restart redis_6379

結(jié)果測(cè)試

1.查看rdb文件存放的目錄

2.刪除已有的dump.rdb文件

3.添加5個(gè)key

RDB文件生成觸發(fā)機(jī)制

1.滿足redis.conf中,快照save生成條件

2.使用flushall命令,自動(dòng)生成一個(gè)RDB文件

3.退出redis

RDB文件恢復(fù)

只需要將RDB文件放入Redis啟動(dòng)目錄就可以了,Redis自動(dòng)加載

優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

適合大規(guī)模的數(shù)據(jù)恢復(fù)!對(duì)數(shù)據(jù)完整性要求不高缺點(diǎn):

需要一定的時(shí)間間隔進(jìn)程操作;如果redis意外宕機(jī),最后一次修改數(shù)據(jù)就沒(méi)有了fork進(jìn)程的時(shí)候,會(huì)占用一定的空間

2、AOF(Append Only File)

AOF持久化以日志的形式記錄服務(wù)器所處理的每一個(gè)寫、刪除操作,查詢操作不會(huì)記錄,只許追加文件,不許改寫文件。以文本的方式記錄,可以打開(kāi)文件看到詳細(xì)的操作記錄。

保存文件格式?appendonly.aof

aof默認(rèn)不開(kāi)啟,需要到配置文件中開(kāi)啟

重啟redis后,appendonly.aof文件自動(dòng)生成

客戶端進(jìn)行一些操作

appendonly.aof文件內(nèi)容,日志形式記錄

重寫規(guī)制

如果aof文件大于64mb,就會(huì)fork一個(gè)新進(jìn)程來(lái)將我們的文件進(jìn)行重寫(清除之前的64mb)

錯(cuò)誤修復(fù)

如果aof文件有錯(cuò)誤,redis是啟動(dòng)不了的,可以使用官方自帶?redis-check-aof --fix aof文件進(jìn)行修復(fù)

優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

每一次修改都同步,文件完整性會(huì)更好每秒同步一次,可能會(huì)丟失一秒數(shù)據(jù)缺點(diǎn)

相對(duì)于數(shù)據(jù)文件來(lái)說(shuō),aof遠(yuǎn)遠(yuǎn)大于rdb,修復(fù)速度比rdb慢aof運(yùn)行速率比rdb慢(追加,頻繁IO操作)

擴(kuò)展

十、Redis發(fā)布訂閱

Redis 發(fā)布訂閱(pub/sub)是一種消息通信模式:發(fā)送者(pub)發(fā)送消息,訂閱者(sub)接收消息。微信、微博、關(guān)注系統(tǒng)!

Redis客戶端可以訂閱任意數(shù)量的頻道

訂閱/發(fā)布消息圖:

下圖展示了頻道 channel1 , 以及訂閱這個(gè)頻道的三個(gè)客戶端 —— client2 、 client5 和 client1 之間的關(guān)系:

當(dāng)有新消息通過(guò) PUBLISH 命令發(fā)送給頻道 channel1 時(shí), 這個(gè)消息就會(huì)被發(fā)送給訂閱它的三個(gè)客戶端:

命令

這些命令被廣泛用于構(gòu)建即時(shí)通信應(yīng)用,比如網(wǎng)絡(luò)聊天室(chatroom)和實(shí)時(shí)廣播、實(shí)時(shí)提醒等。

命令描述PSUBSCRIBE pattern [pattern..]訂閱一個(gè)或多個(gè)符合給定模式的頻道。PUNSUBSCRIBE pattern [pattern..]退訂一個(gè)或多個(gè)符合給定模式的頻道。PUBSUB subcommand [argument[argument]]查看訂閱與發(fā)布系統(tǒng)狀態(tài)。PUBLISH channel message向指定頻道發(fā)布消息SUBSCRIBE channel [channel..]訂閱給定的一個(gè)或多個(gè)頻道。SUBSCRIBE channel [channel..]退訂一個(gè)或多個(gè)頻道

測(cè)試

127.0.0.1:6379> subscribe blog # 訂閱頻道

Reading messages... (press Ctrl-C to quit) # 等待推送信息

1) "subscribe"

2) "blog"

3) (integer) 1

1) "message" # 消息

2) "blog" # 消息來(lái)自頻道

3) "hello world!" # 消息內(nèi)容

127.0.0.1:6379> publish blog "hello world!" # 發(fā)送消息到頻道

(integer) 1

127.0.0.1:6379>

原理

每個(gè) Redis 服務(wù)器進(jìn)程都維持著一個(gè)表示服務(wù)器狀態(tài)的 redis.h/redisServer 結(jié)構(gòu), 結(jié)構(gòu)的 pubsub_channels 屬性是一個(gè)字典, 這個(gè)字典就用于保存訂閱頻道的信息,其中,字典的鍵為正在被訂閱的頻道, 而字典的值則是一個(gè)鏈表, 鏈表中保存了所有訂閱這個(gè)頻道的客戶端。

客戶端訂閱,就被鏈接到對(duì)應(yīng)頻道的鏈表的尾部,退訂則就是將客戶端節(jié)點(diǎn)從鏈表中移除。

使用場(chǎng)景:

實(shí)時(shí)消息系統(tǒng)!實(shí)時(shí)聊天!(頻道當(dāng)作聊天室,將信息回顯給所有人)訂閱,關(guān)注系統(tǒng)都是可以

復(fù)雜的情況,使用專業(yè)的消息中間件

做訂閱的缺點(diǎn)

如果一個(gè)客戶端訂閱了頻道,但自己讀取消息的速度卻不夠快的話,那么不斷積壓的消息會(huì)使redis輸出緩沖區(qū)的體積變得越來(lái)越大,這可能使得redis本身的速度變慢,甚至直接崩潰。這和數(shù)據(jù)傳輸可靠性有關(guān),如果在訂閱方斷線,那么他將會(huì)丟失所有在短線期間發(fā)布者發(fā)布的消息。

十一、主從復(fù)制

概念

主從復(fù)制,是指將一臺(tái)Redis服務(wù)器的數(shù)據(jù),復(fù)制到其他的Redis服務(wù)器。前者稱為主節(jié)點(diǎn)(Master/Leader),后者稱為從節(jié)點(diǎn)(Slave/Follower), 數(shù)據(jù)的復(fù)制是單向的!只能由主節(jié)點(diǎn)復(fù)制到從節(jié)點(diǎn)(主節(jié)點(diǎn)以寫為主、從節(jié)點(diǎn)以讀為主)。

主從復(fù)制的主要作用

數(shù)據(jù)冗余:主從復(fù)制實(shí)現(xiàn)了數(shù)據(jù)的熱備份,是持久化之外的一種數(shù)據(jù)冗余的方式。故障恢復(fù):當(dāng)主節(jié)點(diǎn)故障時(shí),從節(jié)點(diǎn)可以暫時(shí)替代主節(jié)點(diǎn)提供服務(wù),是一種服務(wù)冗余的方式負(fù)載均衡:在主從復(fù)制的基礎(chǔ)上,配合讀寫分離,由主節(jié)點(diǎn)進(jìn)行寫操作,從節(jié)點(diǎn)進(jìn)行讀操作,分擔(dān)服務(wù)器的負(fù)載;尤其是在多讀少寫的場(chǎng)景下,通過(guò)多個(gè)從節(jié)點(diǎn)分擔(dān)負(fù)載,提高并發(fā)量。高可用基石:主從復(fù)制還是哨兵和集群能夠?qū)嵤┑幕A(chǔ)。

一般來(lái)說(shuō),要將Redis運(yùn)用與工程項(xiàng)目中,只使用一臺(tái)Redis是萬(wàn)萬(wàn)不能的(避免宕機(jī),一主二從),原因如下:

從結(jié)構(gòu)上,單個(gè)Redis服務(wù)器會(huì)發(fā)生單點(diǎn)故障,并且一臺(tái)服務(wù)器需要處理所有的請(qǐng)求負(fù)載,壓力較大從容量上,單個(gè)Redis服務(wù)器內(nèi)存容量有限,就算一臺(tái)Redis服務(wù)器內(nèi)存容量為256G,也不能將所有內(nèi)存用作Redis存儲(chǔ)內(nèi)存,一般來(lái)說(shuō),單臺(tái)服務(wù)器最大使用內(nèi)存不超過(guò)20G。

只要在公司中,不可能使用單機(jī)(有瓶頸),必須配置集群、使用主從復(fù)制

環(huán)境配置

只需配置從庫(kù),無(wú)需配置主庫(kù)

查看主從復(fù)制信息:

默認(rèn)情況下,每一個(gè)Redis服務(wù)器都是主節(jié)點(diǎn)

127.0.0.1:6379> info replication

# Replication

role:master # 主節(jié)點(diǎn)

connected_slaves:0 # 沒(méi)有從節(jié)點(diǎn)

master_replid:7776dea8df483b02d12cd482d2034ba55ec7dab0

master_replid2:0000000000000000000000000000000000000000

master_repl_offset:0

second_repl_offset:-1

repl_backlog_active:0

repl_backlog_size:1048576

repl_backlog_first_byte_offset:0

repl_backlog_histlen:0

1、復(fù)制配置文件redis.conf到Redis安裝目錄下

2、再?gòu)脑撐募截惓?個(gè)文件

主:redis_6379.conf

從:redis_6380.conf、redis_6381.conf

3、修改主配置文件

由于端口和后臺(tái)默認(rèn)運(yùn)行pid都是6379的,就不改了

4、修改從配置文件

下面以?redis_6380.conf?為例,?redis_6381.conf?同理

配置文件修改的信息

端口(92行)pid進(jìn)程名(244行)日志文件名(257行)rdb文件名(339行)

5、啟動(dòng)服務(wù)(單機(jī)多服務(wù))

cd /usr/local/bin # 進(jìn)入配置文件所在目錄

[root@liuyou bin]# redis-server redis_6379.conf

[root@liuyou bin]# redis-server redis_6380.conf

[root@liuyou bin]# redis-server redis_6381.conf

[root@liuyou bin]# ps -ef | grep redis # 查看啟動(dòng)狀態(tài)

root 2862 1 0 13:13 ? 00:00:00 redis-server 0.0.0.0:6379

root 2868 1 0 13:13 ? 00:00:00 redis-server 0.0.0.0:6380

root 2874 1 0 13:13 ? 00:00:00 redis-server 0.0.0.0:6381

root 2880 2393 0 13:13 pts/0 00:00:00 grep --color=auto redis

6、登錄客戶端

①開(kāi)啟4個(gè)窗口,前三用于主從復(fù)制,最后一個(gè)用于測(cè)試

②登錄(注意端口)

7、一主二從

默認(rèn)情況下,每一個(gè)Redis服務(wù)器都是主節(jié)點(diǎn)

一般情況下,只配置從機(jī)

如果有密碼,需要在從配置文件中,進(jìn)行配置,后面會(huì)解釋

下面以 窗口3(端口為6381) 為例,窗口2同理

使用slaveof 指定 主節(jié)點(diǎn) ip 和 端口(臨時(shí)配置)

查看主節(jié)點(diǎn),主從復(fù)制信息

有密碼配置(+永久配置)

配置完重啟服務(wù)

測(cè)試

Redis只允許,主機(jī)寫,從機(jī)讀

主機(jī)寫

從機(jī)讀

從機(jī)不能寫

主機(jī)斷開(kāi)連接,從機(jī)依舊連接主機(jī),但是沒(méi)有寫操作,如果從機(jī)中途恢復(fù)正常,從機(jī)依舊可以獲取主機(jī)寫的內(nèi)容

如果使用命令行配置,從機(jī)重啟,就會(huì)變?yōu)橹鳈C(jī)(只有變?yōu)閺臋C(jī),才能獲取之前主機(jī)內(nèi)容)

從機(jī)斷開(kāi)連接,期間,主機(jī)繼續(xù)寫新內(nèi)容,只要從機(jī)恢復(fù),就可獲得主機(jī)寫的新內(nèi)容

復(fù)制原理

Slave 啟動(dòng)成功連接到Master后會(huì)發(fā)送一個(gè)sync命令

Master接收到命令,啟動(dòng)后臺(tái)的存盤進(jìn)程,同時(shí)收集所有接收到的用于修改數(shù)據(jù)集命令,在后臺(tái)進(jìn)程執(zhí)行完畢之后,Master將傳送整個(gè)數(shù)據(jù)文件到Slave,并完成一次完全同步

全量復(fù)制:而Slave服務(wù)在接收到數(shù)據(jù)庫(kù)文件數(shù)據(jù)后,將其存盤并加載到內(nèi)存中

增量復(fù)制:Master繼續(xù)將新的所有收集到修改命令依次傳給Slave,完成同步

但是只要重新連接Master,一次完全同步(全量復(fù)制)將被自動(dòng)執(zhí)行。

8、毛毛蟲(chóng)配置(主從)

上一個(gè)M連接下一個(gè)S,(可以看做主從復(fù)制的一種實(shí)現(xiàn))

配置只需:將上面配好的,窗口3的主機(jī)改為窗口2即可

9、宕機(jī)手動(dòng)配置主機(jī)

slaveof no one # 如果主機(jī)斷開(kāi)連接,從機(jī)可以使用該命令,讓自己變?yōu)橹鳈C(jī),其他節(jié)點(diǎn)連到該節(jié)點(diǎn)

如果主機(jī)如果會(huì)來(lái)了,也沒(méi)有從機(jī)連接上它。

十二、哨兵模式

自動(dòng)選舉Redis主服務(wù)器(如果主服務(wù)器宕機(jī))

在?Redis2.8之前,采用手動(dòng)配置主機(jī)的形式(會(huì)導(dǎo)致一段時(shí)間服務(wù)不可用)

Redis2.8之后,Redis正是提供了Sentinel(哨兵)來(lái)解決這個(gè)問(wèn)題(主機(jī)宕機(jī),根據(jù)投票自動(dòng)在從機(jī)中選出新主機(jī))

哨兵模式是一種特殊的模式,首先Redis提供了哨兵的命令,哨兵是一個(gè)獨(dú)立的進(jìn)程,他會(huì)獨(dú)立運(yùn)行。其原理是哨兵通過(guò)發(fā)送命令,等待Redis服務(wù)器響應(yīng),從而監(jiān)控運(yùn)行的多個(gè)Redis實(shí)例

單哨兵模式

哨兵的作用:

通過(guò)發(fā)送命令,讓Redis服務(wù)器返回監(jiān)控其運(yùn)行狀態(tài),包括主服務(wù)器和從服務(wù)器當(dāng)哨兵監(jiān)測(cè)到master宕機(jī),會(huì)自動(dòng)將slave切換到master,然后通過(guò)?發(fā)布訂閱模式?通知其他的從服務(wù)器,修改配置文件,讓他們切換主機(jī)

多哨兵模式

假設(shè)主服務(wù)器宕機(jī),哨兵1先檢測(cè)到這個(gè)結(jié)果,系統(tǒng)并不會(huì)馬上進(jìn)行failover過(guò)程,僅僅是哨兵1主觀的認(rèn)為主服務(wù)器不可用,這個(gè)現(xiàn)象稱為主觀下線。

當(dāng)其他哨兵也檢測(cè)到主服務(wù)器不可用,并且達(dá)到一定數(shù)量時(shí),那么哨兵之間就會(huì)進(jìn)行一次投票,投票的結(jié)果有一個(gè)哨兵發(fā)起,進(jìn)行failover故障轉(zhuǎn)移操作。

切換成功后,就會(huì)通過(guò)發(fā)布訂閱模式,讓各個(gè)哨兵把自己監(jiān)控的從服務(wù)器實(shí)現(xiàn)切換主機(jī),這個(gè)時(shí)候稱為客觀下線

測(cè)試(一主二從,單哨兵)

1、配置哨兵配置文件(文件名?sentinel.conf)

文件名不能寫錯(cuò),下面是文件內(nèi)容(當(dāng)然這個(gè)文件需要自己創(chuàng)建)

# sentinel monitor 被監(jiān)控的名稱 host port 1

# 1 表示 主機(jī)宕機(jī),從機(jī)投票選舉

sentinel monitor myredis 127.0.0.1 6379 1

2、啟動(dòng)哨兵模式

如果被監(jiān)控有密碼 需在?sentinel.conf?配置文件中,追加

# sentinel auth-pass 被監(jiān)控主機(jī)名稱

sentinel auth-pass myredis

redis-sentinel sentinel.conf

3、關(guān)閉主機(jī),測(cè)試選舉情況

①主機(jī)關(guān)閉

②哨兵詳情

③檢查窗口3(端口為6381)

④我們恢復(fù)窗口1(即之前的主機(jī)),看看情況

變成從機(jī)

優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

哨兵集群,基于主從復(fù)制模式,所有的主從配置優(yōu)點(diǎn),它全有主從可以切換,故障可以轉(zhuǎn)移,系統(tǒng)的可用性就會(huì)更好哨兵模式就是主從模式的升級(jí),手動(dòng)到自動(dòng),更加健壯缺點(diǎn)

Redis不好在線擴(kuò)容的,集群容量一旦達(dá)到上線,在線擴(kuò)容十分麻煩實(shí)現(xiàn)哨兵模式的配置其實(shí)是很麻煩的,里面有很多選擇

哨兵模式的全部配置

# Example sentinel.conf

# 哨兵sentinel實(shí)例運(yùn)行的端口 默認(rèn)26379

# 如果有哨兵集群 需要配置多個(gè)端口

port 26379

# 哨兵sentinel的工作目錄

dir /tmp

# 哨兵sentinel監(jiān)控的redis主節(jié)點(diǎn)的 ip port

# master-name 可以自己命名的主節(jié)點(diǎn)名字 只能由字母A-z、數(shù)字0-9 、這三個(gè)字符".-_"組成。

# quorum 當(dāng)這些quorum個(gè)數(shù)sentinel哨兵認(rèn)為master主節(jié)點(diǎn)失聯(lián) 那么這時(shí) 客觀上認(rèn)為主節(jié)點(diǎn)失聯(lián)了

# sentinel monitor

sentinel monitor mymaster 127.0.0.1 6379 1

# 當(dāng)在Redis實(shí)例中開(kāi)啟了requirepass foobared 授權(quán)密碼 這樣所有連接Redis實(shí)例的客戶端都要提供密碼

# 設(shè)置哨兵sentinel 連接主從的密碼 注意必須為主從設(shè)置一樣的驗(yàn)證密碼

# sentinel auth-pass

sentinel auth-pass mymaster MySUPER--secret-0123passw0rd

# 指定多少毫秒之后 主節(jié)點(diǎn)沒(méi)有應(yīng)答哨兵sentinel 此時(shí) 哨兵主觀上認(rèn)為主節(jié)點(diǎn)下線 默認(rèn)30秒

# sentinel down-after-milliseconds

sentinel down-after-milliseconds mymaster 30000

# 這個(gè)配置項(xiàng)指定了在發(fā)生failover主備切換時(shí)最多可以有多少個(gè)slave同時(shí)對(duì)新的master進(jìn)行 同步,

# 這個(gè)數(shù)字越小,完成failover所需的時(shí)間就越長(zhǎng),

# 但是如果這個(gè)數(shù)字越大,就意味著越 多的slave因?yàn)閞eplication而不可用。

# 可以通過(guò)將這個(gè)值設(shè)為 1 來(lái)保證每次只有一個(gè)slave 處于不能處理命令請(qǐng)求的狀態(tài)。

# sentinel parallel-syncs

sentinel parallel-syncs mymaster 1

# 故障轉(zhuǎn)移的超時(shí)時(shí)間 failover-timeout 可以用在以下這些方面:

#1. 同一個(gè)sentinel對(duì)同一個(gè)master兩次failover之間的間隔時(shí)間。

#2. 當(dāng)一個(gè)slave從一個(gè)錯(cuò)誤的master那里同步數(shù)據(jù)開(kāi)始計(jì)算時(shí)間。直到slave被糾正為向正確的master那里同步數(shù)據(jù)時(shí)。

#3.當(dāng)想要取消一個(gè)正在進(jìn)行的failover所需要的時(shí)間。

#4.當(dāng)進(jìn)行failover時(shí),配置所有slaves指向新的master所需的最大時(shí)間。不過(guò),即使過(guò)了這個(gè)超時(shí),slaves依然會(huì)被正確配置為指向master,但是就不按parallel-syncs所配置的規(guī)則來(lái)了

# 默認(rèn)三分鐘

# sentinel failover-timeout

sentinel failover-timeout mymaster 180000

# SCRIPTS EXECUTION

#配置當(dāng)某一事件發(fā)生時(shí)所需要執(zhí)行的腳本,可以通過(guò)腳本來(lái)通知管理員,例如當(dāng)系統(tǒng)運(yùn)行不正常時(shí)發(fā)郵件通知相關(guān)人員。

#對(duì)于腳本的運(yùn)行結(jié)果有以下規(guī)則:

#若腳本執(zhí)行后返回1,那么該腳本稍后將會(huì)被再次執(zhí)行,重復(fù)次數(shù)目前默認(rèn)為10

#若腳本執(zhí)行后返回2,或者比2更高的一個(gè)返回值,腳本將不會(huì)重復(fù)執(zhí)行。

#如果腳本在執(zhí)行過(guò)程中由于收到系統(tǒng)中斷信號(hào)被終止了,則同返回值為1時(shí)的行為相同。

#一個(gè)腳本的最大執(zhí)行時(shí)間為60s,如果超過(guò)這個(gè)時(shí)間,腳本將會(huì)被一個(gè)SIGKILL信號(hào)終止,之后重新執(zhí)行。

#通知型腳本:當(dāng)sentinel有任何警告級(jí)別的事件發(fā)生時(shí)(比如說(shuō)redis實(shí)例的主觀失效和客觀失效等等),將會(huì)去調(diào)用這個(gè)腳本,

#這時(shí)這個(gè)腳本應(yīng)該通過(guò)郵件,SMS等方式去通知系統(tǒng)管理員關(guān)于系統(tǒng)不正常運(yùn)行的信息。調(diào)用該腳本時(shí),將傳給腳本兩個(gè)參數(shù),

#一個(gè)是事件的類型,

#一個(gè)是事件的描述。

#如果sentinel.conf配置文件中配置了這個(gè)腳本路徑,那么必須保證這個(gè)腳本存在于這個(gè)路徑,并且是可執(zhí)行的,否則sentinel無(wú)法正常啟動(dòng)成功。

#通知腳本

# sentinel notification-script

Copyright 2009-2025 金鑰匙跨境 gantiao.com.cn,All Rights Reserved。金華奇璣電子商務(wù)有限公司 浙ICP備15009899號(hào)-2

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問(wèn)

文章目錄