Redis

一、Redis 简介

Redis (Remote Dictionary Server) 远程字典服务,

是一个开源的使用ANSI C语言编写、支持网络、

可基于内存亦可持久化的日志型、Key-Value

据库(NoSQL一种),并提供多种语言的API

Redis 之父-- Salvatore Sanfilippo,也叫安特雷兹

与 MySQL 数据库不同的是,Redis 的数据存

在内存中,它的读写速度非常快,每秒可以处理

超过10万次读写操作

因此redis被广泛应用于缓存,另外,Redis也经常

用来做分布式锁。除此之外,Redis支持事务、持

久化、LUA 脚本、LRU 驱动事件、多种集群方案

2. Redis 的功能和应用

① 分布式缓存

② 内存存储和持久化(RDB+AOF)

redis 支持异步将内存中的数据写到硬盘上,

同时不影响继续服务

③ 高可用架构搭配

④ 缓存穿透、击穿、学崩

⑤ 分布式锁

⑥ 队列

提供 listset 操作

⑦ 排行榜+点赞

3. 优势

① 性能极高,读写速度快

② 数据类型丰富,不仅支持 k-v 数据,还支

    持 list、set、zset、hash 等数据结构的存

    储

③ 支持数据的持久化,可以将内存中的数据

    保持在磁盘中,重启的时候可以再次加载

    进行使用

④ 支持数据的备份,即 master-slave 模式

    的数据备份

二、安装 redis

(1) Linux 环境安装 Redis 必须先具备 gcc 编译环境

安装C++库环境:

yum -y install gcc- c++

查看:

gcc -v

Redis 建议安装:6.0.8 版本以上

(2) 下载获得 redis-7.0.9.tar.gz 后将它放入我们的

      Linux 目录 /opt 

① tar -zxvf redis7.0.9.tar.gz     /opt目录下解压
② cd redis7.0.9.tar.gz             进入目录
③ make && make install         在redis7.0.9目录下执行
④ cd /usr/local/bin                   默认安装的位置查看                                   

//Linux 下的 /user/local/bin 类似 windows 下的

C:\Program Files

安装完之后查看:

$ find . -type f -executable
redis-benchmark:用于进行redis性能测试的工具
redis-check-dump:用于修复出问题的dump.rdb文件
redis-cli:redis的客户端
redis-server:redis的服务端
redis-check-aof:用于修复出问题的AOF文件
redis-sentinel:用于集群管理

(3) 安装完后回到 /opt/redis7.0.9/

  1) 将默认的 redis.conf 拷贝到自己定义好的一个路径下,

比如 /myredis

⑤ mkdir /myredis                在根目录下创建myredis
⑥ cp redis.conf /myredis/redis7.conf     将默认的复制过去

  2) 修改/myredis目录下redis7.conf配置文件做初始化设置

//redis.conf 配置文件,改完后确保生效,一定要重启

⑦ vim /myredis/redis7.conf             

① 默认 daemonize no 改为 daemonize yes

② 默认 protected-mode yes 改为 protected-mode no

③ 默认 bind 127.0.0.1 改为 直接注释掉(默认bind 127.0.0.1

    只能本机访问)或改成本机IP地址,否则影响远程IP连接

④ 添加redis密码 改为 requirepass 你自己设置的密码

(4) 在/usr/local/bin目录下运行redis-server,启用/myredis

     目录下的redis7.conf

⑧ redis-server /myredis/redis7.conf

连接服务

⑨ redis-cli -a 设置的密码 -p 6379 
⑩ 测试  ping  

     PONG

登录redis 有一个 warning 警告

redis-cli -a 123456 

在后面加上 2>/dev/null 可以去除

redis-cli -a 123456 2>/dev/null

 (5) 关闭

单实例关闭 : redis-cli -a 123456 shutdown
多实例关闭,指定端口号关闭: redis-cli -p 6379 shutdown

 (6) 卸载

停止 redis-server 服务

删除 /user/local/lib 目录下与 redis 相关的文件

rm -rf  /user/local/lib/redis- *

helloworld:

set k1 hello

get k1

二、redis 十大数据类型

① redis 字符串(String)

② redis 列表(List)

③ redis 哈希表(Hash)

④ redis 集合(Set)

⑤ redis 有序集合(ZSet)

⑥ redis 地理空间(GEO)

⑦ redis 基数统计(HyperLogLog)

⑧ redis 位图(bitmap)

⑨ redis 位域(bitfield)

⑩ redis 流(Stream)

常见数据类型操作命令:

官网:https://redis.io/commands/

中文:https://redis.cn/commands.html

key 操作命令:

keys *查看当前库所有的 key
exists key判断某个 key 是否存在
type key查看 key 类型
del key删除指定的 key 数据
unlink key

非阻塞删除,仅仅将 keys 从 keyspace

元数据中删除,真正的删除会在后续异步

中操作

ttl key

查看还有多少秒过期,-1 表示永不过期,

-2 表示已过期

expire key 秒钟为给定的 key 设置过期时间
move key dbindex【0-15】

给当前数据库的 key 移动到给定的数据库

db 当中

dbsize查看当前数据库 key 的数量
select dbindex切换数据库【0-15】,默认为 0
flushdb清空当前库
flushall通杀全部库

命令不区分大小写,而 key 区分大小写

永远的帮助命令,help @类型

