启动的时候,就通过配置文件来启动!
# include .\path\to\local.conf
# include c:\path\to\other.conf
bind 192.168.1.100 10.0.0.1
bind 127.0.0.1 #绑定的ip
#protected-mode yes #保护模式
port 6379 #端口设置
daemonize yes # 以守护进程的方式运行,默认是no ,我们要开启为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 #是否总是显示LOGO
持久化,在规定的时间内,执行了多少次操作,则会持久化到文件 .rdb.aof
redis是内存数据库,如果没有持久化,那么数据断点及失
#如果900s内,至少有一个key进行了修改,我们就进行持久化操作
save 900 1
#如果300s内,至少有10个key进行了修改,我们就进行持久化操作
save 300 10
#如果60s内,至少有10000个key进行了修改,我们就进行持久化操作
save 60 10000
#我们之后学习持久化,会自己定义这个测试
stop-writes-on-bgsave-error yes #持久化如果出错,是否还需要继续工作!
rdbcompression yes #是否压缩 rdb文件,需要消耗一些cpu资源!
rdbchecksum yes #保存rdb文件的时候,进行错误的检查校验
dir ./ # rdb文件保存的目录
通过配置文件
# requirepass foobared 需要密码的话把注释去掉再把密码加上即可
通过命令行设置密码
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" #设置redis密码
OK
127.0.0.1:6379> config get requirepass #设置密码后所有的命令都没有权限了需要登录
(error) NOAUTH Authentication required.
127.0.0.1:6379> ping
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth 123456 #auth 验证密码
OK
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) "123456"
# maxclients 10000 设置能连接上redis的最大客户端的数量
# maxmemory redis 配置最大的内存容量
# maxmemory-policy noeviction 内存到达上限之后的处理策略
移除一些过期的key
报错
...
appendonly no #默认是不开启aof模式的,默认是使用rdb方式持久化的,在大部分的情况下,rdb完全够用
appendfilename "appendonly.aof" #持久化的文件的名字
# appendfsync always 每次修改都会sync ,消耗性能
appendfsync everysec #每秒执行一次sync ,可能会丢失这1s的数据
# appendfsync no 不执行sync ,这个时候操作系统自己同步数据,速度最快
Redis是内存数据库,如果不将内存中的数据库状态保存到磁盘,那么一旦服务器进程退出,服务器中的数据库状态也会消失。所以redis提供了持久化功能!
有时候在生产环境我们会将这个文件进行备份!
rdb保存的文件是 dump.rdb 都是在我们的配置文件中快照进行配置的!
# save "" 在这些规则下快照,会自动生成一个dump.rdb文件
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
关机后依旧存在
127.0.0.1:6379> config get dir
1) "dir"
2) "D:\\JavaEnvironment\\redis" # 把rdb文件放在D:\\JavaEnvironment\\redis即可,在这个目录下存在dump.rdb文件,启动就会自动恢复其中的数据
优点:
缺点:
appendonly no #默认是不开启的,需要手动开启改为yes
# The name of the append only file (default: "appendonly.aof")
appendfilename "appendonly.aof" #生成的文件名字
# appendfsync always 每次都同步
appendfsync everysec #每一秒钟
# appendfsync no #不同步
no-appendfsync-on-rewrite no #重写规则
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb #如果aof文件大于64m,太大了,就会fork一个新的进程来将我们的文件进行重写
#重写规则说明:aof默认就是文件的无限追加,文件会越来越大
默认是不开启的,我们需要手动进行配置!我们只需要将appendonly改为yes就开启了aof。重启redis就会生效了
如果这个aof文件有错误,这时候redis是启动不起来的,我们需要修复这个aof文件,redis给我们提供了这样一个工具 redis-check-aof --fix
如果文件正常,重启就可以直接恢复了
优点:
缺点:
127.0.0.1:6379> subscribe kuangshenshuo
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "kuangshenshuo"
3) (integer) 1
#订阅后,只要那边发布了,这边都会接收到
如果是稍微复杂的场景我们就会使用 消息中间件 MQ
高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> info replication
# Replication
role:master #角色 master
connected_slaves:0 #没有从机
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
复制3个配置文件,然后修改对应的信息
修改完毕后,启动我们的3个redis服务器,可以通过进程信息查看。
默认情况下,每台Redis服务器都是主节点
我们一般情况下只用配置从机就好了!
slaveof 127.0.0.1 6379 #认6379当老大。自己变成了从机
# SLAVEOF host 6379 找谁当自己的老大!
真实的主从配置应该在配置文件中配置,这样的话是永久的,我们这里使用的是命令,只是暂时的。
# slaveof
# masterauth 如果主机有密码,就把密码也配上
主机可以写,从机不能写只能读!主机中的所有信息和数据,都会自动被从机保存!
从机只能读取内容,如果要写命令,就会报错。
测试:主机断开连接,从机依旧连接到主机的,但是没有写操作,这个时候,主机如果回来了,从机依旧可以直接获取到主机写的信息。
假如从机断开连接,如果是命令行修改的主从,那么重启后就又变成主机了。只要一变为从机,就会立马从主机中获得信息。
Slave启动成功连接到master后会发送一个sync命令
Master接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,并完成一次完全同步。
全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。
增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步。
但是只要重新连接master,一次完全同步(全量复制)将被自动执行!我们的数据一定可以在从机中看到
上一个M链接下一个S!这时候也可以完成我们的主从复制
宕机后手动配置主机
“自动选老大的模式”
主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费时费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。Redis 从2.8开始正式提供了Sentinel (哨兵)架构来解决这个问题。
谋朝篡位的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
这里的哨兵有两个作用:
然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
我们目前的状态是一主二从
# sentinel monitor 被监控的名称 host port 1
sentinel monitor myredis 127.0.0.1 6379 1
后面的这个数字1,代表主机挂了,salve让从机投票看让谁接替成为主机,票数最多的就会成为主机!
# redis-sentinel kconfig/sentinel.conf
如果Master节点断开了,这个时候就会从从机中随机选择一个服务器!(这里面有一个投票算法)。如果主机此时回来了,只能归并到新的主机下,当做从机,这就是哨兵模式的规则
优点:
缺点:
面试高频,工作常用
缓存穿透的概念很简单,用户想要查询一个数据,发现redis内存数据库没有,也就是缓存中没有,于是向持久层数据库查询。发现数据库中也没有,于是本次查询失败。当用户很多时,都查这个查询,缓存都没有命中(秒杀场景),于是都去请求了持久层数据库,这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
(简而言之,就是上万条请求一个没有缓存命中的请求,于是都是查询持久层数据库,给持久层数据库造成巨大压力,即缓存穿透)
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行检验,不符合则丢弃,从而避免了对底层存储系统的查询压力。
当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源。(即便返回空对象也缓存起来,这样后续同样的请求就会走缓存,而不是直接对数据库持久层造成压力)
但是这个方法会存在两个问题:
1)如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键;
2)即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。
缓存击穿是指,一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导致数据库瞬间压力过大。
eg:微博热搜服务器宕机(瞬间很多人请求一个东西)
从缓存层面来看,没有设置过时间,所以不会出现热点key过期后产生的问题
分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。
缓存雪崩,是指在某一个时间段,缓存集中过期失效。Redis宕机!
产生雪崩的原因之一,比如马上到双十一零点,很快会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时,那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰,于是所有的请求都会到达存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。
其实集中过期,倒不是非常致命,比较致命的缓存雪崩,是缓存服务器某个节点宕机或断网。因为自然形成的缓存雪崩,一定是在某个时间段集中创建缓存,这个时候,数据库也是可以顶住压力的。无非就是对数据库产生周期性的压力而已。而缓存服务节点的宕机,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。
双十一:停掉一些服务(保证主要的服务可用)
这个思想的含义是,既然redis有可能会挂掉,那我多增设几台redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建的集群。 (异地多活!)
这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待
数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中,在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。