Redis7(新特性笔记)

Redis

介绍

Redis是一个开源的,内存中数据结构存储系统,可以作为数据库,缓存和消息中间件,例如String、Hash、List、Set、SortedSet等等。

它可以作为:

  1. 分布式缓存
  2. redis支持异步将内存中的数据写到硬盘上,同时不影响继续服务
  3. 缓存穿透、击穿、雪崩
  4. 分布式锁
  5. 队列

Redis官网地址:

英文:https://redis.io/

中文:https://redis.com.cn/

源码:https://github.com/redis/redis

在线测试:https://try.redis.io/

Redis命令参数:http://doc.redisfans.com/

安装

Window安装:

下载地址:https://github.com/zkteco-home/redis-windows/releases

  1. 选择对应的版本进行下载,然后解压到本地
  2. 进行配置环境变量,在系统变量Path这里添加redis的安装目录,如:D:\redis\redis-windows-7.0.10
  3. 然后进行启动,在安装目录下执行cmd,再执行 redis-server.exe redis.conf 进行启动
  4. 然后可通过客户端工具查看是否启动成功

Linux安装:

我们常用都是Linux版本进行安装Redis

下载地址:https://redis.io/download/

  1. 前提需要安装gcc编译环境,需要64位

    gcc -v                  # 查看版本,gcc版本需要大于4.8
    yum -y install gcc-c++  # 安装c++库环境
    
    redis -server -V        # 查看redis版本
    
  2. 进行下载包,放在某个位置,进行解压

    tar -zxvf redis7.0.9.tar.gz     # 一般放在/opt目录下解压
    cd redis7.0.9                   # 进入该目录
    make && make install            # 在该目录下执行
    cd /usr/local/bin               # 默认安装的位置查看
    
    # 一般我们安装完,进行复制一份原始的redis的配置文件
    mkdir /myredis                       # 在跟目录创建一个myredis目录
    cp redis.conf /myredis/redis7.conf   # 将原始redis配置文件复制到myredis目录下
    
  3. 修改redis7.conf 配置文件,该文件作为Redis的配置文件

    vim /myredis/redis7.conf  
    默认 daemonize no 改为 daemonize yes  # 将服务作为后端启动
    默认 protected-mode yes 改为 protected-mode no  # 允许其他程序连接到Redis,关闭保护模式
    默认 bind 127.0.0.1 改为 直接注释掉(默认bind 127.0.0.1只能本机访问)或改成本机IP地址,否则影响远程IP连接
    添加 redis密码 改为 requirepass 你自己设置的密码  (生产环境需要设置)
    
  4. 进行启动

    cd /usr/local/bin   # 在该目录
    redis-server /myredis/redis7.conf  # redis-server是启动命令,后面的指定配置文件启动
    ps -ef|grep redis|grep - v grep    # 查看redis的进程和端口,默认是6379
    
  5. 连接服务

    # 客户端进行连接 - 方式1:输入该命令会有警告
    redis-cli -a 设置的密码 -p 6379 
    # 客户端进行连接 - 方式2:
    redis-cli -p 6379  # 此时会提示 NOAUTH... 提示进行输入密码
    auth 设置的密码      # 输入完,也可以登陆
    # 客户端进行连接 - 方式3:
    redis-cli -a 设置的密码 -p 6379 2>/dev/null
    
    # 连接成功后,输入ping ,如返回  pong 就代表成功
    # quit 是退出客户端
    
    # 关闭客户端连接 - 在其他redis登陆,关闭已经连接的redis的客户端,在外面执行
    redis-cli -p 6379 shutdown
    

卸载

# 先停掉已启动redis服务
ps -ef|grep redis
redis-cli shutdown

# 删除/usr/local/lib目录下的redis文件
ls - l /usr/local/bin/redis-*
rm - rf  /usr/local/bin/redis-*
# 删除确保,没有其他文件
ls - l /usr/local/bin/redis-*

Docker版本安装Redis

在Docker篇有:https://blog.csdn.net/yanshengren520/article/details/122018441?spm=1001.2014.3001.5501

Redis7新特性

最新版本:https://github.com/redis/redis/releases

十大数据类型

  • String : 一个字符串value最多是512M,是二进制安全的字符串,支持序列化
  • List :底层是双向链表,List最多可存40亿元素
  • Hash:(哈希表)使用存对象,是键值对
  • Set:(无序集合)不能有重复的
  • ZSet:(有序集合)
  • GEO:(地理空间)存储地理位置信息,计算2个位置距离
  • HyperLogLog:(基数统计)用来做基数统计的,
  • bitmap:(位图)由0和1状态表现二进制bit数组,可用于记录一周内是否打卡状态
  • bitfield:(位域)一次性操作多个比特位域
  • Stream:(流)主要用于消息队列,支持发布订阅
Redis(Key)操作命令