1. String (字符串)

string是redis最基本的数据类型,一个key对应一个

value,一个value最多可以是512M,string类型是

二进制安全的,可以包含任何数据,比如jpg图片

或者序列化的对象 

官网命令:https://redis.io/docs/data-types/strings

(1) 最常用:

set key value

get key

SET key value [NX | XX] [GET] [EX seconds | 
  PX milliseconds | EXAT unix-time-seconds | 
  PXAT unix-time-milliseconds | KEEPTTL]

(2) 同时设置/获取多个键值

MSET key value [key value ...]

MGET key [key ...]

mset/mget/msetnx

(3) 获取指定区间范围内的值

getrange

setrange

(4) 数值增减

一定要是数字才能进行加减

INCR key                              递增数字

INCRBY key increment        增加指定的整数

DECR key                            递减数值

DECRBY key increment       减少指定的整数

(5) 获取字符串长度和内容追加

STRLEN key

APPEND key value

(6) 分布式锁

setnx key value

setex (set with expire) 键秒值/setnx(set if not exist)

(7) getset(先get再set)

将给定 key 的值设为 value,并返回 key 的旧值(old value)

2. List (列表)

简单的字符串列表,按插入顺序排序,底层是双端列

,可以在头尾两端插入

(1) lpush/rpush/lrange

(2) lpop/rpop

(3) lindex,按照索引下标获得元素(从上到下)

(4) llen,获取列表中元素的个数

(5) lrem key,数字N给定值v1(删除N个值等于v1的元素)

(6) Itrim key,开始index 结束index,截取指定范围的值后

                      再赋值给key

(7) rpoplpush,源列表 目的列表

(8) lset key index value

(9) linsert key before/after 已有值 插入的新值

3. Hash (哈希)

是一个 String类型的 field 字段和 value值的映射表,

hash 特别适用于存储对象,KV模式不变,但V是一

键值对

(1) hset/hget/hmset/hmget/hgetall/hdel

(2) hlen 获取某个key内的全部数量

(3) hexists key 在key里面的某个值的key

(4) hkeys/hvals

(5) hincrbyfloat

(6) hsetnx

4. Set (集合)

是String类型的无序集合,集合成员是唯一的,

不能出现重复数据,集合对象的编码可以是

Intset 或 hashtable

redis 中Set集合是通过哈希表实现的,所以添

加、查找、删除的复杂度都是 O(1)

(1) SADD key member [member...] 添加元素

(2) SMEMBERS key 遍历集合中的所有元素

(3) SISMEMBER key member 判断元素是否

     在集合中

(4) SREM key member [member...] 删除元素

(5) scard,获取集合里面的元素个数

(6) SRANDMEMBER key [数字] 

     从集合中随机展现设置的数字个数元素,

     元素不删除

(7) SPOP key [数字] 从集合中随机弹出一个元

     素,出一个删一个

(8) smove key1 key2 在key1里已存在的某个值

     将key1里已存在的某个值赋给key2

(9) 集合运算

① 集合的差集运算 A-B        SDIFF key [key]

② 集合的并集运算 A ∪ B    SUNION key [key]

③ 集合的交集运算 A ∩ B     SINTER key [key]

SINTERCARD numkeys key [key...]  [LIMIT limit]

不返回结果集,而只返回结果的基数,返回由所有

给定集合的交集产生的集合的基数

5. ZSet (sorted set: 有序集合)

和 set 一样都是String类型元素的集合,且不允许

重复的成员

不同之处:

每个元素都会关联一个double类型的分数(score),

通过分数为集合成员从小到大排序,成员唯一

分数(score)可重复

(1) 向有序集合中加入一个元素和该元素的分数

(2) ZADD key score member [score member...]

     添加元素

(3) ZRANGE key start stop [WITHSCORES]

     按照元素分数从小到大的顺序,返回索引从

     start到stop之间的所有元素

(4) zrevrange 反转顺序

(5) ZRANGEBYSCORE key min max

[WITHSCORES] [LIMIT offset count]

    获取指定分数范围的元素

withscores

