Redis学习笔记

Redis入门

概述

Redis能干嘛

1、内存存储、持久化,内存中断电即失,持久化很重要!

2、效率高、可用于高速缓存

3、发布订阅系统

4、地图信息分析

5、计时器、计数器

特性

1、多种数据类型

2、持久化

3、集群

4、事务

Linux安装

下载

官网下载:https://redis.io/

上传服务器中并解压

程序建议放在/opt目录下:
在这里插入图片描述
在这里插入图片描述

进入文件安装环境

#依次执行命令
yum install gcc-c++

make

make install

安装后默认存放路径为:usr/local/bin

在这里插入图片描述

将opt目录下redis文件中的config配置文件拷贝过来

cp /opt/redis-6.0.9/redis.conf Zconfig/ #备份,以后就是用备份配置文件

修改配置文件

在这里插入图片描述

启动redis

通过指定的配置文件启动服务

[root@zhangxuchuan bin]# redis-server Zconfig/redis.conf 
[root@zhangxuchuan bin]# redis-cli -p 6379

关闭redis

[root@zhangxuchuan bin]# redis-cli -p 6379
127.0.0.1:6379> shutdown #关闭redis服务
not connected> exit  #退出redis服务

查看redis的进程

在这里插入图片描述

阿里云远程连接

在这里插入图片描述

性能测试

redis-benchmark :用于测试redis性能

参数

序号选项描述默认值
1-h指定服务器主机名127.0.0.1
2-p指定服务器端口6379
3-s指定服务器 socket
4-c指定并发连接数50
5-n指定请求数10000
6-d以字节的形式指定 SET/GET 值的数据大小2
7-k1=keep alive 0=reconnect1
8-rSET/GET/INCR 使用随机 key, SADD 使用随机值
9-P通过管道传输 请求1
10-q强制退出 redis。仅显示 query/sec 值
11–csv以 CSV 格式输出
12-l生成循环,永久执行测试
13-t仅运行以逗号分隔的测试命令列表。
14-IIdle 模式。仅打开 N 个 idle 连接并等待。
#测试100个并发  10W的请求
redis-benchmark -h localhost-p 6379 -c 100 -n 100000
[root@zhangxuchuan bin]# redis-benchmark -h localhost -p 6379 -c 100 -n 100000
====== PING_INLINE ======
  100000 requests completed in 1.73 seconds #10W请求处理时间
  100 parallel clients #10并发量
  3 bytes payload #每次写入三个字节
  keep alive: 1 #一台服务器处理
  host configuration "save": 900 1 300 10 60 10000
  host configuration "appendonly": no #未开启AOF持久化
  multi-thread: no
...
100.00% <= 18 milliseconds  #18毫秒处理完
57903.88 requests per second #每秒处理57903.88的请求

基础知识

redis默认有16个数据库

在这里插入图片描述

默认使用第0个

可以使用select切换数据库

127.0.0.1:6379> select 3 #切换到3号数据库
OK

查看数据库所有key keys *

127.0.0.1:6379[3]> keys *
1) "age"
2) "name"

清除当前数据库 flushdb

127.0.0.1:6379[3]> flushdb
OK
127.0.0.1:6379[3]> keys *
(empty array)

清除所有数据库flushall

Redis为什么是单线程!

Redis基于内存操作,CPU不是redis性能瓶颈

Redis的性能瓶颈是根据机器的内存和网络带宽

**核心:**多线程涉及cpu上下文切换,耗时操作,对于内存系统来说,单线程多次读写在同一个cpu上最快!

五大数据类型

Redis-key

127.0.0.1:6379> exists name #查看是否存在key值
(integer) 1 #存在返回1
127.0.0.1:6379> exists nam
(integer) 0 #不存在返回0
127.0.0.1:6379> move name 1 #移除key值
(integer) 1
127.0.0.1:6379> expire name 10 #设置key的过期时间(单位s)
(integer) 1
127.0.0.1:6379> ttl name #查看key的过期时间
(integer) 9
127.0.0.1:6379> type name #查看key的类型
string
127.0.0.1:6379> rname cyrus cyrus1 #修改key的名称
OK
127.0.0.1:6379> dbsize #查看DB大小
(integer) 0

String(字符串)

127.0.0.1:6379> set key1 v1
OK
127.0.0.1:6379> get key1
"v1"

####################追加字符串#######################

127.0.0.1:6379> append key1 v2  #往key1中追加字符串

(integer) 4
127.0.0.1:6379> get key1
"v1v2" 
127.0.0.1:6379> append key2 hello #如果当前key不存在 相当于sey了一个key
(integer) 5
127.0.0.1:6379> get key2
"hello"

##################获取字符串长度######################

127.0.0.1:6379> strlen key2  #获取key的字符串长度
(integer) 5

####################增加与减少#######################

127.0.0.1:6379> set views 0

OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views  #自增1
(integer) 1
127.0.0.1:6379> decr views  #自减1
(integer) 0
127.0.0.1:6379> incrby views 10  #自定义增量
(integer) 10
127.0.0.1:6379> decrby views 10  #自定义减量
(integer) 0

####################截取字符串########################

127.0.0.1:6379> get key1

"hellocyrusZhangxuchuan"
127.0.0.1:6379> getrange key1 1 4 #从下标[1,4]截取
"ello"
127.0.0.1:6379> getrange key1 0 -1 #获取全部
"hellocyrusZhangxuchuan" 

####################替换字符串########################

127.0.0.1:6379> set key1 abcdefg

OK
127.0.0.1:6379> get key1
"abcdefg"
127.0.0.1:6379> setrange key1 1 123  #从下标为1开始替换对应长度的字符串
(integer) 7
127.0.0.1:6379> get key1
"a123efg"

####################复合操作#######################

#setex (set with expire)  #设置+过期时间
127.0.0.1:6379> setex key2 10 "hello"
OK
127.0.0.1:6379> ttl key2
(integer) 7  #等待过期时间结束后再次查询key
127.0.0.1:6379> get key2
(nil)
#setnx (set if not exist) # 若不存在设置(分布式锁常常使用)
127.0.0.1:6379> setnx key3 hello
(integer) 1 #返回1成功
127.0.0.1:6379> get key3
"hello"
127.0.0.1:6379> setnx key3 key2 #此时已经存在 设置失败
(integer) 0 #返回0失败
127.0.0.1:6379> get key3
"hello"

######################批量设置#######################

127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 #批量设置 [{key-vlue}{key-vlue}...]
OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379> get k3
"v3"
127.0.0.1:6379> mget k1  k2  k3  #msetnx是一个原子性操作,要么都成功,要么都失败
"v1"
"v2"
"v3"
127.0.0.1:6379> msetnx k1 v5 k5 v5  #msetnx是一个原子性操作,要么都成功,要么都失败
(integer) 0 
127.0.0.1:6379> get v5
(nil)

######################设置对象########################

127.0.0.1:6379> mset user:1:name zhangsan user:1:age 18
OK
127.0.0.1:6379> mget user:1:name user:1:age  #对象:{id}:属性 => 实现id复用
1) "zhangsan"
2) "18"

######################getset命令########################

#getset 先get再set
127.0.0.1:6379> getset db redis
(nil) #若不存在返回null 并set值
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db mongodb
"redis" #若存在查出值,再进行重新设置
127.0.0.1:6379> get db
"mongodb"

String类型使用场景

  • 计数器 (可以设置过期时间)
  • 统计多单位的数量
  • 粉丝数/浏览量 (自增)
  • 对象缓存存储 (设置过期时间,判断是否存在)

List(列表)

######################push命令########################

127.0.0.1:6379> lpush list one #将one插入列表头部(左边)
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lrange list 0 1 #获取列表下标0到1的元素
1) "two"
2) "one"
127.0.0.1:6379> Rpush list three #插入列表尾部(右边)=》 双端队列
(integer) 3
127.0.0.1:6379> lrange list 0 -1 #范围查看所有list列表元素
1) "two"
2) "one"
3) "three"

在这里插入图片描述

######################pop命令########################

127.0.0.1:6379> Lpop list  #移除左边第一个值 (队首)
"two" #移除的元素
127.0.0.1:6379> Lrange list 0 -1
1) "one"
2) "three"
127.0.0.1:6379> Rpop list #移除右边第一个值(队尾)
"three" #移除的元素
127.0.0.1:6379> lrange list 0 -1
1) "one"

######################查看队列长度########################

127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> Llen list
(integer) 3

######################操作指定队列元素######################

127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "three"
4) "three"
127.0.0.1:6379> lrem list 2 three #移除list集合中指定value的个数
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"

######################截取队列元素######################

127.0.0.1:6379> rpush list hello
(integer) 1
127.0.0.1:6379> rpush list hello1
(integer) 2
127.0.0.1:6379> rpush list hello2
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "hello"
2) "hello1"
3) "hello2"
127.0.0.1:6379> ltrim list 1 2 #截取队列[1,2]的元素 修改队列
OK
127.0.0.1:6379> lrange list 0 -1
1) "hello1"
2) "hello2"

######################组合命令########################

######################rpoplpush######################

rpoplpush #移除列表最后的元素并移动到新的列表中

127.0.0.1:6379> lrange list 0 -1
1) "hello0"
2) "hello1"
3) "hello2"
127.0.0.1:6379> rpoplpush list mylist
"hello2" #移除的元素
127.0.0.1:6379> lrange list 0 -1 #查看原来的列表
1) "hello0"
2) "hello1"
127.0.0.1:6379> lrange mylist 0 -1 #查看目标列表
1) "hello2"

######################更新队列元素######################

127.0.0.1:6379> lrange list 0 -1
1) "zhangxuchuan"
127.0.0.1:6379> lset list 0 item #下标为0的元素值替换为item 
OK
127.0.0.1:6379> lrange list 0 -1
1) "item"
127.0.0.1:6379> lset list 1 item #若下标值不存在则报错
(error) ERR index out of range