一些API命令讲解:https://redis.com.cn/commands.html

注:key的值是区分大小写的

# 查
127.0.0.1:6379> keys *  # 查看当前库里所有的key
exists key名            # 判断某个key是否存在, 1代表存在,0代表不存在
type key名              # 查看你的key是什么类型
expire key名 秒数        # 给key设置过期时间,单位(描述)
ttl key名               # 查看key还有多少秒过期,单位(秒) -1代表永不过期 -2 代表已过期 

# 删除
del key名         # 删除指定的key数据
unlink key名      # 非阻塞删除,先keyspace元数据删除,没真正的删除会在后续异步中操作,不会阻塞的删除

# 对数据库的操作,redis默认是有16个数据库的,默认是0号库
move key名 dbindex [0-15]   # 将当前数据库的key移动到指定的数据库中 例子:move key名 3 (把key移到3号库)
select dbindex [0-15]      # 切换数据库[0-15],默认为0,例子:select 3 (切换到3号库)
dbsize   			# 查看当前数据库key的数量,相当于SQL的 select count(key)
flushdb             # 清空当前库
flushall 			# 清空16个数据库,谨慎使用

# 批量删除 - 通过管道进行批量删除,“***” 代表 key前缀
redis-cli -a 密码 keys "***" | xargs redis-cli del
字符串(String)
# 设置值 20秒过期 ex代表以秒为单位设置 px代表以毫秒为单位设置
set key名 value值 ex 20  
# 修改key的值,如果后面加了keepttl,代表保留设置前指定的过期时间,只改value值,过期时间不重置
set key名 value值 keepttl
# 获得对应的值
get key名   

# 同时设置一个或多个键值对
MSET [key1] [value1] [key2] [value2] [key3] [value3]
# 同时获取多个key的值
MGET [key1] [key2] [key3]  
# 同时设置一个或多个 key-value 对  必须保证key都不存在才能成功
MSETNX [key1] [value1] [key2] [value2]  

# 这个相当于对value值进行截取
GETRANGE [key] 0 -1   # 获取这个key的值的全部
GETRANGE [key] 0 2    # 获取这个key的值索引0到索引2之间的值

# 获取字符串长度和内容相加
STRLEN [key]          # 获取key对应的值的长度
APPEND [key] [vale]   # 添加字符串内容

# 数值增减,value值一定是数字
INCR [key]                 # 递增数字 +1
INCRBY [key] [increment]   # 增加指定的整数  +increment 
DECR [key]                 # 递减数字 -1
DECRBY [key] [increment]   # 减少指定的整数  -increment 

# 分布式锁
setnx/setex [key] [过期时间] [value]  # 设置带过期时间的key,动态设置,例子:setnx k1值 10 v1值
setnx [key] [value]                 # 只有在 key 不存在时设置 key 的值。
# 一般是两个命令连用,写成lua脚本连用,具体在Redis高级分布式锁中使用

# getset(先get再set)
getset [key] [value]  # 给定 key 的值设为 value ,并返回 key 的旧值
列表(List)

单个key,多个value,一般用在栈、队列、消息队列等场景,底层是双端链表

lpush [key] [value] ...  # 从(左边)放入元素 例:lpush key1 1 2 3 4
Rpush [key] [value] ...  # 从(右边)放入元素
lrange [key] 0 -1        # 从左边开始遍历列表  只能从左边遍历
lpop [key]               # 最左边的出栈 也就是lrange遍历的第一个,也就是删除掉
rpop [key]               # 最右边的出栈 也就是lrange遍历的最后一个
lindex [key] [index]     # 通过索引值获取值
llen [key]               # 获得元素个数
lrem [key] [num] [value] # 从左往右删除 num个值为 value的值
lrem [key] 0 [value]     # 从左往右删除所有值为value的值
ltrim [key] [开始] [结束] # 截取指定范围的值后再赋给[key],也就是删除这个区间外的值
RPOPLPUSH [key1] [key2]  # 移除列表的最后一个元素,并将该元素添加到另一个列表的第一个并返回
lset [key] [index] [value]   # 将key的第 index 个索引值改为value
linsert [key] before/after [value1] [value2] # 在list某个已有值的前后再添加具体

应用场景:

用户id收藏了文章1、文章2、文章3 ,命令:lpush likearticle:用户id 文章id1 文章id2 文章id3

查询用户最近收藏3条文章; lrange likearticle:用户id 0 3 (0到3条记录)

哈希(Hash)

目前基本不用,结果像Map<String,Map<Object,Object>

hset user id 11 name z1 # 创建一个hash的key
hget user id            # 获取key里其中一个值
hlen                    # 获取在某个key内的全部数量
hexists [key] [k1]      # 看key中是否有k1这个键
hkeys [key]             # 获取key里面的所有key
hvals [key]             # 获取key里面的所有value
集合(Set)