(        不包含

limit 作用是返回限制

(6) ZSCORE key member 获取元素的分数

(7) ZCARD key 获取集合中元素的数量

(8) zrem key 某score下对应的value值,

     作用是删除元素

(9) ZINCRBY key increment member

     增加某个元素的分数

(10) ZCOUNT key min max 获取指定分数范围内

       的元素个数

(11) ZMPOP 从键名列表中的第一个非空排序集中

       弹出一个或多个元素,它们是成员分数对

(12) zrank key values值,作用是获得下标值

(13) zrevrank key values值,作用是逆序获得下标值 

6. GEO (地理空间)

主要用于存储地理位置信息,并对其进行操作

添加、获取地理位置的坐标,计算两者之间距离,

根据用户给定的经纬度坐标来获取指定范围内的

地理位置集合

获取经纬度:http://api.map.baidu.com/lbsapi/getpoint/

(1) GEOADD 添加经纬度坐标

redis- cli -- raw 可解决中文乱码问题 

(2) GEOPOS 返回经纬度

(3) GEOHASH 返回坐标的geohash表示

① geohash算法生成的base32编码值

② 三维变二维变一维,最后将一维的点块转换

    为二进制再通过base32编码

(4) GEODIST 两个位置之间距离

    (m米/km千米/ft英尺/mi英里)

(5) GEORADIUS半径为中心查找附近的xx

(6) GEORADIUSBYMEMBER 找出位于指定范围内的

     元素,中心点是由给定的位置元素决定

7. HyperLogLog (基数统计)

优点是在输入元素数量体积非常时,计算

基数所需的空间总是固定且是很小

每个HyperLogLog 只需花费 12 kb内存就可计算

接近 2^64 个不同元素的基数,但因其只能根据

入元素计算基数,而不会储存输入元素本身,所

以不能像集合那样,返回输入的各个元素

基数:是一种数据集,去重复后的真实个数

(1) PFADD key element [element...]

添加指定元素到 HyperLogLog中

(2) PFCOUNT key [key...]

返回给定 HyperLogLog 的基数估算值

(3) PFMERGE destkey sourcekey [sourcekey...]

将多个 HyperLogLog 合并为一个 HyperLogLog

8. bitmap(位图)

由 0 和 1 状态表现得二进制位的 bit 数组

用String类型作为底层数据结构实现的一种统计二

值状态的数据类型,极大节约存储空间,bitmap的

偏移量是从零开始算的

(1) setbit key offset val

给指定key的值的第offset赋值val,时间复杂度O(1)

(2) getbit key offset 

获取指定key的第offset位,O(1)

(3) bitcount key start end

返回指定key中[start,end]中为1的数量,O(n)

(4) bitop operation destkey key

对不同的二进制存储数据进行位运算(AND、OR、

NOT、XOR),O(n)

(5) strlen 统计字节数占用多少

9. bitfield(位域)

可以一次性操作多个比特位域(指的是连续的多个比

特位),它会执行一系列操作并返回一个响应数组

这个数组中的元素对应参数列表中的相应操作的执行

结果(位域修改,溢出控制)

将一个Redis字符串看作是一个由二进制位组成的数组

并能对变长位宽和任意没有字节对齐的指定整型位域进

行寻址和修改

Ascii 码表:https://ascii.org.cn/ 

当需要一个整型时,有符号整型需在位数前加 i

无符号在位数前加 u

(1) BITFIELD key [GET type offset]  返回指定的位域

(2) BITFIELD key [SET type offset value] 

     设置指定位域的值并返回它的原值

(3) BITFIELD key [INCRBY type offset increment]

     自增或自减 (如果increment为负数) 指定位域的值

     并返回它的新值

     默认情况下,INCRBY使用 WRAP 参数

(4) 溢出控制 OVERFLOW [WRAP|SAT|FAIL]

WRAP:使用回绕(wrap around)方法处理有符号

              整数和无符号整数的溢出情况

SAT:使用饱和计算(saturation arithmetic)方法处

          理溢出,下溢计算的结果为最小的整数值,

          而上溢计算的结果为最大的整数值

           (-128~127)

FAIL:命令将拒绝执行那些会导致上溢或者下溢

           情况出现的计算,并向用户返回空值表示

           计算未被执行

10. Stream(流)

主要用于消息队列,Redis 本身有一个 Redis 发布

订阅(pub/sub) 来实现消息队列的功能,缺点是消息

无法持久化,如果出现网络断开、Redis 宕机等,消

息就会被丢弃

Stream 提供了消息的持久化主备复制功能,可以

让任何客户端访问任何时刻的数据,并且能记住每一

个客户端的访问位置,还能保证销量不消失

Redis版的MQ消息中间件+阻塞队列

(1) 队列相关指令

1) XADD 添加消息到队列末尾

消息ID必须要比上个ID大

默认用星号表示自动生成规矩

*        用于XADD命令中,让系统自动生成 id

2) XTRIM 限制Stream的长度,如果已经超长会进行截取

MAXLEN 允许的最大长度,对流进行修剪限制长度

MINID 允许的最小id,从某个id值开始比该id值小的

将会被抛弃

3) XDEL 删除消息

4) XLEN 获取Stream中的消息长度

5) XRANGE 获取消息列表(可以指定范围),忽略删除的消息

start 表示开始值,- 代表最小值

end 表示结束值,+ 代表最大值

count 表示最多获取多少个值

6) XREVRANGE 和XRANGE相比区别在于反向获取,ID从大到小

7) XREAD 获取消息(阻塞/非阻塞),返回大于指定ID的消息

(2) 消费组相关指令

1) XGROUP CREATE 用于创建消费者组

$ 表示从Stream尾部开始消费

0 表示从Stream头部开始消费

创建消费者组的时候必须指定 ID,ID为0表示

从头开始消费,为$表示只消费新的消息,队尾新来 

2) XREADGROUP GROUP

">",表示从第一条尚未被消费的消息开始读取

消费组groupA内的消费者consumer1从mystream

消息队列中读取所有消息,但是不同消费组的消费

可以消费同一条消息

3) XPENDING

查询每个消费组内所有消费者 [已读取、但尚未

确认] 的消息

查看某个消费者具体读取了哪些数据

4) XACK

向消息队列确认消息处理已完成

(3) 四个特殊符号

- +         最小和最大可能出现的id

$           $表示只消费新的消息,当前流中最大

             的id,可用于将要到来的信息

>           用于XREADGROUP命令,表示迄今

             没有发送给组中使用者的信息,会更新

             消费者组的最后 ID

*           用于XADD命令中,让系统自动生成id