######################插入队列元素######################

linsert [队列] before/after [存在的Value] [插入的value] #往队列中指定value值前/后插入值 
127.0.0.1:6379> lrange list 0 -1
1) "hello"
2) "world"
127.0.0.1:6379> linsert list before world hahah  #往前插
(integer) 3
127.0.0.1:6379> linsert list after world hahah #往后插
(integer) 4 
127.0.0.1:6379> lrange list 0 -1
1) "hello"
2) "hahah"
3) "world"
4) "hahah"

小结

消息队列(Lpush Rpop)

栈(Lpush Lpop)

Set(集合)

#######################添加查看操作#########################

127.0.0.1:6379> sadd List hello  #添加元素
(integer) 1
127.0.0.1:6379> sadd List world
(integer) 1
127.0.0.1:6379> sadd List cyrus
(integer) 1
127.0.0.1:6379> smembers List  #查看集合所有元素
1) "hello"
2) "cyrus"
3) "world"
127.0.0.1:6379> sismember List world #查看集合是否存在该value值
(integer) 1 #存在返回1
127.0.0.1:6379> sismember List worl
(integer) 0 #不存在返回0

####################查看集合长度########################

127.0.0.1:6379> scard List #查看set集合元素个数
(integer) 3

#######################指定移除操作#####################

127.0.0.1:6379> srem List hello #移除set集合中的指定元素
(integer) 1
127.0.0.1:6379> scard List
(integer) 2
127.0.0.1:6379> smembers List
1) "cyrus"
2) "world"
#######################随机操作########################

#######################随机抽数########################
srandmember #随机抽取Set集合元素

127.0.0.1:6379> srandmember List
"world"
127.0.0.1:6379> srandmember List
"cyrus"
127.0.0.1:6379> srandmember List
"cyrus"
127.0.0.1:6379> srandmember List
"world"
127.0.0.1:6379> srandmember List
"hello"
#######################随机删除########################

127.0.0.1:6379> spop List #随机删除Set集合中的元素
"hello"
127.0.0.1:6379> spop List
"cyrus"
127.0.0.1:6379> spop List
"world"

#######################移动指定元素########################

smove [Set集合(from)] [Set集合(To)] [(from)指定的Value]

127.0.0.1:6379> smembers myset
1) "hello"
2) "cyrus"
3) "world"
127.0.0.1:6379> smembers myset2
1) "test"
127.0.0.1:6379> smove myset myset2 cyrus 
(integer) 1
127.0.0.1:6379> smembers myset
1) "hello"
2) "world"
127.0.0.1:6379> smembers myset2
1) "cyrus"
2) "test"

######################差集、交集、并集########################

127.0.0.1:6379> smembers key1
1) "c"
2) "b"
3) "a"
127.0.0.1:6379> smembers key2
1) "d"
2) "c"
3) "e"
127.0.0.1:6379> sdiff key1 key2 #sdiff 查看Set集合key1对于key2的差集
1) "b"
2) "a"
127.0.0.1:6379> sdiff key2 key1 #sdiff 查看Set集合key2对于key1的差集
1) "d"
2) "e"
127.0.0.1:6379> sinter key1 key2 #sinter查看Set集合的交集
1) "c"
127.0.0.1:6379> sunion key1 key2 #sunion查看Set集合的并集
1) "b"
2) "c"
3) "a"
4) "d"
5) "e“

小结

微博:A用户所有关注的人再放在Set集合中,将它的粉丝也放在一个Set集合中

可实现:共同关注,共同爱好,二度好友…

Hash(哈希)

key - value存储

#####################################################
127.0.0.1:6379> hset myhash field1 cyrus1 #set一个具体key-value
(integer) 1
127.0.0.1:6379> hget myhash field1 #获取一个字段值
"cyrus1"
127.0.0.1:6379> hmset myhash field2 cyrus2 field3 cyrus3 #设置多个字段值
OK
127.0.0.1:6379> hmget myhash field1 field2 field3 #获取多个字段值
1) "cyrus1"
2) "cyrus2"
3) "cyrus3"
127.0.0.1:6379> hgetall myhash #获取所有字段值
1) "field1"
2) "cyrus1"
3) "field2"
4) "cyrus2"
5) "field3"
6) "cyrus3"
#####################################################
127.0.0.1:6379> hdel myhash field1 #删除hash指定key字段
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "cyrus2"
3) "field3"
4) "cyrus3"
#####################################################
127.0.0.1:6379> hlen myhash #获取hash表的字段数量
(integer) 2
#####################################################
127.0.0.1:6379> hexists myhash field1 #判断hash中指定字段是否存在
(integer) 0 #不存在
127.0.0.1:6379> hexists myhash field2 #判断hash中指定字段是否存在
(integer) 1 #存在
#####################################################
127.0.0.1:6379> hkeys myhash #获取hash中所有key值
1) "field2"
2) "field3"
3) "field4"
4) "field5"
5) "field6"
127.0.0.1:6379> hvals myhash #获取hash中所有value
1) "cyrus2"
2) "cyrus3"
3) "cyrus4"
4) "cyrus5"
5) "1"
#####################################################
127.0.0.1:6379> hincrby myhash field1 5 #指定增量
(integer) 6
127.0.0.1:6379> hincrby myhash field1 -5
(integer) 1
127.0.0.1:6379> hsetnx myhash field2 hello #若不存在创建
(integer) 1
127.0.0.1:6379> hsetnx myhash field2 hell #若存在不能创建
(integer) 0