单个key,多个value,无重复

SADD key member ...   # 添加元素  例:sadd set1 1 2 3 3 4  ,插进去的数据是1 2 3 4
SMEMBERS key          # 遍历集合中所有元素
SISMEMBER key member  # 判断元素是否在集合中
SREM key member ...   # 删除元素
SCARD  key            # 获取集合长度
SRANDMEMBER key m     # 从set集合里面随机取出m个 ,如果超过最大数量就全部取出   如果写的值是负数,比如-3 ,表示需要取出3个,但是可能会有重复值   不会删除
SPOP key m        # 从集合中随即弹出一个元素  出一个删一个
SMOVE key1 key2 在key1里已存在的某个值  # 将key1的已存在的某个值赋给key2
# 集合运算
SDIFF keyA keyB     # A - B  属于A但不属于B的元素构成的集合
SUNION keyA keyB    # A U B  属于A或者属于B的元素合并后的
SINTER keyA keyB    # A ∩ B  属于A同时属于B
SINTERCARD numkeys keyA keyB [LIMIT limit] # 不返回结果集,只返回结果的基数

应用场景:

  • 微信抽奖

    用户1参加抽奖,命令:sadd key 用户id
    显示多少人参加,命令:SCARD key
    进行抽奖,命令:SRANDMEMBER key 2  (随机抽2个人,但2人不删除,可还可以参与抽奖)
    		命令:spop key 3 (随机抽3人,会从集合中删除掉)
    
  • 集合运算

    sadd s1 1 2 3 4
    sadd s2 3 4 5 6
    SDIFF s1 s2     # 求差集 得出 1 2 
    SDIFF s2 s1     # 求差集 得出 5 6
    SINTER s1 s2    # 求交集 得出 3 4
    
有序集合(Zset)

有序的集合,在set的基础上加了一个score分数值,根据分数值排序

ZADD key score member [ score member ] # 添加元素 例:zadd k1 60 王者 30 飞车 20 派对
ZRANGE key start stop [WITHSCORES]     # 返回元素分数从小到大的顺序  返回索引从start到stop之间的所有元素例:ZRANGE k1 0 -1 (全部) 或  ZRANGE k1 0 -1 (全部) withscores (带分数值返回)
ZREVRANGE key 0 - 1 [WITHSCORES]       # 反序
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] # 获取指定分数范围的元素(min,max) 不包含   limit是返回限制,返回多少个 
ZSCORE key member             # 获取元素的分数
ZCARD key                     # 获取集合中元素的数量
ZREM key 某score下对应的value值 # 删除元素
ZINCRBY key increment member  # 增加某个元素的分数
ZCOUNT key min max            # 获得指定分数范围内的元素个数
ZRANK key values值            # 获得下标值
ZREVRANK key values           # 逆序获得下标值、
位图(bitmap)

由 0 和 1 表示的二进制位的 bit 数组

SETBIT key offset value   # 将第offset的值设为value  value只能是0或1  offset 从0开始
GETBIT key offset         # 获得第offset位的值
STRLEN key                # 得出占多少字节 超过8位后自己按照8位一组一byte再扩容
BITCOUNT key              # 得出该key里面含有几个1
BITOP and destKey key1 key2  # 对一个或多个 key 求逻辑并,并将结果保存到 destkey 
BITOP or destKey key1 key2   # 对一个或多个 key 求逻辑或,并将结果保存到 destkey 
BITOP XOR destKey key1 key2  # 对一个或多个 key 求逻辑异或,并将结果保存到 destkey 
BITOP NOT destKey key        # 对key 求逻辑非,并将结果保存到 destkey 

应用场景:

# 做打卡签到场景
# 第一天打开:setbit sign:用户id1:202201 0 1
# 第二天打开:setbit sign:用户id1:202202 1 1
# 第三天打开:setbit sign:用户id1:202203 2 1
# 第六天打开:setbit sign:用户id1:202203 5 1
# 查看第三天有没有来,   getbit sign:用户id1:202203 2       # 得出结果是 0
# 查看统计这个月打开几次:bitcount sign:用户id1:202203 0 30  # 得出结果是4个数
基数统计(HyperLogLog)

它本身不会存储元素本身,统计某个网站的UV,某个文章的UA,UA是(独立访客,一般是客户端的IP)

pfadd  hel  1 3 5 7      # 添加元素   ,然后统计个数是:4
pfadd  he2  1 3 3 4 6 7  # 添加元素   ,然后统计个数是:5
pfcount hel              # 打印he1个数  ,结果是 4
pfmerge he新 he1 he1     # 添加元素,多个元素
pfcount he新             # 打印he新个数  ,结果是 6
# 适合做统计个数,并不保留结果,添加元素,添加客户端iP
地理空间(GEO)