(4) XINFO 用于打印Stream\Consumer\Group的详细信息

三、 redis 持久化

https://redis.io/docs/manual/persistence/

1. RDB(Redis DataBase)

指定的时间间隔,执行数据集的时间点快照

作用:

在指定的时间间隔内将内存中的数据集快照写入

磁盘,也就是Snapshot内存快照,它恢复时再将

硬盘快照文件直接读回到内存里,RDB保存的是

dump.rdb文件,保存备份的是全量快照,一锅端

(2) 配置 RDB

   1) 自动触发

① Redis7版本,按照redis.conf里配置的

     save <seconds> <changes>

② 本次案例5秒2次修改 save 5 2

③ 修改dump文件保存路径

④ 修改dump文件名称

     dbfilename dump.rdb→

     dbfilename dump6379.rdb

⑤ 触发备份,2种方法

⑥ 恢复备份

     将备份文件(dump.rdb)移动到redis安装

     目录并启动服务即可,

     备份成功后故意用flushdb清空redis,看

     看是否可以恢复数据,     →结论:执行

      flushall/flushdb命令也会产生dump.rdb

      文件,但里面是空的,无意义

     物理恢复,一定服务和备份分机隔离

 

   2)手动触发

Redis提供了两个命令来生成RDB文件,分别

savebgsave

① Save

在主程序中执行会阻塞当前redis服务器,直到

持久化工作完成执行save命令期间,Redis不能

处理其他命令,线上禁止使用

② BGSAVE(默认)

Redis会在后台异步进行快照操作,不阻塞

快照同时还可以响应客户端请求,该触发方

式会fork一个子进程由子进程复制持久化过程

Redis会使用bgsave对当前内存中的所有数据

快照,这个操作是子进程在后台完成的,这 

就允许主进程同时可以修改数据

在Linux中程序中,fork()会产生一个和父进程完

全相同的子进程,但子进程在此后多会exec系统

调用,出于效率考虑,尽量避免膨胀 

LASTSAVE可以通过lastsave命令获取最后一次

成功执行快照的时间

   3) redis 优缺点

优点:

① 适合大规模的数据恢复

② 按照业务定时备份

③ 对数据完整性和一致性要求不高

④ RDB文件在内存中的加载速度要比AOF快的多

缺点:

① 在一定间隔时间做一次备份,所以如果redis意外

     down掉的话,就会丢失从当前至最近一次快照

     期间的数据,快照之间的数据会丢失

② 内存数据的全量同步,如果数据量太大会导致I/O

     严重影响服务器性能

③ RDB依赖于主进程的fork,在更大的数据集中,

     这可能会导致服务请求的瞬间延迟,fork的时候

     内存中的数据被克隆了一份,大致2倍的膨胀性,

     需要考虑

   4) RDB修复命令

   5) 触发RDB快照条件 

① 配置文件中默认的快照配置

② 手动save/bgsave命令

③ 执行flushall/flushdb命令也会产生dump.rdb

     文件,但里面是空的,无意义

④ 执行shutdown且没有设置开启AOF持久化

⑤ 主从复制时,主节点自动触发

   6) 禁用快照

① 动态所有停止RDB保存规则的方法:

     redis-cli config set save " "

② 快照禁用

   7) RDB优化参数

配置文件SNAPSHOTTING模块

save <seconds> <changes>

dbfilename

dir

stop-writes-on-bgsave-error

rdbcompression

rdbchecksum

rdb-del-sync-files

2. AOF(Append Only File)

日志的形式来记录每个写操作,将Redis执

行过的所有写指令记录下来(读操作不记录),

只允许追加文件但不可以改写文件,redis启

动之初会读取该文件重新构建数据,换言之,

redis重启的话就根据日志文件的内容将写指

令从前到后执行一次以完成数据的恢复工作

默认情况下,redis是没有开启AOF的,开启

AOF功能需要设置配置:appendonly yes

AOF保存的是 appendonly.aof 文件

(1) AOF持久化工作流程:

 (2) AOF缓冲区三种写回策略

Always        同步写回,每个写命令执行完立刻

                   同步地将日志写回磁盘

everysec     每秒写回,每个写命令执行完,只

(默认)          是先把日志写到AOF文件的内存缓

                   冲区,每隔1秒把缓冲区中的内容写

                   入磁盘

no               操作系统控制的写回,每个写命令

                   执行完,只是把日志写到AOF文

                   件的内存缓冲区,由操作系统决定

                   何时将缓冲区内容写回磁盘

(3) AOF功能配置开启

  1) 开启aof

      appendonly no→appendonly yes

  2) 使用默认写回策略,每秒钟

      appendonly everysec

  3) aof 文件 - 保存路径

     redis6 保存的位置和rdb一样,都是通过redis.conf

     配置文件的dir配置

     redis7  appenddirname "appendonlydir"

  4) aof 文件 - 保存名称

     redis6 有且仅有一个

     redis7 采用 Multi Part AOF 的设计

① base 基本文件

② incr 增量文件

③ manifest 清单文件

    config 中对应的配置项:

    5) 正常恢复

① 启动:修改默认的appendonly no,改为 yes

② 写操作继续,生成aof文件到指定的目录

③ 恢复1:重启redis然后重新加载,结果OK