小结

存放经常变动的数据信息,hash适合于对象的存储,string适合字符串存储

Zset(有序集合)

127.0.0.1:6379> zadd myset 1 one #添加一条数据(指定得分) 
(integer) 1
127.0.0.1:6379> zadd myset 1 hello #若该位置有值,往后插入
(integer) 1
127.0.0.1:6379> zrange myset 0 -1
1) "one"
2) "hello"
3) "two"
4) "three"
##########################################################
127.0.0.1:6379> zadd salary 2 two 3 three #添加多条数据
(integer) 2
############################################################
127.0.0.1:6379> zrange salary 0 -1 #正序打印
1) "cyrus"
2) "zhangxuchuan"
3) "jiuri"
127.0.0.1:6379> zrevrange salary 0 -1 #倒叙打印
1) "jiuri"
2) "zhangxuchuan"
3) "cyrus"
##########################排序操作############################


127.0.0.1:6379> zrangebyscore myset -inf +inf #从负无穷-》正无穷排序(小-》大)
1) "one"
2) "oneee"
3) "two"
4) "three"

127.0.0.1:6379> zrangebyscore myset -inf +inf withscores #打印得分
1) "one"
2) "1"
3) "oneee"
4) "1"
5) "two"
6) "2"
7) "three"
8) "3"

##########################################################
127.0.0.1:6379> zrem salary cyrus #删除指定元素
(integer) 1
127.0.0.1:6379> zcard salary #获取有序集合中元素个数
(integer) 2

##########################################################
127.0.0.1:6379> zadd myset 1 hello
(integer) 1
127.0.0.1:6379> zadd myset 2 world 3 cyrus
(integer) 2
127.0.0.1:6379> zcount myset 1 3 #在指定区间中的成员集合数量
(integer) 3

小结

排序:存储班级成绩表、工资表

普通消息:重要消息、带权重判断

排行榜应用实现:点击率榜

三大特殊数据类型

geospatial

geoadd

#添加位置的经度(-180,180)、纬度(-85,85)
127.0.0.1:6379> geoadd china:city 114.05 22.52  shengzhen 
(integer) 1
127.0.0.1:6379> geoadd china:city 116.40 39.90 beijin
(integer) 1
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqin
(integer) 1

geopos

#获取指定位置的经纬度
127.0.0.1:6379> GEOPOS china:city beijin chongqin
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"
2) 1) "106.49999767541885376"
   2) "29.52999957900659211"

geodist

#计算两地之间直线距离
127.0.0.1:6379> GEODIST china:city beijin chongqin #默认单位m
"1464070.8051"
127.0.0.1:6379> GEODIST china:city beijin chongqin km #[mi:英里,ft:英尺] #单位km 
"1464.0708"

georadius

寻找附近的人:获取所有人定位,通过半径查询

127.0.0.1:6379> georadius china:city 110 30 100 km #指定经纬度100km半径范围
(empty array)
127.0.0.1:6379> georadius china:city 110 30 1000 km #指定经纬度1000km半径范围
1) "chongqin"
2) "shengzhen"
3) "hangzhou"
127.0.0.1:6379> georadius china:city 110 30 10000 km #指定经纬度1000km半径范围
1) "chongqin"
2) "shengzhen"
3) "hangzhou"
4) "beijin"
###################################################同时获取直线距离
127.0.0.1:6379> georadius china:city 110 30 10000 km withdist #同时获取直线距离
1) 1) "chongqin"
   2) "341.9374"
2) 1) "shengzhen"
   2) "924.6408"
3) 1) "hangzhou"
   2) "977.5143"
4) 1) "beijin"
   2) "1245.2858"
###################################################同时获取直线距离与坐标
127.0.0.1:6379> georadius china:city 110 30 5000 km withdist withcoord withcoord
1) 1) "chongqin"
   2) "341.9374"
   3) 1) "106.49999767541885376"
      2) "29.52999957900659211"
2) 1) "shengzhen"
   2) "924.6408"
   3) 1) "114.04999762773513794"
      2) "22.5200000879503861"
3) 1) "hangzhou"
   2) "977.5143"
   3) 1) "120.1600000262260437"
      2) "30.2400003229490224"
4) 1) "beijin"
   2) "1245.2858"
   3) 1) "116.39999896287918091"
      2) "39.90000009167092543"