用二维的经纬度表示,经度范围 (-180, 180],纬度范围 (-90, 90],只要我们确定一个点的经纬度就可以名取得他在地球的位置

geoadd key1 经度1 纬度1 “天安门” 经度2 纬度2 “天安门2”  # 添加经纬度坐标
ZRANGE key1 0 -1                                   # 获取全部的value值
# 如果返回值,有中文乱码,解决:redis -cli -a 123456 – raw (在外部,Linux命令行输入)
geopos key1  天安门 天安门2  # 返回经纬度
GEOHASH key1 天安门 天安门2  # 返回经纬度坐标的(base32编码)
GEODIST key1 天安门 故宫 km  # 返回两个位置之间的距离,km是单位:千米 或 m:米
GEORADIUS 以给定的经纬度为中心, 返回键包含的位置元素当中,与中心的距离不超过给定最大距离的所有位置元素
# 例子:GEORADIUS key1 114.12 39.2 10 km withcoord withhash count 10 desc
# key (现在的经纬度) 10 (km或m) withcoord(会打印hash值)withhash(返回经纬度坐标)count 10(返回10条)
GEORADIUSBYMEMBER 它这个输入范围元素 例:GEORADIUS key1 天安门 10 km ...
流(Stream)

可以做消息队列,Stream流 (Redis版的MQ消息中间件+阻塞队列),但生产案例实例少,不能等价于Kafka和RabbitMQ

# 使用List实现消息队列(点对点模式)
lpush  key1 1 2 3   # 进行添加集合
lrange key 1        # 从左边查看一个 lrange key 0 -1 遍历全部数据
位域(bitfield)

将 Redis 字符串看作是一个二进制位组成的数组,这个很少使用,汇编语言。

数据持久化

  • RDB (指定时间间隔执行数据集的时间点快照)

    快照文件就称为RDB文件(dump.rdb)

    优点:适合大规模的数据恢复、速度比AOF快、按照业务时间定时备份

    缺点:如果down机,最近一次快照数据会丢失、数据量大IO操作时间长

    默认触发RDB快照:

    配置文件配置、手动save或者BGSAVE 、主从复制、手动执行shutdown并没有开启AOF持久化

    进行配置文件配置:

    # 在redis 7 进行配置,按照 redis.conf 里配置的 (save是命令)
    # 3600秒 修改一次 或 100秒 修改60次 或 60秒 修改10000次,满足以上就触发保存,保存到RDB文件中
    save 3600 1 300 100 60 100  
    # save "" # 这么配置是禁止RDB模式
    
    # 修改文件保存地址
    dir /my/dump自己文件目录   # 可通过命令查看保存地址位置:config get dir
    
    # 修改文件名称
    dbfilename 自己的文件名.rdb
    
    # 进行物理恢复数据 (BGSAVE是命令)
    1. 在配置文件目录下,进行备份文件(备份文件.rdb),备份到其他位置上
    2. 注意:中断、退出、执行重启,系统都会自动生成rdb文件
    3. 我们把(备份文件.rdb)放到配置文件目录下,清空其他rdb文件
    4. 在redis客户端命令下,执行BGSAVE,会执行备份文件的恢复
    
  • AOF(以日志的形式来记录每个写操作)

    默认是不开启,它有3种写回策略:always 同步写回、everyses 每秒写回(默认)、no 由操作系统控制

    优点:更好保护数据,适合做紧急数据恢复

    缺点:恢复速度慢,aof文件大于rdf文件

    进行配置文件配置:

    # 开启配置: appendonly yes
    
    # 修改文件保存地址,默认跟RDB一个目录下
    dir /my/dump自己文件目录
    # 也可以指定自己目录,这个只有redis7版本之后有,会在dir这个之后,
    # 例:/my/dump自己文件目录/AOF目录/xxx.aof
    appenddirname "AOF目录"
    
    # 修改文件名称
    appendfilename "appendonly.aof"
    # redis7版本后会有
    appendonly.aof.1.base.rdb  # 1.基本文件
    appendonly.aof.1.incr.aof  # 2.增量文件
    appendonly.aof.2.incr.aof  # 2.增量文件
    appendonly.aof.manifest    # 3.清单文件
    
    # 进行物理恢复数据 
    1. 在配置文件目录下,进行备份目录(AOF目录,它下面有多个文件),备份到其他位置上
    2. 注意:中断、退出、执行重启,系统都会自动生成rdb文件,需要清空掉rdb文件
    3. 我们把(备份文件.rdb)放到配置文件目录下,清空其他rdb文件和AOF目录
    4. 在redis客户端命令下,进行重启,重新加载redis,就会数据恢复
    # 如果AOF写操作,只写一半会出现文件异常,在AOF目录下执行
    redis-check-aof --fix appendonly.aof.1.incr.aof  # 异常修复命令 
    # 修复完,进行重启redis
    
    # 重写机制,当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时,目的:减少增量文件大小
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    # 手动重写,在redis客户端,执行命令:bgrewriteaof 
    
    # aof重写期间是否同步
    no-appendfsync-on-rewrite no	
    
  • RDB - AOF混合持久化

    同时开启,如果有aof文件,先执行aof文件,不执行rdb文件,没有就只执行rdb文件;

    rdb做存量,aof做当量;

    # 开启混合模式
    aof-use-rdb-preamble yes  # yes 开启 no 禁用
    
  • 纯缓存模式

    # 关闭rdb+aof,但还可以使用save、bgsave生成rdb文件 和 bgrewriteaof生成aof文件
    save "" 
    appendonly no
    