④ 恢复2:写入数据进redis,然后flushdb+shutdown

                 服务器,新生成了dump和aof,备份新生成

                 的aof.bak,然后删除dump/aof再看恢复,

                 重启redis然后重新加载试试,停止服务器,

                 拿出我们的备份修改后再重新启动服务器

                 看看

    6) 异常恢复

    写一半网络闪断文件异常

① 重启redis之后就会进行AOF文件的载入,

    发现启动都不行

② 异常修复命令:

     redis- check- aof --fix 进行修复

③ 重新OK

(4) AOF 优缺点

优点:

更好的保护数据不丢失、性能高、可做紧急恢复

缺点:

相同数据集的数据而言aof文件要远于rdb文件,

恢复速度于rdb;aof运行效率要慢于rdb,每秒

同步策略效率较好,不同步效率和rdb相同

(5) AOF 重写机制

当AOF文件的大小超过所设定的峰值时,Redis就

会自动启动AOF文件的内容压缩,只保留可以恢复

数据的最小指令集或者可以手动使用命令

bgrewriteaof 重写

   1) 自动触发

满足配置文件中的选项后,Redis会记录上次重写

时的AOF大小,默认配置是当AOF文件大小是上次

rewrite后大小的一倍且文件大于64M时

   2) 手动触发

客户端向服务器发送bgrewriteaof命令

   3) 前期配置准备:

① 开启aof,appendonly no改为yes

重写峰值修改为1K

关闭混合,设置为 no

删除之前的全部aof和rdb,清除干扰项

 (6) AOF 优化配置项

配置文件 APPEND ONLY MODE模块

 

 3. RDB+AOF混合

(1) 数据恢复和加载流程:

 (2) 同时开启两种持久化方式

RDB持久化方式能够在指定的时间间隔

    对你的数据进行快照存储

AOF持久化方式记录每次对服务器写的操

    作,当服务器重启的时候会重新执行这些

    命令来恢复原始的数据,AOF命令以redis

    协议追加保存每次写的操作到文件末尾

同时开启,在redis重启时会优先载入AOF文件

来恢复原始的数据,因为通常情况下AOF保存

的数据集要比RDB完整,RDB更适合用来备份

数据库

(3) 步骤

① 开启混合方式设置

    设置 aof-use-rdb-preamble 的值为 yes

RDB镜像做全量持久化,AOF增量持久化

     先使用RDB进行快照存储,然后使用AOF

     久化记录所有的写操作,当重写策略满足或

     手动触发重写的时候,将最新的数据存储为

     新的RDB记录

AOF包括RDB头部+AOF混写 

4. 纯缓存模式

同时关闭RDB+AOF

(1) save " "

禁用rdb,禁用rdb持久化模式下,我们仍然可以

使用命令 save、bgsave 生成RDB文件

(2) appendonly no

禁用aof,禁用aof持久化模式下,我们仍然可以

使用命令 bgrewriteaof 生成AOF文件

四、redis 事务

https://redis.io/docs/manual/transactions

可以一次执行多个命令,本质是一组命令的

集合,一个事务中的所有命令都会序列化,

按顺序的串行化执行不会被其他命令插入

不许加塞

1. 作用:

一个队列中,一次性、顺序性、排他性的

执行一系列命令

2. 与数据库事务的区别: 

 3. 常用命令:

(1) 正常执行

     EXEC、MULTI

(2) 放弃事务

     MULTI、DISCARD

(3) 全体连坐

一个语法写错,编译不通过全体连坐

直接返回错误,所有的命令都不执行

(4) 源头债主

前期语法都没有错,编译通过

执行exec后报错,冤有头,债有主,

对的执行,错的停

与传统数据库区别,不一定要么一起成功,

要么一起失败

(5) watch监控

    Redis使用Watch来提供乐观锁定,类似于

    CAS(Check-and-Set)

① 悲观锁

② 乐观锁

③ CAS

1) watch

初始化k1balance两个key,先监控再开启multi

保证两key变动在同一个事务内

加塞篡改

2) unwatch

 小结:

一旦执行了exec之前加的监控锁都会被取消掉了,

当客户端连接丢失的时候(比如退出链接),所有东

西都会被取消监视

五、redis 管道

管道(pipeline)可以一次性发送多条命令

服务端,服务端依次处理完毕后,通过一

条响应一次性将结果返回,通过减少客户

端与Redis的通信次数来实现降低往返延时

时间,pipeline实现的原理是队列先进先

特性就是保证数据的顺序性

    https://redis.io/docs/manual/pipelining/

pipeline是为了解决RTT往返回时,仅仅是

将命令打包一次性发送,对整个Redis的执

行不造成其他任何的影响

批处理命令变种优化措施,类似Redis的原

生批命令(mget和mset)

1. Pipeline 与原生批量命令对比

① 原生批量命令是原子性(例如:mset,mget),

     pipeline非原子性

② 原生批量命令一次只能执行一种命令,pipeline

     支持批量执行不同指令

③ 原生批量命令是服务端实现,而pipeline需要

     务端与客户端共同完成 

2. Pipeline 与事务对比

① 事务具有原子性,管道不具有原子性

② 管道一次性将多条命令发送到服务器,事务是

     一条一条的发,事务只有在接收到exec命令后

     才会执行,管道不会

③ 执行事务时会阻塞其他命令的执行,而执行管

     道中的命令时不会

3. 使用 Pipeline 注意事项 