#################################同时获取直线距离与坐标与指定显示数量(距离短的优先)      
127.0.0.1:6379> georadius china:city 110 30 5000 km withdist withcoord withcoord count 1
1) 1) "chongqin"
   2) "341.9374"
   3) 1) "106.49999767541885376"
      2) "29.52999957900659211"

georadiusbymember

#找出位于指定元素周围的其他元素
127.0.0.1:6379> georadiusbymember china:city chongqin 10000 km
1) "chongqin"
2) "shengzhen"
3) "hangzhou"
4) "beijin"

geohash

返回一个和多个位置元素的geohash表示

#将二位的经纬度转换为一维字符串,若字符串越接近,距离越接近
127.0.0.1:6379> geohash china:city beijin chongqin
1) "wx4fbxxfke0"
2) "wm5xzrybty0"

geo底层实现为Zset

127.0.0.1:6379> zrange china:city 0 -1
1) "chongqin"
2) "shengzhen"
3) "hangzhou"
4) "beijin"
127.0.0.1:6379> zrem china:city beijin
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqin"
2) "shengzhen"
3) "hangzhou"

hyperloglog

什么是基数(集合中不重复元素的个数)

A{1,2,3,3,4}

B{1,2,3,4}

A的基数为4 ,B的基数为4

简介

0.81%的错误率. 统计UV任务,可以忽略不计(一人访问网站多次,只算一个人)

占用内存为固定的12KB(2^64)

基于基数的统计算法

127.0.0.1:6379> pfadd mykey a b c d e f g #存放第一组元素
(integer) 1
127.0.0.1:6379> pfcount mykey #统计基数数量
(integer) 7
127.0.0.1:6379> pfadd mykey1 f g i j k l m k #存放第二组(重复元素只存放一个)
(integer) 1
127.0.0.1:6379> pfcount mykey1
(integer) 7
127.0.0.1:6379> pfmerge mykey2 mykey mykey1 #
OK
127.0.0.1:6379> pfcount mykey2 #统计并集数量
(integer) 12

允许容错,可以使用hyperloglog

不允许容错,使用set或自己的数据类型

Bitmaps

位存储

统计用户信息:是否活跃、登陆或未登录、是否签到、打卡…只要有两种状态的 就可以使用bitmaps

Bitmaps位图,数据结构。操作二进制数来进行记录,只有0、1两种状态

365天=365bit 1字节=8bit

在这里插入图片描述

例子:使用bitmaps实现一周的打卡 =》 1:打卡 0:未打卡

在这里插入图片描述

查看某一个是否打卡:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0FxHMjmI-1605188133299)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201110095317930.png)]

统计这周打卡天数:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7eDF7lrU-1605188133302)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201110095429670.png)]

事务

------------队列  set set set 执行-------------

Redis单条命令保证原子性

Redis事务不保证原子性!

Redis没有隔离级别概念:所有命令在实务中,没有直接被执行。只有发起执行命令的时候才会执行!exec

Redis事务:

  • 开启事务:multi
  • 命令入队:set
  • 执行事务:exec
127.0.0.1:6379> MULTI #开启事务
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec  #执行事务
1) OK
2) OK
3) OK

放弃事务

discard

127.0.0.1:6379> MULTI #开启事务
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> DISCARD  #取消事务
OK
127.0.0.1:6379> get k1
(nil)

编译型异常 (代码错误/命令错误)

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> getset k3 #出现错误命令
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> exec #最终事务中所有命令都不会被执行
(error) EXECABORT Transaction discarded because of previous errors.

运行时异常 (1/0)

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> incr k1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec
1) (error) ERR value is not an integer or out of range #虽然第一条命令报错,但依旧正常执行成功  =》 redis事务不保证原子性!
2) OK
3) "v2"

监控 Watch(乐观锁)

watch

悲观锁:

  • 很悲观,什么时候都认为会出现问题(被修改) ,无论做什么都会加锁!

乐观锁:

  • 很乐观,什么时候都认为不会出现问题(不被修改),不会上锁!更新数据时候判断,在此期间是否有人修改过
  • 获取version
  • 更新时候比较version

Redis监控测试

单线程测试:

127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money  #监控money对象
OK
127.0.0.1:6379> MULTI #事务正常结束,数据期间没有发生变动,正常执行成功
OK
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
127.0.0.1:6379> exec

多线程:

127.0.0.1:6379> get money
127.0.0.1:6379> 100
127.0.0.1:6379> get out
127.0.0.1:6379> 0
#线程1 
127.0.0.1:6379> watch money #监视money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> incrby out 20 
QUEUED 
127.0.0.1:6379> exec #执行之前使用线程2对money进行修改
(nil) #乐观锁机制,执行前比对与事务之前的money值是否相等!
#线程2
127.0.0.1:6379> set money 1000
OK
127.0.0.1:6379> get money
"1000"

关于Watch监视补充

