Redis(参阅狂神说视频,整理)
2021-07-09 09:40:54 18 举报
AI智能生成
redis基础入门
作者其他创作
大纲/内容
入门
概述
Redis(Remote Dictionary Server ),即远程字典服务
是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API
能做些什么
效率高,可以用于高速缓存
内存存储,持久化,内存中是断电即失,所以持久化很重要(A)F,RDB)
发布订阅系统
地图信息分析
计时器、计数器
特性
持久化
事务
集群
多样的数据类型
......
学习工具
Redis官网
Redis中文
Redis英文
安装
window安装
1、下载安装包
从github上查找redis下载
2、下载获得压缩包,解压到自己电脑目录下就可以
3、开启redis,运行服务server即可
4、使用redis客户端Client,连接redis(服务server不能关)
5、测试连接ping,返回‘PONG’就是成功
6、设置值set name value
官方推荐使用Linux部署
linux安装
1、下载安装包,直接从官网下载,首页‘Download it’,获得安装包
2、使用XShell连接服务器,使用Xftp将安装包上传
3、解压redis的安装包,放入/opt目录下
4、进入到redis文件中,可以看到redis.conf配置文件
5、使用前的操作
6、redis默认安装路径
/usr/local/bin
7、可以在bin路径下找到server、client,操作如同window一样
8、可将bin目录下文件redis.conf拷贝到当前目录下
9、redis默认不是后台启动的,修改配置文件
进入redis.conf中,将daemonize no 改成yes
10、启动redis 服务
redis-server kconfig/redis.conf
通过指定的配置文件启动服务
11、启动客户端
redis-cli -p 6379
12、测试如同window安装一样
13、查看redis进程是否存在
命令:ps -ef|grep redis
14、如何关闭redis服务呢?
命令:shutdown
测试性能
redis-benchmark是一个压力测试工具
进入usr/local/bin
简单测试
基础知识
默认使用16个数据库,默认使用第0个
可以使用select进行切换数据库
清除数据库
Redis是单线程的
redis是基于内存操作的,CPU不是redis性能瓶颈,Redis的瓶颈是根据机器的内存和网络带宽
redis为什么单线程还这么快?
误区
1、高性能的服务器一定是多线程
2、多线程(CPU上下文切换)一定比单线程效率高
核心
1、redis是将所有数据放入内存中的,所以使用单线程操作效率就是最高的
2、多线程(CPU上下文切换:耗时操作),对于内存来讲,如果没有上下文切换效率是最高的
3、多次读写都在一个CPU上操作的,在内存情况下,单线程就是最佳方案
Redis是C语言写的,官方提供的数据QPS为100000+,完全不必同样是使用key-value的Memecache差
五大基础类型
Rerdis-key
命令操作
String(字符串)
APPEND 拼接
STRLEN 字符串长度
INCR 自增
DECR 自减
INCRBY 设置步长,指定增量
DECRBY
GETRANGE 范围,截取字符串
GETRANGE key 0 2
SETRANGE 替换指定位置的字符串
setex (set with expire) 设置过期时间
setex key 30 xxx(30->指时间)
setnx (set if not exist) 不存在再设置
setnx key xxx(若存在key,则将xxx设置进去,若不存在,则不会设置)
mset 批量设置
mset k1 v1 k2 v2 k3 v3
mget 批量获得
mget k1 k2 k3
msetnx 批量判断是否存在
msetnx k1 v1 k4 v4
msetnx 是一个原子性的操作,要么一起成功,要么一起失败
msetex 批量设置过期时间
实战使用 set key:{id}:{filed}
getset 先get再set
getset key value 如果不存在值则返回null,再设置新值;若存在,返回原来的值,并设置新指
String类型使用场景:vlaue除了是字符串还可以是数字
计数器
统计多单位的数量
List(列表)
详情
在redis里面,我们可以把list完成 栈、队列、阻塞队列
所有list命令都是用L开头的
Redis不区分大小写命令
LPUSH 插入到第一个元素
LPUSH 将一个值或者多个值,插入到列表的头部(左-left)
LPUSH list one
RPUSH 将一个值或者多个值,插入到列表的尾部(右-right)
RPUSH list one
LRANGE 获取范围内的值
LRANGE list 0 1 通过区间获取具体的值
LRANGE list 0 -1 查看列表中的值
LPOP 移除第一个元素
LPOP list 左边的值移除,移除list的第一个元素
RPOP list 右边的值移除,移除list的最后一个元素
Lindex 通过下标获得 list 中的某一个值
Lindex list 1
Llen 获得list的长度
Lrem 移除固定的值
Lrem list 1(表示个数) one(表示对应的值) 移除list集合中指定个数的value,精确匹配
Ltrim 通过下标截取指定的长度
Ltrim list 1 2 通过下标截取指定的长度,list改变,只剩下截取的元素
rpopLpush 移除列表最后一个元素,并且移动到新列表
rpoplpush source destination
rpoplpush list list2
Lset 将列表中指定下标的值替换成另一个值,更新操作
Linsert 将某个具体的value插入到别表中某个元素的前面或者后面
Linsert list before/after value value1 往list中value的位置before或after插入value1
小结
list 实际上是一个链表,before node after,left,right都可以插入
如果key不存在,创建新的链表
如果key存在,新增内容
如果移除所有的值,形成空链表,也代表不存在
在两边插入或者改动值,效率最高!中间元素,相对来说效率较低写
类似 消息队列
Lpush Rpop 左近右出
类似 栈
Lpush Lpop 先进先出
Set(集合)
set的命令以s开头,set中的值不能重复,类似java里的方法;
sadd set集合中添加元素
sadd myset value
SMEMBERS 查看指定set中所有的值
SMEMBERS set
SISMEMBER 判断某个值是否存在set集合中
SISMEMEBER myset value
scard 获取set集合中的内容元素个数
scard myset
srem 移除set集合中指定的值
srem myset value
srandmember 随机抽选出set集合中元素
srandmember myset 随机抽选出set中一个元素
srandmember myset 2 随机抽选出指定个数的元素
spop 随机移除set集合中的元素
smove 将一个指定的值,移动到另外一个set集合
smove myset myset2 value 将指定value从myset移动到myset2中
集合
差集 SDIFF
SDIFF key1 key2
交集 SINTER
SINTER key1 key2
并集 SUNION
SUNION key1 key2
Hash(哈希)
Map集合,key-value键值对,和string的差不多,只不过命令开头用h开头
hset 单个设置值
hset myhash key1 value1
hmset 多个设置值 hmset myhash k1 v1 k2 v2
hget
hget myhash key
hmget myhash key1 key2 获取多个值
hgetall 获取所有值
hgetall myhash
hdel 删除hash指定的key,对应的value也被删除
hdel myhash k1
hlen 获取hash的size
hlen myhash
hexists 判断hash中指定key是否存在
hexsits myhash key
hkeys 获取hash所有key
hkeys myhash
hvals 获取hash所有值
hvals myhash
hincr 指定增量
hincr
hincrby
hdecr 自减
hdecr
hdecrby
hsetnx 如果不存在则设置,如果不存在者不设置
hsetnx myhash key value
hash变更的数据 user name age ,尤其是用户信息子类的,经常变动的信息!hash 更适合对象的存储,String更加适合字符串存储
Zset(有序集合)
在set的基础上增加了一个值,zset k1 score v1,score排序;不会重复
zadd
zadd myset k1 v1
排序如何实现
升序
ZrangeByScore myset -inf +inf 显示全部用户,从小到大
-inf 负无穷 +inf 正无穷
zrangebyscore myset min max withscores
ZrangeByScore myset -1 0 withscores
可以排序
降序
zrevrange
zrevrange myset max min
降序
zrem
zrem myset key
zrange
zcard 获取有序集合的个数
zcount
zcount myset 0 3 获取指定区间的数量
三种特殊数据类型
geospatial 地理位置
geo这个功能可以推算出地理位置的信息,两地之间的举例
有效的经度从-180度到180度。
有效的纬度从-85.05112878度到85.05112878度。
有效的纬度从-85.05112878度到85.05112878度。
GEO底层是zset命令,可以使用zset的命令操作geo
六个命令
GEOADD 添加地理位置
GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
GEOADD china:city px py name
添加到sorted set元素的数目,但不包括已更新score的元素。
GEODIST 两个城市之间的距离
GEODIST Sicily Palermo Catania 默认单位m
GEODIST Sicily Palermo Catania km
指定单位的参数 unit 必须是以下单位的其中一个:
m 表示单位为米。
km 表示单位为千米。
mi 表示单位为英里。
ft 表示单位为英尺。
m 表示单位为米。
km 表示单位为千米。
mi 表示单位为英里。
ft 表示单位为英尺。
计算出的距离会以双精度浮点数的形式被返回。 如果给定的位置元素不存在, 那么命令返回空值。
GEOHASH 返回一个或多个位置元素的 Geohash 表示
GEOHASH Sicily Palermo Catania
一个数组, 数组的每个项都是一个 geohash 。 命令返回的 geohash 的位置与用户给定的位置元素的位置一一对应。
该命令将返回11个字符的Geohash字符串,所以没有精度Geohash,损失相比,使用内部52位表示。返回的geohashes具有以下特性:
他们可以缩短从右边的字符。它将失去精度,但仍将指向同一地区。
它可以在 geohash.org 网站使用,网址 http://geohash.org/<geohash-string>。查询例子:http://geohash.org/sqdtr74hyu0.
与类似的前缀字符串是附近,但相反的是不正确的,这是可能的,用不同的前缀字符串附近。
返回值
一个数组, 数组的每个项都是一个 geohash 。 命令返回的 geohash 的位置与用户给定的位置元素的位置一一对应。
他们可以缩短从右边的字符。它将失去精度,但仍将指向同一地区。
它可以在 geohash.org 网站使用,网址 http://geohash.org/<geohash-string>。查询例子:http://geohash.org/sqdtr74hyu0.
与类似的前缀字符串是附近,但相反的是不正确的,这是可能的,用不同的前缀字符串附近。
返回值
一个数组, 数组的每个项都是一个 geohash 。 命令返回的 geohash 的位置与用户给定的位置元素的位置一一对应。
GEOPOS 获取指定城市的经纬度
GEOPOS Sicily Palermo Catania NonExisting
GEOPOS 命令返回一个数组, 数组中的每个项都由两个元素组成: 第一个元素为给定位置元素的经度, 而第二个元素则为给定位置元素的纬度。
当给定的位置元素不存在时, 对应的数组项为空值。
当给定的位置元素不存在时, 对应的数组项为空值。
GEORADIUS 以给定的经纬度为中心, 找出某一半径内的元素
GEORADIUS Sicily 15 37 100 km
范围可以使用以下其中一个单位:
m 表示单位为米。
km 表示单位为千米。
mi 表示单位为英里。
ft 表示单位为英尺。
m 表示单位为米。
km 表示单位为千米。
mi 表示单位为英里。
ft 表示单位为英尺。
withdist 显示到中间距离的位置
withcoord 显示他人的定位信息
GEORADIUS china:city 100 30 500 km withdis withcoord count 1 以100,30这个经纬度为中心,寻找方圆500km内的城市
可以搜索半径之内的所有城市
在没有给定任何 WITH 选项的情况下, 命令只会返回一个像 [“New York”,”Milan”,”Paris”] 这样的线性(linear)列表。
在指定了 WITHCOORD 、 WITHDIST 、 WITHHASH 等选项的情况下, 命令返回一个二层嵌套数组, 内层的每个子数组就表示一个元素。
在返回嵌套数组时, 子数组的第一个元素总是位置元素的名字。 至于额外的信息, 则会作为子数组的后续元素, 按照以下顺序被返回:
以浮点数格式返回的中心与位置元素之间的距离, 单位与用户指定范围时的单位一致。
geohash 整数。
由两个元素组成的坐标,分别为经度和纬度。
举个例子, GEORADIUS Sicily 15 37 200 km WITHCOORD WITHDIST 这样的命令返回的每个子数组都是类似以下格式的:
["Palermo","190.4424",["13.361389338970184","38.115556395496299"]]
在指定了 WITHCOORD 、 WITHDIST 、 WITHHASH 等选项的情况下, 命令返回一个二层嵌套数组, 内层的每个子数组就表示一个元素。
在返回嵌套数组时, 子数组的第一个元素总是位置元素的名字。 至于额外的信息, 则会作为子数组的后续元素, 按照以下顺序被返回:
以浮点数格式返回的中心与位置元素之间的距离, 单位与用户指定范围时的单位一致。
geohash 整数。
由两个元素组成的坐标,分别为经度和纬度。
举个例子, GEORADIUS Sicily 15 37 200 km WITHCOORD WITHDIST 这样的命令返回的每个子数组都是类似以下格式的:
["Palermo","190.4424",["13.361389338970184","38.115556395496299"]]
GEORADIUSBYMEMBER 找出位于指定范围内的元素,中心点是由给定的位置元素决定
GEORADIUSBYMEMBER Sicily Agrigento 100 km
找出位于指定元素周围的其他元素
子主题
hyperloglog
用于基数统计的算法
优点:占用的内存是固定的,2^64不同的元素的技术,只需要费12kb内存!如果要从内存角度比较的化,Hyperloglog首选!
Pfadd
命令将所有元素参数添加到 HyperLogLog 数据结构中
PFADD key element [element ...] 返回值:整型,如果至少有个元素被添加返回 1, 否则返回 0。
redis 127.0.0.1:6379> PFADD mykey a b c d e f g h i j
(integer) 1
redis 127.0.0.1:6379> PFCOUNT mykey
(integer) 10
(integer) 1
redis 127.0.0.1:6379> PFCOUNT mykey
(integer) 10
Pfcount
命令返回给定 HyperLogLog 的基数估算值。
PFCOUNT key [key ...] 返回值:整数,返回给定 HyperLogLog 的基数值,如果多个 HyperLogLog 则返回基数估值之和。
redis 127.0.0.1:6379> PFADD hll foo bar zap
(integer) 1
redis 127.0.0.1:6379> PFADD hll zap zap zap
(integer) 0
redis 127.0.0.1:6379> PFADD hll foo bar
(integer) 0
redis 127.0.0.1:6379> PFCOUNT hll
(integer) 3
redis 127.0.0.1:6379> PFADD some-other-hll 1 2 3
(integer) 1
redis 127.0.0.1:6379> PFCOUNT hll some-other-hll
(integer) 6
redis>
(integer) 1
redis 127.0.0.1:6379> PFADD hll zap zap zap
(integer) 0
redis 127.0.0.1:6379> PFADD hll foo bar
(integer) 0
redis 127.0.0.1:6379> PFCOUNT hll
(integer) 3
redis 127.0.0.1:6379> PFADD some-other-hll 1 2 3
(integer) 1
redis 127.0.0.1:6379> PFCOUNT hll some-other-hll
(integer) 6
redis>
Pfmerge(并集)
命令将多个 HyperLogLog 合并为一个 HyperLogLog ,合并后的 HyperLogLog 的基数估算值是通过对所有 给定 HyperLogLog 进行并集计算得出的
PFMERGE destkey sourcekey [sourcekey ...]
redis 127.0.0.1:6379> PFADD hll1 foo bar zap a
(integer) 1
redis 127.0.0.1:6379> PFADD hll2 a b c foo
(integer) 1
redis 127.0.0.1:6379> PFMERGE hll3 hll1 hll2
OK
redis 127.0.0.1:6379> PFCOUNT hll3
(integer) 6
redis>
(integer) 1
redis 127.0.0.1:6379> PFADD hll2 a b c foo
(integer) 1
redis 127.0.0.1:6379> PFMERGE hll3 hll1 hll2
OK
redis 127.0.0.1:6379> PFCOUNT hll3
(integer) 6
redis>
bitmaps
bit位,位存储
位图,数据结构,操作二进制位进行记录,只有0和1两个状态
setbit
setbit sign 0 0
使用bitmaps记录一周七天,打卡上班的例子
周1:1 周二:0 周三:0......
周1:1 周二:0 周三:0......
getbit
getbit sign 3
bitcount sign 统计数量
事务
Redis事务本质:一组命令的集合!
一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行
一次性、顺序性、排他性
一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行
一次性、顺序性、排他性
没有隔离级别的概念
所有命令在事务中,并没有直接执行!只有发起执行命令的时候才会执行!Exec
Redis单条命令是保证原子性,但是事务不保证原子性
redis事务命令
开启事务(multi)
开启事务
discard 放弃事务
事务队列中命令都不会被执行
命令入队(......)
执行事务(exec)
监控 Watch
乐观锁
悲观锁
redis监视成功
watch xx
获取最新的值version,监视,select version 获取版本
unwatch xx
如果事务执行失败,就先解锁
子主题
Jedis
什么是Jedis
是redis官方推荐的java连接开发工具!使用java操作redis中间件!
如果要使用java操作redis,那么一定要对Jedis十分熟悉
如果要使用java操作redis,那么一定要对Jedis十分熟悉
项目使用
导入jedis依赖包
导入fastjson依赖包,阿里巴巴的
编码测试
连接数据库
Jedis jedis = new Jedis(ip,port);
jedis就可以使用所有指令方法
操作命令
基础
断开连接
常用API
String
List
Set
Hash
Zset
springBoot整合
注意
springboot 2.x之后默认使用lettuce,若使用jedis配置,因为源码中许多类没有注入,类不存在,因此别使用jedis,有可能导致配置不成功
jedis 不安全,需要使用 pool 池化,像BIO
lettuce 安全,像NIO,现在比较常用
使用
redisTemlpate.opsForXXX() opsFor->operation for 操作
除了基本的操作,常用的方法也可以直接使用 redisTemplate 操作,比如事务
获取连接 redisTemplate.getConnectionFactory().getConnection()
connection.flushDB()
connection.flushAll()
序列化
序列化配置,JDK序列化
开发中需要序列化,否则存入后取值会报错
序列化方式
实现Serialized接口
对应的实现的序列化
使用最好自己封装好工具包util
自己开发方便,一般直接使用String
定义后,可以使用@Qualifer("reidsTemplate")
Redis.conf详解
进入方式
进入服务器找到redis安装的目录,找到redis.conf 文件进行配置
1、配置文件unit单位 对大小写不敏感
单位
网络
bind 127.0.0.1 # 绑定的ip
protected-mode yes # 保护模式
port 6379 # 端口设置
通用General
daeminize yes # 以守护进程的方式运行,默认是no,我们需要自己开启为yes
pidfile /var/run/redis_6379.pid # 如果以后台的方式运行,我们就需要指定一个 pid
日志 loglevel notice 四个层级
logfile "" # 日志的文件位置名
databases 16 #数据库的数量,默认是 16 个数据库
always-show-log yes # 是否总是显示log,默认为yes
快照
持久化,在规定的时间内,执行了多少次操作,则会持久化到文件.rdb .aof
redis是内存数据库,如果没有持久化,那么断电数据既失
# 如果 900s 内,如果至少有一个1 key进行了修改,我们及进行持久化操作
save 900 1
# 如果 300s 内,如果至少有一个10 key进行了修改,就会进行持久化
save 300 10
# 如果 60s 内,如果至少有一个10000 key进行了修改,就会进行持久化
save 60 10000
save 900 1
# 如果 300s 内,如果至少有一个10 key进行了修改,就会进行持久化
save 300 10
# 如果 60s 内,如果至少有一个10000 key进行了修改,就会进行持久化
save 60 10000
stop-writes-on-bgsave-error yes # 持久化如果出错,是否还需要继续工作
rdbcompression yes #是否压缩redb文件,需要消耗一些cpu资源
rdbchecksum yes # 保存rdb文件的时候,进行错误的检查校验
dir ./ # rdb文件保存的目录
SECURIT 安全
设置密码,这是通过在配置文件中设置的
命令设置密码
config get requirepass
config set requirepass "123456"(password)
auth加权限
config get requirepass
config set requirepass "123456"(password)
auth加权限
CLIENTS 限制
maxclients 10000 # 设置能连接上的redis的最大客户端数量
maxmemory <bytes> # redis 配置最大的内存容量
maxmemory-policy noeviction #内存到达上限后的处理策略
处理策略
APPEND Only模式 aof配置
appendonly on # 默认是不开启aof模式的,默认是使用rdb方式持久化的,大部分所有的情况下,rdb够用了
appendfilename “appendonly.aof” 持久化文件的名字
基本配置
Redis持久化
RDB(Redis DataBase)
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话说的snapshot快照,恢复时是将快照文件直接读到内存里
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化的文件。
整个过程中,主进程时不进行任何IO操作的。
确保了极高的性能。
如果需要大规模数据的恢复,且对数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。
RDB的缺点就是最后一次持久化的数据可能丢失
整个过程中,主进程时不进行任何IO操作的。
确保了极高的性能。
如果需要大规模数据的恢复,且对数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。
RDB的缺点就是最后一次持久化的数据可能丢失
步骤:
1、操作redis时,创建fork子进程进行持久化
2、将内存内容以快照的形式写入临时RDB文件中(rdb保存的文件是dump.rdb)
3、快照写入完成后,替换原来的快照rdb文件
4、子进程退出
1、操作redis时,创建fork子进程进行持久化
2、将内存内容以快照的形式写入临时RDB文件中(rdb保存的文件是dump.rdb)
3、快照写入完成后,替换原来的快照rdb文件
4、子进程退出
rdb的dump.rdb文件触发规则:
1、save的规则满足的情况下,会自动触发rdb规则
2、执行flushall命令,也会触发我们的rdb规则
3、退出redis,也会产生rdb文件
备份就会自动生成一个dump.rdb文件
1、save的规则满足的情况下,会自动触发rdb规则
2、执行flushall命令,也会触发我们的rdb规则
3、退出redis,也会产生rdb文件
备份就会自动生成一个dump.rdb文件
如何恢复rdb文件?
1、只需要将rdb文件放到redis启动目录就可以,redis启动的时候会自动检查dump.rdb恢复数据
2、查看需要存在的位置
config get dir 就能直到对应的redis启动目录
1、只需要将rdb文件放到redis启动目录就可以,redis启动的时候会自动检查dump.rdb恢复数据
2、查看需要存在的位置
config get dir 就能直到对应的redis启动目录
优点:
1、适合大规模的数据恢复
2、如果对数据的完整性要求不高!因为rdb这边有一个配置save 900 10类型的配置,有一个最低要求,如果再这期间宕机,就不会生成文件,导致文件丢失
3、父进程无须执行任何磁盘的IO操作,因此恢复数据比AOF快
1、适合大规模的数据恢复
2、如果对数据的完整性要求不高!因为rdb这边有一个配置save 900 10类型的配置,有一个最低要求,如果再这期间宕机,就不会生成文件,导致文件丢失
3、父进程无须执行任何磁盘的IO操作,因此恢复数据比AOF快
缺点:
1、需要一定的时间间隔进程操作!如果redis意外宕机了,这个最后一次修改的数据就没有了
2、创建fork子进程的时候,也会占用一定的内容空间(只要是进程都会占用空间)
3、RDB文件时特定的格式,阅读性差,格式固定,可能存在不兼容的情况
1、需要一定的时间间隔进程操作!如果redis意外宕机了,这个最后一次修改的数据就没有了
2、创建fork子进程的时候,也会占用一定的内容空间(只要是进程都会占用空间)
3、RDB文件时特定的格式,阅读性差,格式固定,可能存在不兼容的情况
注意:一般在工作中,生产环境使用redis时,会将redis的rdb文件进行备份,以防止数据丢失
AOF(Append Only File)
将在redis操作的所有命令全部记录下来,以日志的形式,恢复的时候,将这些文件全部执行一遍!
以日志的形式记录每个写操作,将redis执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据
redis重启的化,就根据日志文件的内容将指令从头开始执行一遍,以完成数据恢复的工作
redis重启的化,就根据日志文件的内容将指令从头开始执行一遍,以完成数据恢复的工作
AOF保存的文件是appendonly.aof
默认是不开启AOF模式的,需要手动进行配置修改;
appendonly yes
其他的aof配置可以保持默认的,默认aof命令是无限追加的
触发机制:
当前aof文件的大小是上次rewrite后的两倍且大于64M
具体大小配置 :
auto-aof-rewrite-min-size 64mb 生产环境下要配置的比较大
auto-aof-rewrite-percentage: 100 增长的百分比
也可使用命令bgwriteaof
设置同步策略:
appendfsysnc: 保存操作记录的模式
always: 每次有数据修改时添加记录 性能差
everysecond:每秒记录一次 默认 最多丢失1s的数据即每秒把缓冲区的数据写入磁盘
no: 由OS决定何何时同步,linux通常是30s
appendonly yes
其他的aof配置可以保持默认的,默认aof命令是无限追加的
触发机制:
当前aof文件的大小是上次rewrite后的两倍且大于64M
具体大小配置 :
auto-aof-rewrite-min-size 64mb 生产环境下要配置的比较大
auto-aof-rewrite-percentage: 100 增长的百分比
也可使用命令bgwriteaof
设置同步策略:
appendfsysnc: 保存操作记录的模式
always: 每次有数据修改时添加记录 性能差
everysecond:每秒记录一次 默认 最多丢失1s的数据即每秒把缓冲区的数据写入磁盘
no: 由OS决定何何时同步,linux通常是30s
恢复数据,重启redis就可以生效了,不需要固定的位置保存
如果aof文件出现错误,这时候redis时启动不起来的,就需要修复aof文件
redis给我们提供一个工具:redis-check-aof --fix appendonly.aof
redis给我们提供一个工具:redis-check-aof --fix appendonly.aof
优点:
1、每一次修改都同步,文件的完整性更好
2、默认开启的策略是,每秒开启一次,可能会丢失一秒的数据
3、从不同步,效率最高的!
缺点:
1、相对于数据文件来说,aof远远大于rdb,修复的速度也比rdb慢
2、Aof运行效率也比rdb慢,因此redis默认的配置是rdb持久化
1、每一次修改都同步,文件的完整性更好
2、默认开启的策略是,每秒开启一次,可能会丢失一秒的数据
3、从不同步,效率最高的!
缺点:
1、相对于数据文件来说,aof远远大于rdb,修复的速度也比rdb慢
2、Aof运行效率也比rdb慢,因此redis默认的配置是rdb持久化
同时开启两种持久化机制
当AOF和RDB同时开启,优先读取aof文件(数据安全性)
缺点:同时开启,性能开销大,内存消耗更快,会同时生产rdb文件和aof文件
缺点:同时开启,性能开销大,内存消耗更快,会同时生产rdb文件和aof文件
redis先加载AOF文件来恢复原始数据,因为AOF数据比rdb更完整但是aof存在潜在的bug,如把错误的操作记录写入了aof,会导出数据恢复失败所以可以把RDB作为后备数据为了考虑性能,可以只在Slave上开启RDB,并且15min备份一次
如果为了避免AOF rewite的IO以及阻塞,可以在Redis集群中不开启AOF,靠集群的备份机制来保证可用性,在启动时选取较新的RDB文件如果集群全部崩溃,会丢失15min前的数据
如果为了避免AOF rewite的IO以及阻塞,可以在Redis集群中不开启AOF,靠集群的备份机制来保证可用性,在启动时选取较新的RDB文件如果集群全部崩溃,会丢失15min前的数据
子主题
混合模式
redis4.0开始支持该模式
为了解决的问题:
redis在重启时通常是加载AOF文件,但加载速度慢因为RDB数据不完整,所以加载AOF
开启方式:
aof-use-rdb-preamble true开启后,AOF在重写时会直接读取RDB中的内容
运行过程:
通过bgrwriteaof完成,不同的是当开启混合持久化后,
1 子进程会把内存中的数据以RDB的方式写入aof中,
2 把重写缓冲区中的增量命令以AOF方式写入到文件
3 将含有RDB个数和AOF格数的AOF数据覆盖旧的AOF文件新的AOF文件中,一部分数据来自RDB文件,一部分来自Redis运行过程时的增量数据
为了解决的问题:
redis在重启时通常是加载AOF文件,但加载速度慢因为RDB数据不完整,所以加载AOF
开启方式:
aof-use-rdb-preamble true开启后,AOF在重写时会直接读取RDB中的内容
运行过程:
通过bgrwriteaof完成,不同的是当开启混合持久化后,
1 子进程会把内存中的数据以RDB的方式写入aof中,
2 把重写缓冲区中的增量命令以AOF方式写入到文件
3 将含有RDB个数和AOF格数的AOF数据覆盖旧的AOF文件新的AOF文件中,一部分数据来自RDB文件,一部分来自Redis运行过程时的增量数据
数据恢复:
当我们开启了混合持久化时,启动redis依然优先加载aof文件,aof文件加载可能有两种情况如下:
aof文件开头是rdb的格式, 先加载 rdb内容再加载剩余的 aof。
aof文件开头不是rdb的格式,直接以aof格式加载整个文件。
优点:既能快速备份又能避免大量数据丢失
缺点:RDB是压缩格式,AOF在读取它时可读性教差
当我们开启了混合持久化时,启动redis依然优先加载aof文件,aof文件加载可能有两种情况如下:
aof文件开头是rdb的格式, 先加载 rdb内容再加载剩余的 aof。
aof文件开头不是rdb的格式,直接以aof格式加载整个文件。
优点:既能快速备份又能避免大量数据丢失
缺点:RDB是压缩格式,AOF在读取它时可读性教差
Redis发布订阅
什么是发布订阅?
Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接受消息
Redis客户端可以订阅任意数量的频道’
订阅/发布消息图
实现原理
子主题
命令
# 订阅一个或多个符合给定模式的频道
psubsribe pattern [pattern......]
# 查看订阅与发布系统状态
pubsub subcommand [argument [argument ...]]
# 将信息发送到指定的频道
publish channel message
# 退订所有给定模式的频道
punsubscribe [pattern......]
# 订阅给定的一个或者多个频道的信息
subscribe channel [channel ...]
# 指推定给定的频道
unsubscribe [channel [channel...]]
psubsribe pattern [pattern......]
# 查看订阅与发布系统状态
pubsub subcommand [argument [argument ...]]
# 将信息发送到指定的频道
publish channel message
# 退订所有给定模式的频道
punsubscribe [pattern......]
# 订阅给定的一个或者多个频道的信息
subscribe channel [channel ...]
# 指推定给定的频道
unsubscribe [channel [channel...]]
订阅/发送
场景:
1、实时消息系统!
2、实时聊天!(可以将频道当聊天室,将消息回显示给所有人即可!)
3、订阅、关注系统都是可以的!
1、实时消息系统!
2、实时聊天!(可以将频道当聊天室,将消息回显示给所有人即可!)
3、订阅、关注系统都是可以的!
Redis主从复制
了解
概念
是将一台redis服务器的数据,复制到其他的redis服务器
前者称为主节点(master/leader),后者称为从节点(slave/follower)
数据的复制都是单向的,只能由主节点到从节点
Master以写为主,Slave以读为主
主从复制,读写分离;读的操作都分给从机上,而写只需要写给主机,就能缓减服务器压力
主要作用
数据冗余
主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
故障恢复
当主节点出现问题时,可以 由从节点提供服务,实现快速的故障恢复;实际上时一种服务的冗余
负载均衡
在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,分担服务器负载
写redis数据时,应用连接主节点;读redis数据时,应用连接从节点
在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量
高可用基石
除了上诉的作用外,主从复制还是哨兵和集群能够实施的基础,因此主从复制时redis高可用的基础
注意事项
要用redis运用与工程中,只使用一台redis是万万不能的(因为会出现宕机问题,导致数据丢失,因此一般会准备3太,一主二从)
从结构上,单个redis服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大
从容量上,单个redis服务器内存容量有限,就算一台redis服务器内存容量为256G,也不能将所有内存用作与redis存储内存。一般来说,单个redis最大使用内存不应该超过20G
使用场景
电商网站上的商品,一般都是一次上传,无数次浏览
环境配置
只配置从库,不用配置主库
一般修改配置redis.conf
端口 port
pid 名字
log日志文件名字
dump.rdb文件名字
appendonlyfile.aof文件名字
默认情况下,每台redis服务器都是主节点
我们就需要配置从机就可以了,主机不用配置
集群命令,通过命令实现
SlaveOF host port
host:就是主库的ip
port:就是主库的端口
port就是从机需要跟随的老大
SlaveOF host port
host:就是主库的ip
port:就是主库的端口
port就是从机需要跟随的老大
也可以通过配置redis.conf里面配置
REPLICATION
REPLICATION
通过配置实现
细节
主机负责写,从机负责读
主机中所有的数据和命令,都会自动被从机保存
当主机断了,从机仍然运行连接主机,但是没有写操作,这个时候,如果主机回来了,从机依旧可以直接获取到主机写的信息
如果使用命令行,来配置的主从,这个时候如果重启,就会变成主机!主要变为从机,立马就会从主机中获取值
复制原理
Slave启动成功连接到master后会发送一个sync同步命令
Master 接受命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master 将传送整个数据文件到slave,并完成一次完成同步
全量复制
slave服务在接受到数据库文件数据后,将其存盘并加载到内存中
增量复制
Master 继续将新的所有收到的修改命令依次传给slave,完成同步
但只要重新连接master,一次完全同步(全量复制)将被自动执行!数据一定可以再从机上看到
全量和增量简易理解:
当主机服务器重启后,redis从机会将主机的命令及数据全部复制(全量),等后面再操作时,redis从机再一个一个将主机的命令和数据复制(增量)
当主机服务器重启后,redis从机会将主机的命令及数据全部复制(全量),等后面再操作时,redis从机再一个一个将主机的命令和数据复制(增量)
当一个B是A的从机,是C的主机,那么B还是从机,无法写入,但是还是可以完成主从复制
哨兵模式(自动选举老大,只要发现老大没了,就会选举新的老大)
以前:
当主机断了,从机可以通过命令手动变为主节点,slaveof no one,变为主节点;
但当这是主机又回来了,那就只能重新配置,重新连接
当主机断了,从机可以通过命令手动变为主节点,slaveof no one,变为主节点;
但当这是主机又回来了,那就只能重新配置,重新连接
哨兵模式是一种特殊的模式,首先redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,他会独立运行。
其原理就是哨兵通过发送命令,等待redis服务器相应,从而监控运行的多个redis实例
其原理就是哨兵通过发送命令,等待redis服务器相应,从而监控运行的多个redis实例
运行图例
作用
通过发送命令,让redis服务器返回监控其运行状态,包括主服务器和从服务器
当哨兵检测到master宕机,会自动将slave切换程master,然后通过发布订阅模式,通知其他的从服务器,修改配置文件,让他们切换主机
注意
一个哨兵进程对redis服务器进行监控,可能会出现问题,为此,可以使用多个哨兵及逆行监控,各个哨兵之间还会进行监控,这样就形成多哨兵的模式
1、配置哨兵配置文件:vim sentinel.conf
2、最核心的配置,和最基础的
sentinel monitor myredis 127.0.0.1 6379 1
# sentinel monitor 被监控的名字 host port 1
后面的数字1,代表主机挂了,slave投票看让谁接替称为主机,票数最对的,就会称为主机
3、启动哨兵
4、如果主机挂了,哨兵自动从从机中选择一个当主机,但当原主机回来了,只能当从机
2、最核心的配置,和最基础的
sentinel monitor myredis 127.0.0.1 6379 1
# sentinel monitor 被监控的名字 host port 1
后面的数字1,代表主机挂了,slave投票看让谁接替称为主机,票数最对的,就会称为主机
3、启动哨兵
4、如果主机挂了,哨兵自动从从机中选择一个当主机,但当原主机回来了,只能当从机
优点:
1、哨兵集群,基于主从复制模式,所有的主从配置优点,他全由
2、主从可以切换,故障可以转移,系统的可用性就会更好
3、哨兵模式就主从模式的升级,手动到自动
缺点:
1、redis不好在线扩容,集群容量一旦达到上限,在线扩容就特别麻烦
2、实现哨兵模式,配置很麻烦
1、哨兵集群,基于主从复制模式,所有的主从配置优点,他全由
2、主从可以切换,故障可以转移,系统的可用性就会更好
3、哨兵模式就主从模式的升级,手动到自动
缺点:
1、redis不好在线扩容,集群容量一旦达到上限,在线扩容就特别麻烦
2、实现哨兵模式,配置很麻烦
哨兵全部配置
第一部分
第二部分
第三部分
子主题
Redis缓存穿透、击穿和雪崩
缓存穿透
用户想要查一个数据,发现redis内存数据库没有(也就是缓存没有命中),于是向持久层数据库查询(类似mysql)。
发现持久层数据也没有,于是本次查询失败。
当用户很多的时候,缓存都没有命中(举例场景:秒杀活动),于是都去请求持久层数据库,最终持久层数据库带来压力,就相当于缓存穿透
发现持久层数据也没有,于是本次查询失败。
当用户很多的时候,缓存都没有命中(举例场景:秒杀活动),于是都去请求持久层数据库,最终持久层数据库带来压力,就相当于缓存穿透
解决方案
布隆过滤器
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免对底层存储系统的查询压力
缓存空对象
当存储层不命中,及时返回空对象也将其缓存起来,同时会设置一个过期时间,之后在访问这个数据将会从缓存中获取,保护了后端数据源
可能存在两个问题
1、如果控制能够被缓存,这就意味着缓存需要更多的空间存储来存储更多的键
2、及时对空值设置了过期时间,还是会存在缓存层和存储层的数据,会出现一段时间窗口不一致,这对保持一致性的业务有影响
出现场景:秒杀活动
缓存击穿
是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开一个洞。
当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般就是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导致数据库瞬间压力过大!
当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般就是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导致数据库瞬间压力过大!
解决方案
设置热点数据永不过期
从缓存层面来看,没有设置过期时间,所以不会出现热点key过期后产生的问题
存在问题:需要更多空间存储
加互斥锁
分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务器,其他线程没有获得分布式锁的权限,因此需要等待即可。
这种方式将高并发的压力转移到分布式锁,因此对分布式 锁的考验很大
这种方式将高并发的压力转移到分布式锁,因此对分布式 锁的考验很大
出现场景:微博热搜
缓存雪崩
是指在某一个时间段,缓存集体过期失效或者redis宕机
解决方案
redis高可用
既然redis可能挂掉,那么就多增设几台redis,这样一台挂了,其他还可以工作,其实就搭建的集群
限流降级
在缓存失效后,通过加锁或者队列来控制读数据数据库写缓存的线程数量,比如对某个key只允许一个线程查询数据和写数据,其他线程等待
先停掉一些服务,保证其他服务可用
数据预热
数据加热的含义:在正式部署之前,先把可能的数据选预先访问一边,这样部分可能大量访问的数据就会加载到缓存中。
在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀
在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀
出现场景:淘宝双十一抢购,假设商品集体缓存过期,导致缓存查不到,压力全部压到数据库上
集中过期倒不是最致命的,最终名的雪崩,是缓存服务器某个节点宕机或断网,自然形成的雪崩;
因为是缓存服务器节点宕机,对数据库造成压力是不可以预知的,谁也不知道下一秒是不是就会导致数据库压垮
因为是缓存服务器节点宕机,对数据库造成压力是不可以预知的,谁也不知道下一秒是不是就会导致数据库压垮
使用场景:双十一期间,为了保证高效,可能为关闭当天退款的功能,等第二天或者等其他时候可以退款
区别
缓存击穿和缓存穿透区别
击穿 -> 量大!key存在,但缓存过期!(热点)
穿透 -> key不存在
收藏
0 条评论
下一页