事务

Redis是单线程架构,在执行事务内的指令,不可能执行其他客户端的请求处理;它在一组队列中,顺序的执行一系列指令;

特点:没有隔离性的概念、不保证原子性(可能一部分成功,一部分失败)、不能回滚、排他性(一个事务依次执行,不会被其他指令插入)

操作:

# 开启事务  MULTI
# 执行事务  EXEC 
# 放弃事务  DISCARD

# 案例
MULTI       # 开启事务
set key1 11 # 添加数据
set key2 22
EXEC   		# 提交事务
# 1 如果中间有语法错误,会直接返回结果,全部指令逻辑都不会执行
# 2 如果中间有语法没错,但没有语法错误,指的是get 不存在的值,事务会有效,会执行有效的指令
Watch 监控

相当于Redis的乐观锁,一旦执行了EXEC,监控也就会取消

watch
# 开始进行监控,先监控再开启事务,保证两key变动在同一事务内,如果有其他人先修改了k1,会返回null,执行失败,比较并交换

# 案例:
get k1
watch k1
MULTI        # 提交事务
set k1 新值1  # 修改数据
set k2 新值2  
get k1
get k2
EXEC   		 # 提交事务

unwatch  
# 放弃监控

# 案例:
get k1
watch k1
get k2
unwatch

管道

就是一次性发送多条命令给服务端,减少客户端与Redis服务端的通信次数;

# 批处理
# 可以把多个命令写一个txt文件中,然后执行批处理
cat cmd.txt
# 执行批处理
cat cmd.txt | redis-cli -a redis密码 -- pipe

管道与事务的区别:

事务具有原子性,管道没有;

管道是一次性将多条指令发送服务端,事务是一条一条发,并且只有提交事务才执行;

常用批量删除

# 批量删除 - 通过管道进行批量删除,“***” 代表 key前缀 (在Linux)
redis-cli -a 密码 keys "***" | xargs redis-cli del

发布订阅

消息通信模式:

  • 发送者 - 发送消息
  • 订阅者 - 接受消息

一般很少使用,不推荐,因必须先订阅才有发送者进行发送消息

SUBSCRIBE channel [channel]   # 订阅多个频道
PUBLISH channel message       # 对一个频道发布信息
PSUBSCRIBE pattern [pattern...]  # 按照模式批量订阅,订阅一个或多个符合给定模式(支持*号?号之类的)的频道
PUSUB CHANNELS                # 由活跃频道组成的列表
PUSUB NUMSUB channel [channel...]   # 某个频道有几个订阅者
PUBSUB NUMPAT   # 只统计使用PUBSCRIBE 命令执行的,返回客户端订阅的唯一模式的数量
UNSUBSCRIBE channel [channel...]    # 取消订阅
PUNSUBSCRIBE pattern [pattern...]   # 退订所有给定模式的频道

主从复制

master以写为主,slave以读为主

基本命令

info replication   # 查看主从关系和配置信息
replicaof 主库IP 主库端口   # 从库认主库,在从库这里配置
slaveof 主库IP 主库端口     # 更换主库地址
slaveof no one     # 当前从库升级为主库,停止与其他数据库的同步
# 注意:命令执行,一但redis重启就失效
配置一主两从

一个主机可以有2个从机,也可以一个主机有一个从机,这个从机下有个从机,这样目的可以减少一个主机同步的压力

主库配置:

# 配置主库,主库配置文件:
daemonize yes        # 开启后台启动
注释掉 bind 127.0.0.1 # 注释掉,允许其他机器访问本机
protected-mode no    # 保护模式关闭
port 6379			 # 指定端口
dir /myredis/配置绝对路径 # 指定当前工作目录 dir
pidfile /var/run/redis_6379.pid   # 文件进程id,默认也是这个地址,需要知道该地址
loglevel notice    # redis日志级别,默认就是notice
logfile "/myredis6379.log"        #  日志存放地址,默认是"",指定自己的目录
requirepass 12345  # 设置redis的密码
dbfilename dump6379.rdb       # 开启rdb数据持久化模式
appendonly yes 			      # 开启aof数据持久化模式
appendfilename appendonly.aof