何时取消key的监视
1、watch命令可以被调用多次。对键的监视从watch执行之后开始生效,直到调用exec为止,不管事务是否成功执行,

对所有键的监视都会被取消。

2、当客户端断开连接时,该客户端对键的监视也会被取消。

3、unwatch命令可以手动取消对所有键的监视。

Jedis

什么是Jedis

使用java操作Redis的中间件

依赖

<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.3.0</version>
</dependency>

springboot整合

SpringBoot2.X之后,由原来的jedis被替换成lettuce

  • jedis:采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全的,使用jedis pool连接池!更像BIO模式
  • lettuce:采用netty,实例可以再多个线程中进行共享,不存在线程不安全的情况!可以减少线程数量,更像Nio模式

Springboot整合Redis

1、依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.75</version>
</dependency>

2、配置文件

#配置redis
spring.redis.host=8.131.97.122
spring.redis.port=6379

3、测试

@SpringBootTest
class RedisdemoApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void test() {
        /**
         * redisTemplate操作
         *      opsForValue : 操作String
         *      opsForList
         *      opsForSet
         *      opsForHash
         *      opsForZSet
         *      opsForGeo
         *      opsForHyperLogLog
         */
        redisTemplate.opsForValue().set("name","cyrus");
        System.out.println(redisTemplate.opsForValue().get("name"));
    }
}

打印结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sEej9BMw-1605188133308)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201111101656620.png)]

Redis.conf详解

单位

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f4pU9dgP-1605188133309)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201111134007447.png)]

配置文件unit单位对大小写不敏感

包含 include

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BekiRs75-1605188133311)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201111134104187.png)]

类似于导入(import)

网络 NETWORK

bind 127.0.0.1 #绑定的ip 如需让外网访问改成0.0.0.0

protected-mode yes #保护模式

port 6379 #端口号设置

通用 GENERAL

daemonize yes #以守护进程方式运行  默认为yes

pidfile /var/run/redis_6379.pid #后台方式运行时所需的指定pid文件

#日志
# Specify the server verbosity level.
# This can be one of:
# 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 #是否显示redis启动时的logo

快照 SNAPSHOTTING

持久化,在规定时间执行多少次操作,则会持久化到rdb.aof中

redis为内存数据库,断点及失,必须持久化!

save 900 1 #900s内 至少1个key修改 进行持久化
save 300 10 #300s内 至少10个key修改,进行持久化
save 60 10000 #60s内,至少10000个key修改,进行持久化

stop-writes-on-bgsave-error yes #持久化出错后是否继续工作

rdbcompression yes #是否压缩rdb文件,消耗cpu资源操作

rdbchecksum yes #保存rdb文件时,是否进行错误校验

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

复制 REPLICATION ->主从复制篇#

安全 SECURITY

#requirepass foobared   #redis密码设置,默认没有密码

#设置redis密码
127.0.0.1:6379> ping #查看是否可以联通
PONG
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) ""
127.0.0.1:6379> config set requirepass 123456 #设置密码
OK
127.0.0.1:6379> auth 123456 #进行登录校验
OK
127.0.0.1:6379> config get requirepass #获取密码
1) "requirepass"
2) "123456"

限制 CLIENTS

maxclients 10000  #设置redis最大客户端连接数

maxmemory <bytes> #redis配置最大的内存容量

maxmemory-policy noeviction #内存到达上限后的处理策略
                - allkeys-lru:在所有键中采用lru算法删除键,直到腾出足够内存为止。
                - volatile-lru:在设置了过期时间的键中采用lru算法删除键,直到腾出足够内存为止。
                - allkeys-random:在所有键中采用随机删除键,直到腾出足够内存为止。
                - volatile-random:在设置了过期时间的键中随机删除键,直到腾出足够内存为止。
                - volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除。

Aof持久化模式 APPEND ONLY MODE

appendonly no #默认不开启
appendfilename "appendonly.aof" #持久化文件名

# appendfsync always #每次修改都会sync
appendfsync everysec #每秒执行一次sync 可能会丢失这一秒数据
# appendfsync no #不执行sync,这个时候操作系统自己同步数据

Redis持久化

RDB(Redis Database)

在这里插入图片描述

正式生产时:会将RDB配置文件进行备份,防止丢失!

持久化方式

指定间隔将内存中数据集快照写入磁盘,恢复时将快照文件直接读到内存中

保存的文件

以文件dump.rdb 进行保存

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VWIt8G8f-1605188133332)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201111145808130.png)]

修改rdb机制 60秒内修改5次触发持久化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4DhMOHTj-1605188133333)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201111150053210.png)]

触发机制

1、save的规则满足情况下,触发

2、执行flushall命令,触发

3、退出redis、也会产生dump.rdb

如何恢复rdb文件

1、将rdb文件放在redis启动目录、redis启动会自动检查dump.rdb进行恢复

127.0.0.1:6379> config get dir
1) "dir"
2) "/usr/local/bin" #若此目录下存在dump.rdb 会启动时自行恢复其中数据