① pipeline缓冲的指令只是会依次执行,不保证原

    子性,如果执行中指令发生异常,将会继续执行

    后续的指令

② 使用pipeline组装的命令个数不能太多,不然数

    据量过大客户端阻塞的时间可能过久,同时服务

    端此时也被迫回复一个队列答复,占用很多内存

六、redis 发布订阅

是一种消息通信模式:发送者(PUBLISH)发送消息,

订阅者(SUBSCRIBE)接收消息,可以实现进程间的

消息传递

Redis可以实现消息中间件MQ的功能,通过发布订

阅实现消息的引导和分流

发布/订阅其实是一个轻量的队列,只不过数据不会

被持久化,没用来处理实时性较高的异步信息

七、redis 复制(replica)

https://redis.io/docs/management/replication/

主从复制master为主,Slave为主

当master数据变化的时候,自动将新的数据

步同步到其他slave数据库

1. 作用:

① 读写分离

② 容灾恢复

③ 数据备份

④ 水平扩容支撑高并发

2. 权限细节:(重要)

配从(库)不配主(库)

master如果配置了requirepass参数,需要密

码登陆,那么slave就要配置masterauth

置校验密码,否则的话master会拒绝slave的

访问请求

3. 操作命令

info replication 可以查看复制节点的主从关系

                        和配置信息

replicaof 主库IP 主库端口

一般写进redis.conf配置文件内

slaveof 主库IP 主库端口

每次与master断开之后,都需要重新连接,除

非配置进redis.conf文件内

在运行期间修改slave节点的信息,如果该数据

库已经是某个主数据库的从数据库,那么会停

止与原主数据库的同步关系转而和新的主数据

库同步重新拜码头

slaveof no one 使当前数据库1停止与其他数据

                        库的同步,转成主数据库自立

                        为王

4. 案例

(1) 一主二从:拷贝多个redis.conf文件

     redis6379、redis6380、redis6381

    三边网络相互ping通且注意防火墙配置

(2) 三大命令

① 主从复制

replicaof 主库IP 主库端口

配从(库)不配主(库)

② 改换门庭

slaveof 新主库IP 新主库端口

③ 自立为王

slaveof no one

(3) 修改配置文件细节操作

① 开启 daemonize yes

注释掉bind 127.0.0.1

protected-mode no

④ 指定端口

⑤ 指定当前工作目录,dir

⑥ pid 文件名字,pidfile

⑦ log 文件名字,logfile

⑧ requirepass

dump.rdb 名字

⑩ aof文件,appendfilename(可选)

从机访问主机的通行密码masterauth

    (必须)从机需要配置,主机不用

 

(4) 常用三招

  1) 一主二仆

    ① 配置文件固定写死

① 配置文件执行 replicaof 主库IP 主库端口

② 配从不配主

③ 先master后两台slave依次启动

④ 主从关系查看

     日志:主机日志、备机日志

     命令:info replication命令查看

结论: 

① 从机只可以读取,不可以执行写操作

② 主机shhutdown从机原地待命,等待主

    机归来

   ② 命令操作手动指定

配置持久稳定,命令当次生效

   2) 薪火相传

上一个slave可以是下一个slave的master,slave

一样可以接收其他slave的连接和同步请求,那么

slave作为了链条下一个的master,可以有效

轻主master的写压力

中途变更转向:

会清除之前数据,重新建立拷贝最新的

slaveof 新主库IP 新主库端口

   3) 反客为主

SLAVEOF no  one 

使当前数据库停止与其他数据库连接

5. 复制原理和工作流程

slave启动,同步初请

    slave启动成功连接到master后会发送一个

    snyc命令,slave首次全新连接master,一

   次完全同步(全量复制)将被自动执行,slave

   自身原有数据会被master覆盖

首次连接,全量复制

心跳持续,保持通信

    master发出PING包的周期,默认是10秒

    repl- ping replica- period 10

进入平稳,增量复制

从机下线,重连续传

    master会检查backlog里面的offset,master

   和slave都会保存一个复制的offset还有一个

   masterId,offset是保存在backlog中的,

   Master只会把已经复制的offset后面的数据

   复制给Slave

6. 复制的缺点

复制延时,信号衰减

② master挂了,默认不会在slave中重选一个

    master,每次都需要人工干预,这时无人值

    守安装就变成了刚需

八、redis 哨兵(sentinel)

吹哨人巡查监控后台master主机是否故障,

如果故障了根据投票数自动将某一个从库

转换为新主库,继续对外服务

1. 作用:无人值守运维

    https://redis.io/docs/management/sentinel/

主从监控

    监控主从redis库是否正常

消息通知

    哨兵可以将故障转移的结果发送给客

    户端

故障转移

     如果master异常,则会进行主从切换,

     将其中一个slave作为新master

配置中心

     客户端通过连接哨兵来获得当前redis

     服务的主节点地址

2. 案例

(1) 3个哨兵,1主2从

3个哨兵:自动监控和维护集群,不存放数

                据,只是吹哨人

1主2从:用于数据读取和存放

(2) 步骤

   1) /myredis目录下新建或者拷贝sentinel.conf

       文件

   2) 先看看/opt目录下默认的sentinel.conf文件

       的内容

   3) 重点参数

bind        服务监听地址,用于客户端连接,

               默认本机地址