# 配置从机,从机配置文件(从机配置上主机的ip、端口、密码)
redis6380.conf (slave)
replicaof 主机的ip 主机的端口  # 例:replicaof 127.1.xx 6379
masterauthc "主机的访问密码"
# 注意:不同的从机的,端口号不同,防火墙也需要关闭

# 配置完,分别重启redis
cd /usr/local/bin   # 在该目录
redis-server /myredis/redis7.conf  # 通过指定自己的配置文件启动

# 查看主机日志,是否配置成功
tail -f myredis6379.log
# 先看主机日志:如果看到Synchronization with replica 从机ip地址:从机端口号 succeeded  (代表成功)
# 再看从机日志:如果看到Connecting to MASTER 主机ip:主机端口号 (代表从机连接到主机)
# 还可以通过 info replication   # 查看主从关系和配置信息

防火墙关闭

启动: systemctl start firewalld
关闭: systemctl stop firewalld
查看状态: systemctl status firewalld 
开机禁用  : systemctl disable firewalld
开机启用  : systemctl enable firewalld
    
添加 :firewall-cmd --zone=public --add-port=80/tcp --permanent    (--permanent永久生效,没有此参数重启后失效)
重新载入: firewall-cmd --reload
查看: firewall-cmd --zone= public --query-port=80/tcp
删除: firewall-cmd --zone= public --remove-port=80/tcp --permanent

复制原理:

同步机制开启后,主机会发送给从机sync命令,首次连接,进行全量复制,随机会有心跳检测,平稳阶段,进行增量复制,每个主机对应从机都有偏移量,记住从机复制到哪里,如果从机端口,会从偏移量继续传递复制。

哨兵

用来监控后台master主机是否故障,如果故障了根据投票重新选举一个新主库,一般哨兵为3个,1个主机,2个从机。

配置哨兵

# 一般在/opt/redis目录下有sentinel.conf配置文件,哨兵的配置文件(默认的)
# 我们进行配置,/myredis/redis7.conf 这个目录下是启动redis配置文件,我们也在该目录下创建哨兵的配置文件sentinel.conf

daemonize yes        # 开启后台启动
注释掉 bind 127.0.0.1 # 注释掉,允许其他机器访问本机
protected-mode no    # 保护模式关闭
port 26379			 # 指定端口
dir /myredis/配置绝对路径 # 指定当前工作目录 dir
pidfile /var/run/redis_sentinel26379.pid   # 文件进程id,默认也是这个地址,需要知道该地址
logfile "/mysentinel26379.log"             #  日志存放地址,默认是"",指定自己的目录
# sentinel monitor 主机的名字 主机的ip地址 端口号 几个哨兵认同就代表它成为主机
sentinel monitor mymaster 192.xxx 6379 2
# sentinel auth-pass 主机的名字 主机的访问密码
sentinel auth-pass mymaster 主机的访问密码
# 主观下线,默认超过30秒,心跳检测30秒内没有回复,代表主机下线了(单位:毫秒)
sentinel down-after-milliseconds mymaster 30000

# 如有3个哨兵,需要写3个哨兵的配置文件,进行分别启动,注意:从机需要都配置主机的访问密码

启动哨兵

# 启动哨兵前,需要启动1个主机和2个从机,完成一主两从的配置
redis-server /myredis/redis6379.conf 
redis-server /myredis/redis6380.conf 
redis-server /myredis/redis6381.conf
# 启动哨兵
cd /myredis
redis-sentinel sentinel26379.conf --sentinel
redis-sentinel sentinel26380.conf --sentinel
redis-sentinel sentinel26381.conf --sentinel
# 可在 /mysentinel26379.log 日志文件中查看哨兵的日志,观察是否配置成功

哨兵的数量最好是奇数,哨兵+主从复制,并不能保证数据不丢失。

集群

用来解决数据量过大,单个Master难以满足需求,需要多个主机和从机。集群配置,就不再需要哨兵功能,客户端连接Redis只需要连接其中一个节点就可以,进行读写。连接是通过(槽位slot)负责分配到各个节点,槽位最多是12384,但建议不超过1000个,槽点分片到不同的Redis机器中,分配到的方式有3种。

Redis集群分布式存储方法

  • 哈希取余分区

    hash值取余 ,计算出哈希值,用来决定映射到哪台Redis中。缺点:不容易扩容。

  • 一致性哈希算法

    hash函数按照算法产生的hash值,在算法中形成一个首尾相连的圆形,每个圆形不同的区域分布不同的Redis机器,这样的好处,如果新增一台机器,方便扩容;缺点:就是算法很容易数据倾斜,不平均。

  • 哈希槽分区

    它是一个数组,它增加了一层哈希槽,一个集群有16384个槽,这些槽会分配给集群中的所有主节点;优点:方便扩容分派查找;Redis集群数量不可能有1000个,节点越多,心跳检测,传输数量越大。