优点

1、适合大规模数据恢复

2、适合对数据完整性要求不高

缺点

1、需要一定时间间隔进行进程操作,若redis宕机,最后一次修改数据会丢失!

2、fork进程的时候,会占用一定的内存空间

AOF(Append Only File)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MFZxIVqI-1605188133335)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201111152738383.png)]

将所有(写操作)命令全部以日志形式记录下来,恢复的时候将这个日志文件里的命令全部执行一遍

使用

Aof默认是不开启的,需要手动开启!

appendonly no #将no改为yes
#重启redis服务

#往redis中写入数据
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> set k3 v3
OK

1、查看bin目录下是否出现appendonly.aof 文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qor5Hhkk-1605188133339)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201111153303220.png)]

2、查看appendonly.aof 内存,记录了所有写命令

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HUuafd1Z-1605188133345)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201111153553185.png)]

破坏appendonly.aof文件

1、往文件中写入一些字符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-neq3fYbz-1605188133351)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201111153655559.png)]

2、重启redis服务后重新连接redis

发现无法连接redis!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NH2TVN8T-1605188133353)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201111153503786.png)]

Aof文件中若有错误命令,是无法启动redis,需要进行修复!

3、使用redis-check-aof --fix 命令对aof文件进行修复

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xy7fcqdQ-1605188133355)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201111154128024.png)]

进入aof文件中,发现字符已经被删除!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MVZGH70H-1605188133356)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201111154103044.png)]

4、启动redis服务,重新连接成功!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s29idJOI-1605188133358)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201111154224277.png)]

重写规则

aof默认就是文件无限追加!文件会越来越大!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V6bZcB0c-1605188133360)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201111154722907.png)]

默认如果aof文件大于64m(可修改),会fork一个新进程来将文件进行重写,减少冗余命令

例子:

写入6条set语句存储5个元素["C", "D", "E", "F", "G"]

重写后变为一条语句RPUSH list "C" "D" "E" "F" "G"

优点

# appendfsync always #每次修改都会sync
appendfsync everysec #每秒执行一次sync 可能会丢失这一秒数据
# appendfsync no #不执行sync,这个时候操作系统自己同步数据

1、每次修改都同步,文件完整性好

2、每秒同步一次、可能会丢失一秒数据

3、从不同步,效率最高

缺点

1、相对于数据文件来说,aof大于rdb,修复速度比rdb慢

2、Aof运行效率慢,默认配置为rdb持久化

扩展

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Lb7a9KD-1605188133361)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201111155539081.png)]

Redis发布订阅

角色①:消息发布者

角色②:频道

角色③:消息订阅者

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-svmqTVk9-1605188133362)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201112093615149.png)]

实现

Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。

Redis 客户端可以订阅任意数量的频道。

下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AdJQq4os-1605188133363)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201112095226653.png)]

当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AQvOAyjj-1605188133365)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201112095233908.png)]

命令

序号命令及描述
1[PSUBSCRIBE pattern pattern …] 订阅一个或多个符合给定模式的频道。
2[PUBSUB subcommand argument [argument …]] 查看订阅与发布系统状态。
3PUBLISH channel message 将信息发送到指定的频道。
4[PUNSUBSCRIBE pattern [pattern …]] 退订所有给定模式的频道。
5[SUBSCRIBE channel channel …] 订阅给定的一个或多个频道的信息。
6[UNSUBSCRIBE channel [channel …]] 指退订给定的频道。

测试

订阅端

127.0.0.1:6379> subscribe Cyrus  #订阅[Cyrus]这个频道
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "Cyrus"
3) (integer) 1
#等待读取推送消息
1) "message" #消息
2) "Cyrus"   #所属频道
3) "hello"   #消息内容

发送端

127.0.0.1:6379> publish Cyrus hello #发布者往[Cyrus]频道发送消息
(integer) 1
127.0.0.1:6379> 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bryx6gIh-1605188133367)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201112094929656.png)]

使用场景:

1、实时聊天系统

2、公众号推文

复杂场景使用MQ中间件处理!

Redis主从复制

环境配置

info replication:查看配置信息

127.0.0.1:6379> info replication #打印应用信息
# Replication
role:master  #身份默认为master主机
connected_slaves:0
master_replid:14f8e46f6cde5808675f59f2294b70c35b824480
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

复制三个配置文件,修改内容

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-COHv2t9X-1605188133370)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201112101007867.png)]

port 6380  #修改端口号

pidfile /var/run/redis_6380.pid #修改pid值

logfile "6380.log"  #修改日志文件名

dbfilename dump6380.rdb  #修改dump文件名

开启redis服务