daemonize 是否以后台daemon方式运行

protected-mode 安全保护模式

port        端口

logfile     日志文件路径

pidfile      pid文件路径

dir           工作目录

sentinel monitor <master-name> <ip>

<redis-port> <quorum>

设置要监控的master服务器,quorum表示

最少有几个哨兵认可客观下线,同意故障

迁移的法定票数

sentinel auth-pass <master-name> <password>

master设置了密码,连接master服务的密码

   4) 哨兵sentinel文件通用配置

  ① 先启动一主二从 

 ② 再启动3个哨兵完成监控

 ③ 启动哨兵监控后再测试一次主从复制

 ④ 原有的master挂了

原有master6379挂了,两台从机数据OK,会

重新票选出新的master6381,之前down机的

master6379回来,新的master还是6381,夺

权成功,6379降级变成slave

   5) 对比配置文件

 ① vim sentinel26379.conf

    数据增多了

 ② 老master,vim redis6379.conf

 ③ 新master,vim redis6381.conf

 结论:

文件的内容,在运行期间会被sentinel动态

进行更改

Master-Slave切换后,master_redis.conf

和sentinel.conf的内容都会发生改变,即

master_redis.conf中会多一行slaveof的配

sentinel.conf目标会随之调换

    6) 其他备注

生产都是不同机房不同服务器,很少出现三

个哨兵全挂掉的情况,可以同时监控三个

master,一行一个

(3) 运行流程

当一个主从配置中的master失效之后,sentinel

可以是选举出一个新的master,用于自动接替原

master的工作,主从配置中的其他redis服务器自

动指向新的master同步数据

一般建议sentinel采取奇数台,防止某一台sentinel

无法连接到master导致误切换   

运行流程,故障切换:

   1)三个哨兵监控一主二从,正常运行中

   2) SDown主观下载(Subjectively Down)

SDown(主观不可用)是单个sentinel自己主观上检测

到的关于master的状态,从sentinel的角度来看,如

果发送了PING心跳后,在一定时间内没有收到合法

的回复,就达到了SDown的条件

sentinel配置文件中的down-after-milliseconds设置了

判断主观下线的时间长度

   3) ODown客观下载(Objectively Down)

ODown需要一定数量的sentinel,多个哨兵达成一致

意见才能认为一个master客观上已经宕掉

   4) 选举出领导者哨兵(哨兵中选出兵王)

当主节点被判断客观下线以后,各个哨兵节点会进行

协商,选举出一个领导者的哨兵节点(兵王),并由该

领导者节点,也即被选举出的兵王进行failover(故障迁移)

三哨兵日志文件两次2次解读分析

兵王由Raft算法选出来的

   5) 由兵王开始推动故障切换流程并选出

      一个新的master

    ① 新主登基

       某个Slave被选中成为新Master

   ② 群臣俯首

       一朝天子一朝臣,换个码头重新拜

   ③ 旧主拜服

       老master回来也认怂

(4) 使用建议

① 哨兵节点的数量应为多个,哨兵本身应该

    集群,保证高可用

② 哨兵节点的数量应该是奇数

③ 各个哨兵节点的配置应一致

④ 如果哨兵节点部署在Docker等容器里面,

     尤其要注意端口的正确映射

⑤ 哨兵集群+主从复制,并不能保证数据零

     丢失

九、redis 集群(cluster)

由于数据量过大,单个Master复制集难以承担,

因此需要对多个复制集进行集群,形成水平扩

展每个复制集只负责存储整个数据集的一部分,

这就是redis的集群

1. 作用:

1) 提供在多个redis节点间共享数据的程序集

2) 可以支持多个Master,每个Master又可以挂载

    多个Slave

   ① 读写分离

   ② 支持数据的高可用

   ③ 支持海量数据的读写存储操作

    https://redis.io/docs/reference/cluster-spec/

3) 由于Cluster自带Sentinel的故障转移机制,内

   置了高可用的支持,无需再去使用哨兵功能

4) 客户端与Redis的节点连接,不再需要连接集

   群中的所有的节点,只需要任意连接集群中的

   一个可用节点即可

5) 槽位slot负责分配到各个物理服务节点,由对

   应的集群来负责维护节点、插槽和数据之间的

   关系

2. 集群算法-分片-槽位slot

(1) slot槽位映射的三种解决方案:

   1) 哈希取余分区

   2) 一致性哈希算法分区

解决分布式缓存数据变动和映射问题,某个

机器宕机了,分母数量改变了,自然取余数

不OK了

作用:

提出一致性Hash解决方案

目的是当服务器个数发生变动时,尽量减少

影响客户端到服务器的映射关系

三大步骤:

① 算法构建一致性哈希环

② 服务器IP节点映射

③ key落到服务器的落键规则

 优点:

① 容错性

② 扩展性

 缺点:

   数据倾斜

 

   3) 哈希槽分区

哈希槽实质就是一个数组,数组 [0,2^14-1] 形成

hash slot 空间

作用:

解决均匀分配的问题,在数据和节点之间又加入

了一层,把这层称为哈希槽(slot),用于管理数据

和节点之间的关系,现在就相当于节点上放的是

槽,槽里放的是数据

槽解决的是粒度问题,粒度放大了,便于数据移

,哈希解决的是映射问题,使用key的哈希值来

计算所有的槽,便于数据分配