集群配置(三主三从)

前提需要6个Redis服务主机,Redis配置文件放在/myredis/cluster目录下

步骤1:配置每台Redis配置

# 主机1配置 - 端口6381
# 进行配置:vim /myredis/cluster/redisCluster6381.conf
bind 0.0.0.0
daemonize yes
protected-mode no
port 6381
logfile "/myredis/cluster/cluster6381.log"
pidfile /myredis/cluster6381.pid
dir /myredis/cluster
dbfilename dump6381.rdb
appendonly yes
appendfilename "appendonly6381.aof"
requirepass 123456
masterauth 123456
# 开启集群配置
cluster-enabled yes
# 集群配置文件
cluster-config-file nodes-6381.conf
# 集群超时连接时间
cluster-node-timeout 5000

# 主机2配置 - 端口6382
# 进行配置:vim /myredis/cluster/redisCluster6382.conf
bind 0.0.0.0
daemonize yes
protected-mode no
port 6382
logfile "/myredis/cluster/cluster6382.log"
pidfile /myredis/cluster6382.pid
dir /myredis/cluster
dbfilename dump6382.rdb
appendonly yes
appendfilename "appendonly6382.aof"
requirepass 123456
masterauth 123456
cluster-enabled yes
cluster-config-file nodes-6382.conf
cluster-node-timeout 5000

# 主机3配置 - 端口6383
# 同上,进行配置:vim /myredis/cluster/redisCluster6383.conf
cluster-enabled yes
cluster-config-file nodes-6383.conf
cluster-node-timeout 5000

# 主机4配置 - 端口6384
# 同上,进行配置:vim /myredis/cluster/redisCluster6384.conf
cluster-enabled yes
cluster-config-file nodes-6384.conf
cluster-node-timeout 5000

# 主机5配置 - 端口6385
# 同上,进行配置:vim /myredis/cluster/redisCluster6385.conf
cluster-enabled yes
cluster-config-file nodes-6385.conf
cluster-node-timeout 5000

# 主机6配置 - 端口6386
# 同上,进行配置:vim /myredis/cluster/redisCluster6386.conf
cluster-enabled yes
cluster-config-file nodes-6386.conf
cluster-node-timeout 5000

步骤2:启动每台Redis配置

redis-server /myredis/cluster/redisCluter6381.conf 
..........
redis-server /myredis/cluster/redisCluter6386.conf 

# 通过命令查询redis启动是否成功
ps -ef|grep redis

步骤3:使用redis-cli命令为6台机器构建集群关系启动每台Redis配置

# -cluster-replicas 1 表示为每个master创建一个slave节点
redis-cli -a (redis密码) --cluster create --cluster-replicas 1 192.IP地址.1:6381 192.IP地址.1:6382 192.IP地址.2:6383 192.IP地址.2:6384 192.IP地址.3:6385 192.IP地址.3:6386

# 中途输入yes

步骤4:检查是否成功

# 登录 其中一台redis
redis-cli -a 设置的密码 -p 6381 -c
# -c表示集群 不加的话不是按照集群启动的,对于在别的机器上的key,会报错

# 查看节点状态
cluster nodes  # 查看集群的主从关系
# 输出信息,显示哪些是主机,哪些是从机,但主机和从机对应的顺序是随机的

# 查看集群信息
cluster info  
# 输出信息,显示当前机器是主机还是从机,还有槽的状态,有几个节点

# 查看主从
info replication  
# 输出信息,显示当前机器信息

步骤5:配置成功

# 我们可以登陆其中一台redis
redis-cli -a 设置的密码 -p 6381 -c
# 进行新建、查询
# 查看某个key是哪个槽位
cluster keyslot 键名称

步骤6:主从容错切换迁移

# 随着时间,主机6381该主机,之前是主机,如果它断了,它下面的从机会变成主机
# 当主机6381重启后,它还是从机,不再是主机
# 想要原先的master继续做master的话
CLUSTER FAILOVER   # 让谁上位 就在谁的端口号下执行这个命令

步骤7:主从扩容

