本节内容基于 centos 7.4.1708,redis 3.2.12 环境实验。
redis 是一个开源的高性能键值对数据库。
安装:yum install -y redis
特性:
可执行文件:
启动方式:
启动验证:
ps -ef|grep redis
redis-cli -h locahost -p 6379 ping
由于 redis 是单线程的,推荐在一台多核cpu机器上部署多个 redis 实例充分发挥。
redis 持久化支持2种:
注意:
rdb是什么:
触发命令:
主要触发方式:
过程:
优点:
缺点:
关闭rdb方式:
redis-cli config set save ""
注意:
rdb并不能真正的关闭,在主从复制时主从都会生成rdb文件
aof是什么:
由于每次改动都会记录,产生2个问题:
aof文件有3种写入策略:
aof重写:
注意:
为什么需要主从复制:
通过持久化保证 redis 在服务器重启的情况下数据也不会丢失。但数据在一台服务器上,如果服务器的硬盘坏了,也会导致数据丢失。为了避免单点故障,redis 提供了主从复制高可用方案。
主从复制结构:
开启复制:
--slaveof ip port
slaveof ip port
(默认配置都是master)关闭复制:
slaveof no one
复制类型:
全量复制过程:
psync ? -1
在master重启(master 的run_id更新)和slave重启(slave 的run_id丢失)时都会发生全量复制,通过 info server 可以查看run_id。
部分复制过程:
当全量复制完成 或 网络抖动一定范围 时,master 相当于 slave 的 client 进行增量更新数据。
redis-sentinel是什么?
sentinel工作原理:
2种下线判定:
启动方式:
redis-sentinel /path/to/sentinel.conf
redis-server /path/to/sentinel.conf --sentinel
三个定时任务:
__sentinel__:hello
发布一条消息,宣布自己的存在。同时也订阅来确定其他的 sentinel 节点。配置模拟:
echo "停止当前所有redis-server + redis-sentinel"; ps -x | grep redis | grep -v grep | awk '{print $1}' | xargs -r kill echo "生成并启动3个 redis 配置"; for port in 6379 6380 6381 ;do echo -e "daemonize yes\nport $port\npidfile /var/run/redis-$port.pid\nlogfile /var/log/redis/redis-$port.log\n" > /etc/redis/redis-$port.conf if [ $port != 6379 ];then echo "slaveof 127.0.0.1 6379" >> /etc/redis/redis-$port.conf fi redis-server /etc/redis/redis-$port.conf done echo "生成并启动3个 redis-sentinel 配置"; for port in 26379 26380 26381 ;do echo -e "daemonize yes\nport $port\ndir /tmp\nsentinel monitor mymaster 127.0.0.1 6379 2\nsentinel down-after-milliseconds mymaster 3000\nsentinel parallel-syncs mymaster 1\nsentinel failover-timeout mymaster 60000\nlogfile /var/log/redis/sentinel-$port.log\n" > /etc/redis/redis-sentinel-$port.conf redis-sentinel /etc/redis/redis-sentinel-$port.conf done echo "结束";
常用的channel:
.net core环境开发:
dotnet add package stackexchange.redis
var options = new configurationoptions() { commandmap = commandmap.sentinel, endpoints = { { "192.168.0.51", 26379}, {"192.168.0.51", 26381}, {"192.168.0.51", 26380} }, allowadmin = true, tiebreaker = "", servicename = "mymaster", synctimeout = 5000 }; var sentinelconn = connectionmultiplexer.connect(options); var master = sentinelconn.getserver("192.168.0.51",26381).sentinelgetmasteraddressbyname("mymaster"); // ... var conn = connectionmultiplexer.connect(master); sentinelconn.getsubscriber().subscribe("+switch-master", (channel, message) => { // mymaster 192.168.0.51 6380 192.168.0.51 6381 console.writeline((string)message); // ... conn = connectionmultiplexer.connect(ip); conn.getdatabase().stringset("hello","故障切换后值"); }); sentinelconn.getsubscriber().subscribe("+convert-to-slave", (channel, message) => { // slave 192.168.0.51:6379 192.168.0.51 6379 @ mymaster 192.168.0.51 6380 console.writeline((string)message); }); conn.getdatabase().stringset("hello","原始值");
注意:
实际上大部分场景下,redis sentinel已经足够好。请根据实际情况采用 redis cluster。
redis cluster 采用虚拟槽分区方式(16384个虚拟槽)。
原因:
常用命令:
redis-cli -h localhost -p 6382 cluster info
:查看集群基本信息redis-cli -h localhost -p 6382 cluster slots
:查看集群slot信息redis-cli -h localhost -p 6382 cluster nodes
:查看集群node信息redis-cli -c
:move自动跳转执行yum install -y redis-trib
:官方提供了基于 ruby 的工具方便部署搭建 cluster 过程:
cluster-enabled:yes
cluster-node-timeout 15000
cluster-require-full-coverage no
cluster-config-file node-${port}.conf
redis-cli cluster meet ip port
redis-cli cluster addslots {0....5461}
redis-cli cluster replicate {nodeid}
redis-cli 搭建:
echo "停止当前所有redis-server + redis-sentinel"; mkdir /etc/redis ps -x | grep redis | grep -v grep | awk '{print $1}' | xargs -r kill sleep 1 echo "启动6个 redis + meet"; for port in 7000 7001 7002 7003 7004 7005;do echo -e "daemonize yes\nport $port\npidfile /var/run/redis-$port.pid\nlogfile /var/log/redis/redis-$port.log\ncluster-enabled yes\ncluster-config-file nodes-$port.conf\ncluster-require-full-coverage no" > /etc/redis/redis-$port.conf redis-server /etc/redis/redis-$port.conf done for port in 7000 7001 7002 7003 7004 7005;do redis-cli -p $port flushall redis-cli -p $port cluster reset soft if [ $port != 7000 ];then redis-cli -p 7000 cluster meet 127.0.0.1 $port fi done sleep 1 echo "分配 16383 槽"; redis-cli -p 7000 cluster addslots {0..5461} redis-cli -p 7001 cluster addslots {5462..10922} redis-cli -p 7002 cluster addslots {10922..16383} echo "配置 replication" redis-cli -p 7003 cluster replicate `redis-cli -p 7000 cluster nodes | grep myself | awk '{print $1}'` redis-cli -p 7004 cluster replicate `redis-cli -p 7001 cluster nodes | grep myself | awk '{print $1}'` redis-cli -p 7005 cluster replicate `redis-cli -p 7002 cluster nodes | grep myself | awk '{print $1}'`
redis-trib搭建:
redis-trib create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
redis-trib create 会自动meet、addslots、replicate。
查看去除注释的配置:cat /etc/redis.conf | grep -v '^#' | grep -v '^$'
设置配置:config set key value
查询所有配置:config get *
配置项 | 默认值 | 推荐值 | 说明 |
---|---|---|---|
daemonize | no | yes(docker环境例外) | 是否以守护进程方式启动 |
port | 6379 | - | redis服务监听端口 |
pidfile | /var/run/redis.pid | /var/run/redis-{port}.pid | pid文件 |
logfile | /var/log/redis/redis.log | /var/log/redis/redis-{port}.log | 日志文件名:redis工作时产生的日志。 |
dir | /var/lib/redis | - | rdb文件和aof文件目录。推荐使用大文件目录。(不指定则为当前目录) |
protected-mode | yes | - | 限制为127.0.0.1访问。启用条件:没有bindip 和 没有设置密码 |
配置项 | 默认值 | 推荐值 | 说明 |
---|---|---|---|
dbfilename | dump.rdb | dump-{port}.rdb | rdb文件名 |
rdbcompression | yes | yes | 压缩格式 |
stop-writes-on-bgsave-error | yes | yes | 出现错误时,停止新的写入 |
rdbchecksum | yes | yes | 数据完整性校验 |
配置项 | 默认值 | 推荐值 | 说明 |
---|---|---|---|
appendonly | no | yes | 是否开启 aof 模式 |
appendfilename | "appendonly.aof" | "appendonly-{port}.aof" | aof文件名 |
appendfsync | everysec | everysec | fsync方式 |
no-appendfsync-on-rewrite | no(安全) | yes(高性能) | 在 aof 重写时,是否停止fsync |
auto-aof-rewrite-min-size | 64mb | - | aof文件重写的最小大小 |
auto-aof-rewrite-percentage | 100 | - | aof文件增长率 |
aof-load-truncated | yes | yes | 当 aof 文件不完整的时候,将完整的部分加载 |
配置项 | 默认值 | 推荐值 | 说明 |
---|---|---|---|
slowlog-max-len | 128 | 1000 | 慢查询队列长度 |
slowlog-log-slow-than | 10000 | 1000(qps1w) | 慢查询阈值(单位:微秒) |
slaveof | ip port | - | 主从复制配置 |
slave-read-only | yes | yes | 从节点只读 |
repl-backlog-size | 1048576 | 10m | 复制缓存区,可以再原有基础上稍微增加 |
配置项 | 默认值 | 推荐值 | 说明 |
---|---|---|---|
daemonize | no | yes | 是否以守护进程方式启动 |
port | 26379 | {port} | sentinel监听端口 |
dir | /tmp | - | 工作目录 |
sentinel monitor | mymaster 127.0.0.1 6379 2 | - | odown(objectively down,客观下线)规则:mastername ip port quorum |
sentinel down-after-milliseconds | mymaster 30000 | - | sdown(subjectively down,主观下线)规则:mastername timeout(单位:毫秒) |
sentinel parallel-syncs | mymaster 1 | - | 并发同步数量 |
sentinel failover-timeout | mymaster 180000 | - | 多长时间内不再故障转移(单位:毫秒) |
logfile | /var/log/redis/sentinel.log | /var/log/redis/sentinel-{port}.log | 日志文件 |
配置项 | 默认值 | 推荐值 | 说明 |
---|---|---|---|
cluster-enabled | no | yes | 开启cluster模式 |
cluster-node-timeout | 15000 | - | 故障转移时间,主观下线超时时间 |
cluster-config-file | nodes-{port}.conf | cluster配置 | |
cluster-require-full-coverage | yes | no | cluster 所有节点全部在线才提供服务 |
redis其实不是单线程(fsync,bgsave),一次只能执行一条命令。
查询慢查询队列:slowlog get
客户端请求的生命周期:
慢查询发送在第三个阶段(执行命令),客户端超时不一定是慢查询。
repl_backlog_size
调整大info 信息:
如对本文有疑问, 点击进行留言回复!!
网友评论