[root@iZ2zegptd6bqaotm8lfby0Z bin]# redis-server Zconfig/redis79.conf 
[root@iZ2zegptd6bqaotm8lfby0Z bin]# redis-server Zconfig/redis80.conf 
[root@iZ2zegptd6bqaotm8lfby0Z bin]# redis-server Zconfig/redis81.conf 
[root@iZ2zegptd6bqaotm8lfby0Z bin]# ps -ef|grep redis
#三台redis全部开启成功
root     17762     1  0 Nov11 ?        00:01:24 redis-server 0.0.0.0:6379
root     19412     1  0 10:12 ?        00:00:00 redis-server 0.0.0.0:6380
root     19418     1  0 10:12 ?        00:00:00 redis-server 0.0.0.0:6381
root     19424 19102  0 10:12 pts/0    00:00:00 grep --color=auto redi

一主二从

默认情况下,每台Redis服务器都是主节点,我们只需配置从机

slaveof [ip] [端口] :配置为指定Redis服务器的从机

127.0.0.1:6380> slaveof 127.0.0.1 6379  #配置为本机端口号为6379的从机
OK
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1 #主机IP
master_port:6379 #主机端口
master_link_status:up
master_last_io_seconds_ago:4
master_sync_in_progress:0
slave_repl_offset:112
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:8cb96e468cdaeaafb984c11418e36da2a001adc5
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:112
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:99
repl_backlog_histlen:14

注意:命令配置为临时,若永久生效需要在配置文件中配置!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CfbS13vD-1605188133371)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201112102513295.png)]

# replicaof <masterip> <masterport> #配置主机IP 与 端口号

# masterauth <master-password> #设置主机密码验证

细节:主机可以写,从机只能读!

主机:

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
3) "k1"

从机:

[root@iZ2zegptd6bqaotm8lfby0Z bin]# redis-cli -p 6380
127.0.0.1:6380> keys *
1) "k3"
2) "k1"
3) "k2"
127.0.0.1:6380> set k4 v4
(error) READONLY You can't write against a read only replica.

若主机断开:从机依旧可以读取信息!

主机

127.0.0.1:6379> shutdown

从机

127.0.0.1:6380> keys *
1) "k3"
2) "k1"
3) "k2"

注意:若用命令行配置从机,从机配置失效,再次变回主机!重新配置为从机,立马会从主机中获取到值

原理

Slave启动成功连接到master后会发送一个sync同步命令
Master接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行宪毕之后,master将传送整个数据文件到slave,并完成一次完全同步。
全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。
增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步
但是只要是重新连接master,一次完全同步(全量复制)将被自动执行

层层链路

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-11gawe4g-1605188133373)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201112104253007.png)]

手动配置选老大 :谋权篡位

slaveof no one :让自己变成主机,其他节点手动配置为该机的从机

哨兵模式

概述

哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fO9fPLHm-1605188133375)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201112113142237.png)]

多哨兵模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fbAgyjDV-1605188133376)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201112113331813.png)]

假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为==主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover[故障转移]操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线==。

测试

1、配置哨兵配置文件sentinel.conf

#sentinel monitor 被监控的名称  host  port 
sentinel monitor myredis 127.0.0.1 6379 1
#数字1代表主机宕机,slave投票让谁接替成为主机

2、启动哨兵

[root@iZ2zegptd6bqaotm8lfby0Z bin]# redis-sentinel Zconfig/sentinel.conf 
19687:X 12 Nov 2020 11:43:09.618 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
19687:X 12 Nov 2020 11:43:09.618 # Redis version=6.0.9, bits=64, commit=00000000, modified=0, pid=19687, just started
19687:X 12 Nov 2020 11:43:09.618 # Configuration loaded
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 6.0.9 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in sentinel mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379
 |    `-._   `._    /     _.-'    |     PID: 19687
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

19687:X 12 Nov 2020 11:43:09.619 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
19687:X 12 Nov 2020 11:43:09.619 # Sentinel ID is cb220149c1ab64ed0706e80bf204a40467b79b9f
19687:X 12 Nov 2020 11:43:09.619 # +monitor master myredis 127.0.0.1 6379 quorum 1
19687:X 12 Nov 2020 11:43:09.620 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis 127.0.0.1 6379  #从机6380
19687:X 12 Nov 2020 11:43:09.623 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis 127.0.0.1 6379  #从机6381

如果Master节点断开,会在从机中通过投票算法选举新主机!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-65Jub3Y2-1605188133380)(C:\Users\acer\AppData\Roaming\Typora\typora-user-images\image-20201112114618374.png)]

结果:选举6380成为主机!

[root@iZ2zegptd6bqaotm8lfby0Z bin]# redis-cli -p 6380
127.0.0.1:6380> info replication
role:master  #6380变为master
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=12936,lag=0 #6381自动变为6380从机
master_replid:c2d04217c3181bb7815415c7b650dc0e40efb657
master_replid2:f0d05fda716ab210843ff2520c6821c3da94352f
master_repl_offset:12936
second_repl_offset:6570
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:12936

优点

1、主机宕机后,自动主从机切换

2、故障转移,系统可用性更好

缺点

1、Redis不好在线扩容,集群容量一旦到达上线,扩容十分麻烦

2、哨兵模式配置复杂

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值