# 1.创建2个Redis,配置文件大致与前几台一致,新Redis机器端口为6387、6388 
# 2.启动Redis,分别启动
redis-server /myredis/cluster/redisCluster6388.conf 
redis-server /myredis/cluster/redisCluster6387.conf
# 3.将新增的6387节点作为master加入原集群,之前6381节点是主机
redis-cli -a redis密码 --cluster add-node 192.IP地址.4:6387 192.IP地址.1:6381
# -- 相当于新的master主机(6387)拜之前的master主机(6381)看到最后一行有ok代表成功
# 4.检查集群情况,6381
redis-cli -a redis密码 --cluster check 192.IP地址.1:6381
# 会打印出有哪些master主机,还可以看到哪些主机对应的槽号
# 5.分配槽号,默认新创建的Redis没有分配槽号
redis-cli -a redis密码 --cluster reshard 192.IP地址.1:6381
# 然后执行完该命令,中途会输入分配哪些槽号,输入4096 (总槽号是16384,如果4台:16384/4=4096)
# 然后还会再输入一个ID,ID是6387这台主机的ID,(谁来接收的主机ID)
# 然后再输入all,(代表谁分配的,all代表大家都分配一点,这里也可以指定6381这主机的ID,代表这台机器分配)
# 然后再输入yes,就配置完成
# 5.检查集群情况,6381,第二次检查
redis-cli -a redis密码 --cluster check 192.IP地址.1:6381
# 就可以重新分配后的槽号
# 6.为主节点6387分配从节点6388
redis-cli -a redis密码 --cluster add-node 192.IP地址.4:6388 192.IP地址.4:6387 --cluster-slave --cluster-master-id b86176(6387主机的ID)
# 7.查看集群最新配置
redis-cli -a 设置的密码 -p 6381 -c  # 登录其中一台Redis机器
cluster nodes  # 查看集群的主从关系 ,也可以看到每台机器的ID

步骤8:主从缩容

# 1.6387和6388下线,先删除从机6388节点
redis-cli -a redis密码 --cluster check 192.IP地址.4:6388    # 先得到6388、6381、6387主机的ID 
redis-cli -a redis密码 --cluster del-node 192.IP地址.4:6388 4111(6388主机的ID)
# 2.检查节点,在其他Redis主机检查,6388主机已不见
redis-cli -a redis密码 --cluster check 192.IP地址.1:6381
# 3.将6387的槽号情况,重新分配,先全部都给6381主机
redis-cli -a redis密码 --cluster reshard 192.IP地址.1:6381 
# 然后执行完该命令,中途会输入分配哪些槽号,输入4096 (总槽号是16384,如果4台:16384/4=4096)
# 然后还会再输入一个ID,ID是6381这台主机的ID,(谁来接收的主机ID,这4096槽号由6381主机接收)
# 然后再输入6387主机ID,(代表6387主机要删除这4096槽号)
# 然后再输入 done
# 然后再输入 yes,配置完成
# 4.检查节点,在其他Redis主机检查,6387主机已变成从机
redis-cli -a redis密码 --cluster check 192.IP地址.1:6381
# 5.删除从机6387节点
redis-cli -a redis密码 --cluster del-node 192.IP地址.4:6387 xxx(6387主机的ID)
# 6.查看集群最新配置
redis-cli -a 设置的密码 -p 6381 -c  # 登录其中一台Redis机器
cluster nodes  # 查看集群的主从关系 ,也可以看到每台机器的ID

注意:

在Redis配置文件中,默认是yes,代表如果配置3主3从,如果其中1主1从的机器挂掉了,整个集群是不完整的,redis默认不会对外访问,如果改为no,是对外提供,可以访问Redis

cluster- require- full- coverage yes

Spring Boot集成Redis

一般我们使用RedisTemplate 、Jedis(过时)

连接单机
# 1.引包
<!--SpringBoot与Redis整合依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
# 2.配置文件
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=123456
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
# 3.Redis配置类
@Configuration
public class RedisConfig {

    /**
     * redis序列化的工具配置类 - 避免查看redis有乱码
     * @param lettuceConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory)
    {
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        //设置key序列化方式string
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置value的序列化方式json,使用GenericJackson2JsonRedisSerializer替换默认序列化
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}
# 4.基本使用
@Resource
private RedisTemplate redisTemplate;     
// 写
redisTemplate.opsForValue().set(key, value);    
// 读
String str = (String) redisTemplate.opsForValue().get(keyId);
连接集群
# 配置文件修改
spring.redis.password=123456
#获取失败,集群最大重定向次数
spring.redis.cluster.max-redirects=3
spring.redis.clusterspring.redis.cluster.nodes=192.1.max-redirects=3
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
# 集群节点 - 6个
spring.redis.cluster.nodes=127.0.0.1:6381,127.0.0.1:6382,127.0.0.1:6383,127.0.0.1:6384,127.0.0.1:6385,127.0.0.1:6386
# 注意:如果其中有一台集群挂掉,会报错,因:Redis默认的是 Lettuce、
# 解决方案1:下面2个配置
# 支持集群拓扑动态感应刷新,自适应拓扑刷新是否使用所有可用的更新,默认false关闭
spring.redis.lettuce.cluster.refresh.adaptive=true
# 定时刷新
spring.redis.lettuce.cluster.refresh.period=2000
# 解决方案2:引入新包(不推荐)
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
	<exclusions>
		<exclusion>
			<groupId>io.lettuce</groupId>
			<artifactId>lettuce-core</artifactId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>3.7.0</version>
</dependency>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值