(2) redis集群的最大槽数为什么是16384(2^14)?

 ① 如果槽位为65536(2^16),发送心跳信息的消

     息头达8K,发送的心跳包过于庞大

 ② redis的集群主节点数量基本不可能超过1000个

 ③ 槽位越小,节点少的情况下,压缩比高,容易

     传输

 (3) Redis集群不保证强一致性,这意味着在特定的条

     件下,Redis集群可能会丢掉一些被系统收到的写入

     请求命令

3. 案例

(1) 3主3从redis集群配置

    1) 三台虚拟机各自新建:mkdir -p myredis/cluster

    2) 新建6个独立的redis服务:

IP:192.168.111.175+端口6381/6382

vim /myredis/cluster/redisCluster6381.conf

IP:192.168.111.172+端口6383/6384

IP:192.168.111.174+端口6385/6386

启动 6台redis主机

redis-server /myredis/cluster/redisCluster6381.conf

   3) 通过redis-cli命令为6台机器构建集群关系

      构建主从关系命令

    4) 链接进入6381作为切入点,查看并验证集群状态

info replication

cluster info

cluster nodes

(2) 3主3从redis集群读写

    ① 对6381新增两个key,报错,需要路由到位

    ② 防止路由失效加参数-c并新增两个key

 

    ③ 查看集群信息

        cluster nodes

    ④ 查看某个key对应槽位值:

        CLUSTER KEYSLOT 键名称

(3) 主从容错切换迁移案例

   1) 容错切换迁移

    ① 主6381和从机切换,先停止主机6381

        主机停了,对应的真实从机上位

    ② 再次查看集群信息,本次6381主6384从

    ③ 停止主机6381,再次查看集群信息

        6384成功上位并正常使用

   ④ 即使6381原来的主机回来了,也不会上位,

        而是以从节点形式回归

   2) 集群不保证数据一致性100%OK,一定会有

       数据丢失情况

不保证强一致性意味着在特定条件下,Redis

集群可能会丢掉一些被系统收到的写入请求

命令

   3) 手动故障转移 or 节点从属调整

上面6381和6384主从对调,和原始设计图不一样,

重新登陆6381,CLUSTER FAILOVER

(4) 主从扩容案例

   1) 新建6387,6388两个服务实例配置文件+新建

       后启动

IP:192.168.111.174+端口6387/6388

vim /myredis/cluster/redisCluster6387.conf

  

   2) 启动87/88两个新的节点实例,此时它们都是

       master

redis-server /myredis/cluster/redisCluster6387.conf

   3) 将新增的6387几点(空槽号)作为master节点加

       入原集群

   4) 检查集群情况第一次

   5) 重新分派槽号(reshard)

   6) 检查集群情况第二次 

   7) 为主节点6387分配从节点6388

   8) 检查集群情况第三次

(5) 主从缩容案例

目的:6387和6388下线

1) 检查集群情况第一次,先获得从节点6388的

   节点ID

2) 从集群中将4号从节点6388删除

3) 将6387的槽点清空,重新分配,本例将清除

   来的槽号都给6381

4) 检查集群清空第二次

5) 将6387删除

6) 检查集群情况第三次6387/6388被彻底祛除

4. 集群常用操作命令和CRC6算法分析

(1) 不在同一个slot槽位下的多键操作支持不

     好,通识占位符登场

 

(2) Redis集群有16384个哈希槽,每个key通过

    CRC16校验后对16384取模来决定放置哪个

    槽,集群的每个节点负责一部分hash槽

(3) 常用符号

cluster-require-full-coverage

CLUSTER COUNTKEYSINSLOT 槽位数字编号

 1,表示该槽位被占用,0表示没被占用

CLUSTER KEYSLOT 键名称

该键应该存在哪个槽位

十、SpringBoot 集成 Redis

1. 本地Java连接Redis常见问题

① 请注释掉bind配置

② 保护模式设置为no

③ Linux系统的防火墙设置

④ redis服务器的IP地址和密码是否正确

⑤ 忘记写访问redis的服务端口号和auth密码

2. 集成 Jedis

Jedis Client是Redis官网推荐的一个面向Java

客户端,库文件实现了对各类API进行封装调用

① 建Module

Redis7_study

② 改POM

改完刷新一下

③ 写YML

④ 主启动

⑤ 业务类

 

 

 

3. 集成 lettuce

Lettuce是一个Redis的Java驱动包

线程安全

 ① 改POM

② 业务类

 

4. 集成 RedisTemplate(推荐使用)

(1) 连接单击

① 建Module

② 改POM

③ 写YML

④ 主启动

⑤ 业务类

配置类:RedisConfig、SwaggerConfig

service

controller

⑥ 测试

序列化问题,JDK序列化方式(默认)惹的祸

 

 

(2) 连接集群

1) 启动Redis集群6台实例

2) 第一次改写YML

3) 直接通过微服务访问redis集群

4) 问题

主备切换后,微服务客户端再次读写访问

故障现象:SpringBoot客户端没有动态感知到

                  RedisCluster的最新集群信息

导致原因:SpringBoot2.x版本,Redis默认的

                  连接池是Lettuce,当Redis集群节

                  点发生变化后,Lettuce默认是不会

                  刷新节点拓扑

解决方案:刷新节点集群拓扑动态感应

 

 第二次改写YML:

​​​​​​​

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值