redis-benchmark
redis性能测试
以下参数被支持:
Usage: redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests]> [-k <boolean>]
-h <hostname> Server hostname (default 127.0.0.1)
-p <port> Server port (default 6379)
-s <socket> Server socket (overrides host and port)
-a <password> Password for Redis Auth
-c <clients> Number of parallel connections (default 50)
-n <requests> Total number of requests (default 100000)
-d <size> Data size of SET/GET value in bytes (default 2)
-dbnum <db> SELECT the specified db number (default 0)
-k <boolean> 1=keep alive 0=reconnect (default 1)
-r <keyspacelen> Use random keys for SET/GET/INCR, random values for SADD
Using this option the benchmark will expand the string __rand_int__
inside an argument with a 12 digits number in the specified range
from 0 to keyspacelen-1. The substitution changes every time a command
is executed. Default tests use this to hit random keys in the
specified range.
-P <numreq> Pipeline <numreq> requests. Default 1 (no pipeline).
-q Quiet. Just show query/sec values
--csv Output in CSV format
-l Loop. Run the tests forever
-t <tests> Only run the comma separated list of tests. The test
names are the same as the ones produced as output.
-I Idle mode. Just open N idle connections and wait.
Redis.conf
单位
- 配置文件对大小写不敏感
包含
网络
#绑定的IP
bind 127.0.0.1
#保护模式
protected-mode yes
#端口设置
prot 6379
通用
#以守护进程的方式运行,默认是NO,需要自己开启
daemonize yes
#如果是以后台的方试运行,我们就需要制定一个pid文件
pidfile /var/run/redis_6379.pid
#数据库的数量,默认是16个数据库
databse 16
#显示logo
always-show-logo yes
日志级别
# 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 ""
快照
- 持久化,在规定时间内执行了多少次操作则会持久化到文件(rdb.aof)
- redis是内存数据库,如果没有持久化,那么数据断电即失
#如果900s内至少有一个key修改了,我们就进行持久化
save 900 1
#如果在300s内至少有十个key进行了修改,我们就进行持久化操作
save 300 10
#如果60s内有10000个key值进行了修改,我们就进行持久化的操作
save 60 10000
#持久化出错是否继续工作
stop-writes-on-bgsave-error yes
#是否压缩rdb文件(需要消耗CPU资源)
dbcompression yes
#保存rdb文件的时候,进行错误的检查校验
rdbchecksum yes
#rdb文件保存的位置
dir ./
安全
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) ""
客户端
#设置能连接上redisde 最大客户端的数量
maxclients 10000
#redis配置最大的内存容量
maxmemory <bytes>
#内存容量到达上限之后的处理策略
maxmemory-policy noeviction
- 处理策略
1、volatile-lru:只对设置了过期时间的key进行LRU(默认值)
2、allkeys-lru : 删除lru算法的key
3、volatile-random:随机删除即将过期key
4、allkeys-random:随机删除
5、volatile-ttl : 删除即将过期的
6、noeviction : 永不过期,返回错误
append only模式(OAF)
#默认是不开启aof模式,默认使用rdb方式持久化,大部分情况下rdb完全够用
appendonly no
#持久化文件名称
appendfilename "appendonly.aof"
#锁模式
# appendfsync always 每次修改都会sync 消耗性能
appendfsync everysec #每秒执行一次,可能会丢失这一秒的数据
# appendfsync no 不执行sync,这个时候操作系统自己同步数据,速度最快
Redis持久化
Redis是内存数据库,如果不讲内存中的数据保存到磁盘,那么一旦服务器进程退出,服务器中的数据库状态也会小时,所以Redis提供了持久化功能
RDB(Redis Database)
什么是RDB
#如果900s内至少有一个key修改了,我们就进行持久化
save 900 1
#如果在300s内至少有十个key进行了修改,我们就进行持久化操作
save 300 10
#如果60s内有10000个key值进行了修改,我们就进行持久化的操作
save 60 10000
- 保存的是
触发机制
1、save的规则满足的情况下会自动触发
2、执行flushall命令
3、退出redis
备份就会自动生成dump.rdb文件
查看文件存在位置
127.0.0.1:6379> config get dir
1) "dir"
2) "/opt/redis-6.0.6/src"
- 优点
– 适合大规模数据恢复
– 如果对数据完整性要求不高 - 缺点
– 需要一定的时间间隔进行操作,如果redis意外宕机了,最后一次修改的数据就没有了
– fork进程的时候,会占用一定的内存空间
AOF(Append Only File)
是什么
将我们所有写命令都记录下来,只许追加文件但不许改写文件。Redis启动之初就会读取改文件重构数据,redis重启的话就根据日志文件的内容将写指令重新执行一次。
append
#默认是关闭的
appendonly no
# The name of the append only file (default: "appendonly.aof")
appendfilename "appendonly.aof"
如果AOF文件有错,redis无法启动,redis提供了redis-check-aof文件修复aof文件
[root@iZ0jli9zrxt29wd918ru5mZ src]# ./redis-cli -p 6379
Could not connect to Redis at 127.0.0.1:6379: Connection refused
not connected> exit
[root@iZ0jli9zrxt29wd918ru5mZ src]# ./redis-check-aof --fix appendonly.aof
0x 0: Expected prefix '*', got: 's'
AOF analyzed: size=8, ok_up_to=0, diff=8
This will shrink the AOF from 8 bytes, with 8 bytes, to 0 bytes
Continue? [y/N]: y
Successfully truncated AOF
配置
#默认是不开启aof模式,默认使用rdb方式持久化,大部分情况下rdb完全够用
appendonly no
#持久化文件名称
appendfilename "appendonly.aof"
#锁模式
# appendfsync always 每次修改都会sync 消耗性能
appendfsync everysec #每秒执行一次,可能会丢失这一秒的数据
# appendfsync no 不执行sync,这个时候操作系统自己同步数据,速度最快
- 优点:
– 每一次修改都同步,文件的完整会更好
– 每秒同步一次,可能丢失一秒数据
– 从不同步,效率最高 - 缺点
– AOF大于RDB文件,修复速度也比RBD慢
– AOF效率比rdb慢,因此我们redis默认的配置就是rdb持久化
重写规则
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
文件最大64m,超过就会进行重写
发布订阅
redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息
redis客户端可以订阅任意数量的频道
命令
订阅消息
127.0.0.1:6379> SUBSCRIBE duanjinyu
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "duanjinyu"
3) (integer) 1
1) "message"
2) "duanjinyu"
3) "hello"
发布评论
127.0.0.1:6379> PUBLISH duanjinyu "hello"
(integer) 1
Redis主从复制
概念
主从复制是指将一台redis服务器的数据复制到其他的redis服务器。
- 数据的复制是单向的,只能从主节点到从节点
- 主机负责写,从机负责读(80%的业务都是读)
作用
- 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
- 故障恢复:当主节点出现问题时,可以有从节点提供服务,实现快速的故障恢复,实际上是一种服务的冗余
- 负载均衡:读写分离,分担服务器负载
- 高可用(集群)基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础
环境配置
127.0.0.1:6379> info replication
# Replication
# 默认是主节点
role:master
connected_slaves:0
master_replid:cc58d5d00e4a3a7908a4a2651e985cc08cf535ae
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
从机配置
- 临时配置
127.0.0.1:6380> slaveof [ip] [port]
- 永久配置(在redis.conf)中配置如下信息
replicaof <masterip> <masterport>
# If the master is password protected (using the "requirepass" configuration
# directive below) it is possible to tell the replica to authenticate before
# starting the replication synchronization process, otherwise the master will
# refuse the replica request.
masterauth <master-password>
细节
- 主机只能写,从机只能读
- 主机宕机,从机依旧连接主机,但没有写操作,主机恢复依旧,从机依旧可以连接
- 从机如果使用命令行变为从机,断开恢复后会自动变为主机,但只要变为从机,主机的信息会立刻复制
– 全量复制:只要重新连接至master一定会来一次全量复制
– 增量复制
哨兵模式
哨兵的作用
- 通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
- 当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。
为了防止哨兵宕机
然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
故障切换(failover)的过程。
- 假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。
- 当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover操作。
- 切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。这样对于客户端而言,一切都是透明的。
启动过程
1、配置 sentinel.conf
# Example sentinel.conf
# 哨兵sentinel实例运行的端口 默认26379
port 26379
# 哨兵sentinel的工作目录
dir /tmp
# 哨兵sentinel监控的redis主节点的 ip port
# master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
# quorum 当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 1
# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
# 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,
这个数字越小,完成failover所需的时间就越长,
但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。
可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
# 故障转移的超时时间 failover-timeout 可以用在以下这些方面:
#1. 同一个sentinel对同一个master两次failover之间的间隔时间。
#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
#3.当想要取消一个正在进行的failover所需要的时间。
#4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
# 默认三分钟
# sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
# SCRIPTS EXECUTION
#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,
#这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,
#一个是事件的类型,
#一个是事件的描述。
#如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
#通知脚本
# sentinel notification-script <master-name> <script-path>
sentinel notification-script mymaster /var/redis/notify.sh
# 客户端重新配置主节点参数脚本
# 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
# 以下参数将会在调用脚本时传给脚本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 目前<state>总是“failover”,
# <role>是“leader”或者“observer”中的一个。
# 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的
# 这个脚本应该是通用的,能被多次调用,不是针对性的。
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
2、开启redis-sentinel
redis-sentinel xxx/sentinel.conf
- 优点:
– 哨兵集群,基于主从复制模式,所有主从复制的优点,它都有
– 主从可以切换,故障可以转移,系统的可用性更好
– 哨兵模式是主从模式的升级,手动到自动,更加健壮 - 缺点:
– Redis不好在线扩容,集群容量一旦达到上限,在线扩容就十分麻烦
– 实现哨兵模式的配置其实是很麻烦的,里面有很多配置项
缓存穿透和雪崩
缓存穿透
概念
当用户查询数据缓存中没有时,用户向持久层中查询,发现也没有,查询失败。当大量用户缓存都没命中(秒杀场景)去访问持久层,会对数据库造成很大压力,此时我们成为缓存穿透。
解决方法
- 布隆过滤器
是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力。
存在的问题
– 如果空值被存储起来,则需要有很多空间存储,因为可能会有很多空值。
– 即使对空值设置了过期时间,还是会存在缓存层和持久层的数据会有一段时间不一致,对于一致性业务要求较高。
缓存击穿
概念
当一个热度非常高的key扛着非常大的并发,在这个key失效的瞬间持续的大并发击破缓存涌入数据库。
解决方案
- 设置热点数据永不过期
- 加互斥锁(setnx)
缓存雪崩
概念
某一个时间段,缓存集体失效,redis宕机
eg:双十一零点抢购,这波商品比较集中的被放入缓存,假设缓存1小时,那么到凌晨一点的时候这批缓存就会集体过期,此时查询都落到了数据库,就有可能造成存储层挂掉的情况。
(阿里当天会停掉一些不重要的服务,如退款)
解决方案
- redis高可用
– 增加服务器(异地多活) - 限流降级
– 控制线程数 - 数据预热
– 把即将使用的数据事先部署