Redis教程

Redis 实战笔记

本文主要是介绍Redis 实战笔记,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Redis

yum源安装

yum install -y epel-release redis
systemctl enable redis
systemctl start redis
systemctl status redis

redis 简介

Redis是一个开源的使用 C语言编写的 Key-value内存数据库 读写性能强,支持多种数据类型 把数据存储在内存中的高速缓存 作者 Salvatore Sanfilippo # 中文文档 http://www.redis.cn/documentation.html

redis 特点

速度快
支持多种数据结构( string、list、hash、set、stored set)
持久化
主从复制(集群)
支持过期时间
支持事务
消息订阅
官方不支持 WINDOWS,但是有第三方版本

Redis与 Memcache的对比

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

对比测试

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

Redis应用场景

数据缓存     提高访问性能,使用的方式与 memcache相同。 会话缓存( Session Cache)     保存Web会话信息 排行榜/计数器     Nginx+lua+Redis 计数器进行IP自动封禁 消息队列     构建实时消息系统,聊天,群聊。

多实例

复制redis.conf redis-server redis-cli 到不同的文件夹 修改配置文件中的端口
# 去除注释
sed -ri '/^$|#/d' redis.conf
# 后台启动
[root@mysql-56 redis-6.0.9]# grep daemon redis.conf
daemonize yes
[root@mysql-56 redis-6.0.9]# ./src/redis-server redis.conf
[root@mysql-56 redis-6.0.9]# ./src/redis-cli -p 6380
127.0.0.1:6380>

redis 源码安装

#安装
wget http://download.redis.io/releases/redis-3.2.6.tar.gz
tar xzf redis-3.2.6.tar.gz
cd redis-3.2.6
make

#运行
src/redis-server
#客户端
src/redis-cli

#查看路径
rpm -ql redis 

# 启动客户端端口
redis-cli -p 6380


配置文件

主目录下 redis.conf  
port 6380    # 端口
daemonize yes                          # 后台运行
pidfile /var/run/redis_6380.pid        #进程文件
logfile "/data/redis6380/redis.log"    #日志文件
appendonly yes        #日志开关
dbfilename dump.rdb    # 持久化数据文件


[root@mysql-56 redis-6.0.9]# ls /data/redis6380/
redis.conf  redis.log  redis-server


redis 保护模式

一键部署 watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=
[root@mysql-56 redis-6.0.9]# cat /usr/lib/systemd/system/redis.service
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target


[Service]
ExecStart=/usr/bin/redis-server /etc/redis.conf --supervised systemd
ExecStop=/usr/libexec/redis-shutdown
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755


[Install]
WantedBy=multi-user.target

Bind 保护模式

  • Redis 3.2 新特性
    -解决访问安全
  • Bind
    -指定IP进行监听 bind 10.0.0.11
  • 禁止 protected-mode
    protected-mode yes/no
  • 增加 requirepass {password}
    requirepass 123456
  • 在redis-cli中使用
    auth {password}进行认证
[root@mysql-56 redis-6.0.9]# grep prote redis.conf
protected-mode yes
requirepass 123456

127.0.0.1:6380> SHUTDOWN
not connected> exit
127.0.0.1:6380> get foo
(error) NOAUTH Authentication required.
127.0.0.1:6380> auth 123456
OK
127.0.0.1:6380> get a
"1"

redis 数据

获取当前配置 CONFIG GET * 变更运行配置 CONFIG SET loglevel "notice"
watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

持久化

  • RDB持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)
  • AOF持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。AOF文件中的命令全部以Redis协议的格式来保存,新命令会被追加到文件的末尾。Redis还可以在后台对AOF文件进行重写(rewrite),使得AOF文件的体积不会超出保存数据集状态所需的实际大小。
  • Redis还可以同时使用AOF持久化和RDB持久化。在这种情况下,当 Redis重启时,它会优先使用AOF文件来还原数据集,因为AOF文件保存的数据集通常比RDB文件所保存的数据集更完整。
  • 你甚至可以关闭持久化功能,让数据只在服务器运行时存在。

持久化策略

日志文件 appendonly yes/no save 900 1 save 300 10 save 60  10000 分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改,即将数据写入硬盘。

压缩

decompression yes -指定存储至本地数据库时是否压缩数据,默认为yes,Redis 采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大

同步

appendfsync everysec     - no:表示等操作系统进行数据缓存同步到磁盘,linux 约30秒(快)     - always:表示每次更新操作后调用fsync()将数据写到磁盘(慢,安全)     - everysec:表示每秒同步一次(折中,默认值)

核心实战


数据类型


watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

常规操作

KEYS * 查看KEY支持通配符 DEL    删除给定的一个或多个key EXISTS    检查是否存在 EXPIRE    设定生存时间 TTL        以秒为单位返回过期时间 DUMP RESTORE        序例化与反序列化 PEXIRE PTTL PERSIST    以毫秒为单位 RENAME    变更KEY名 SORT    键值排序,有非数字时报错 TYPE    返回键所存储值的类型

字符串


SET name lewen Get name 一个键最大能存储512MB
Append    #将value追加到key原来的值的末尾
INCRBY    #增加
DECRBY    #减少
    DECRBY count 20    减去指定量
Mget mset    #同时获取设置一个或多个键值对
STRLEN    #返回字符串长度
INCR DECR    #将值增或减1

练习

127.0.0.1:6380> set name lewen
OK
127.0.0.1:6380> get name
"lewen"
127.0.0.1:6380> type name
string


127.0.0.1:6380> APPEND name 123
(integer) 8
127.0.0.1:6380> get name
"lewen123"


127.0.0.1:6380> mset name fadewalk age 24
OK
127.0.0.1:6380> get name
"fadewalk"
127.0.0.1:6380> get age
"24"


127.0.0.1:6380> mget name age
1) "fadewalk"
2) "24"


127.0.0.1:6380> STRLEN name
(integer) 8
127.0.0.1:6380> STRLEN age
(integer) 2

127.0.0.1:6380> INCR age
(integer) 25
127.0.0.1:6380> INCR age
(integer) 26

127.0.0.1:6380> DECR age
(integer) 25
127.0.0.1:6380> DECR age
(integer) 24

重复set 会覆盖掉前面的值

127.0.0.1:6380> EXISTS name
(integer) 1
127.0.0.1:6380> INCRBY age
(error) ERR wrong number of arguments for 'incrby' command
127.0.0.1:6380> INCRBY age 100
(integer) 124

hash

Redis hash 是一个键值对集合。 Redis hash 是一个 string类型的field 和 value 的映射表 hash 特别适合用于存储对象。 每个hash可以存储2^32-1键值对
HSET HGET    #设置返回单个值 HMSET HMGET    #设置返回多个值 Hmset user name quo sex male age 22
HGETALL   #返回KEY的所有键值 HEXSITS   #判断是否存在 HLEN      #判断长度 HKEYS    #获取所有字典 HVALS    #获取所有值 HDEL     #删除key中的一个或多个指定域
127.0.0.1:6380> hset user:1 name lewen
(integer) 1
127.0.0.1:6380> TYPE user:1
hash
127.0.0.1:6380> hset user:1 set male
(integer) 1

127.0.0.1:6380> hgetall user:1
1) "name"
2) "lewen"
3) "age"
4) "24"
5) "set"
6) "male"
127.0.0.1:6380> hget user:1 name
"lewen"
127.0.0.1:6380> hget user:1 age
"24"
127.0.0.1:6380> hmget user:1 name age
1) "lewen"
2) "24"

删除
127.0.0.1:6380> hdel user:1 name
(integer) 1
127.0.0.1:6380> hdel user:1 set
(integer) 1
127.0.0.1:6380> del user:1
(integer) 1
127.0.0.1:6380> keys *
1) "age"
2) "name"


127.0.0.1:6380> hmset user name lewen age 24 sex male
OK
127.0.0.1:6380> HINCRBY user age 10
(integer) 34
127.0.0.1:6380> HINCRBY user age -5
(integer) 29

list

Redis    列表是简单的字符串列表。 按照插入顺序排序每个 LIST可以存储2^32-1键值对
LPUSH    #将一个或多个值插入到列表头部 RPUSH    #将一个或多个值插入到列表尾部 LPOP/RPOP    #移除表头/尾的元素 LLEN      #返回列表长度 LRANGE    #返回指定的元素 LREM greet 2 morning    #删除前两个 morning LREM greet -1 morning   #删除后一个 morning LREM greet 0 hello     #删除所有 hello
Lindex    #返回列表key中下标为 index的元素 LSET key index value    #将列表key下标为 index的元素的值设置为value LINSERT    #插入数据位于某元素之前或之后。 LINSERT key BEFORE|AFTER pivot value
127.0.0.1:6380> lpush found gf yfd jy fc zs
(integer) 5
127.0.0.1:6380> type found
list


127.0.0.1:6380> lrange found 0 10
1) "zs"
2) "fc"
3) "jy"
4) "yfd"
5) "gf"


127.0.0.1:6380> lrange found 0 3
1) "zs"
2) "fc"
3) "jy"
4) "yfd"
127.0.0.1:6380> lrange found 0 5
1) "zs"
2) "fc"
3) "jy"
4) "yfd"
5) "gf"


127.0.0.1:6380> lpush found wj
(integer) 6
127.0.0.1:6380> lrange found 0 5
1) "wj"
2) "zs"
3) "fc"
4) "jy"
5) "yfd"
6) "gf"


127.0.0.1:6380> rpush found ha
(integer) 7
127.0.0.1:6380> lrange found 0 6
1) "wj"
2) "zs"
3) "fc"
4) "jy"
5) "yfd"
6) "gf"
7) "ha"


消费
127.0.0.1:6380> rpop found
"ha"
127.0.0.1:6380> lrange found 0 6
1) "wj"
2) "zs"
3) "fc"
4) "jy"
5) "yfd"
6) "gf"
127.0.0.1:6380> lpop found
"wj"
127.0.0.1:6380> lrange found 0 6
1) "zs"
2) "fc"
3) "jy"
4) "yfd"
5) "gf"

127.0.0.1:6380> rpush found bao1 bao2 bao3 bao4
(integer) 9
127.0.0.1:6380> lrange found 0 10
1) "zs"
2) "fc"
3) "jy"
4) "yfd"
5) "gf"
6) "bao1"
7) "bao2"
8) "bao3"
9) "bao4"
127.0.0.1:6380> lpop found
"zs"
127.0.0.1:6380> lpop found
"fc"
127.0.0.1:6380> lpop found
"jy"
127.0.0.1:6380> lpop found
"yfd"
127.0.0.1:6380> lpop found
"gf"
127.0.0.1:6380> lpop found
"bao1"

127.0.0.1:6380> lrange found 0 10
1) "bao2"
2) "bao3"
3) "bao4"
127.0.0.1:6380> LLEN found
(integer) 3




127.0.0.1:6380> rpush found bao1 bao2 bao3 bao4
(integer) 7
127.0.0.1:6380> lrange found 0 10
1) "bao2"
2) "bao3"
3) "bao4"
4) "bao1"
5) "bao2"
6) "bao3"
7) "bao4"
127.0.0.1:6380> lrem found 1 bao2
(integer) 1
127.0.0.1:6380> lrange found 0 10
1) "bao3"
2) "bao4"
3) "bao1"
4) "bao2"
5) "bao3"
6) "bao4"

127.0.0.1:6380> lset found 0 baozi001
OK
127.0.0.1:6380> lrange found 0 10
1) "baozi001"
2) "bao4"
3) "bao1"
4) "bao2"
5) "bao3"
6) "bao4"


127.0.0.1:6380> lindex found 0 "baozi001"
127.0.0.1:6380> linsert found after baozi001 baozi002 (integer) 7 127.0.0.1:6380> lrange found 0 10 1) "baozi001" 2) "baozi002" 3) "bao4" 4) "bao1" 5) "bao2" 6) "bao3" 7) "bao4"

redis 队列订阅

生产消费模型

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

消息模式

  • 发布消息通常有两种模式:队列模式( queuIng)和发布-订阅模式(publish- subscribe)。队列模式中, consumers可以同时从服务端读取消息,每个消息只被其中一个 consume读到。
  • 发布-订阅模式中消息被广播到所有的 consumer中, topic中的消息将被分发到组中的一个成员中。同一组中的 consumer可以在不同的程序中,也可以在不同的机器上。

Redis 发布订阅

  • Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
  • Redis客户端可以订阅任意数量的频道。
watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

订阅发布实例

SUBSCRIBE mq1    #客户端 PUBLISH mq1 "Redis is a great caching technique" PSUBSCRIBE 订阅一个或多个符合给定模式的频道 psubscribe news *tech* PUBLISH channel message 将信息 message 发送到指定的频道 channel。返回值代表消费者数量 pubsub channels    #显示订阅频道     PUBSUB NUMSUB news.it    #打印各频道订阅者数量 PUNSUBSCRIBE    #退订多个频道 SUBSCRIBE       #订阅给定的一个或多个频道的信息。 UNSUBSCRIBE     #退订频道
127.0.0.1:6380> PUBLISH mq1 "redis is a great caching technique" (integer) 2 127.0.0.1:6380>

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk= watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=



Redis 事务

Redis 事务可以一次执行多个命令 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。 事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。 原子性:事务中的命令要么全部被执行,要么全部都不执行。
执行过程
  • 开始事务
  • 命令入队
  • 执行事务


事务命令

DISCARD     取消事务,放弃执行事务块内的所有命合。 EXEC     执行所有事务块内的命令 MULTI     标记一个事务块的开始 UNWATCH     取消 WATCH命合对所有key的监视 WATCH key [key....]     -监视一个(或多个)key,如果在事务执行之前这个(或这些)key被其他命合所改动,那么事务捋被打断








watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk= watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=
watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=
watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=
watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=



watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=





数据备份

[root@cs7 ~]# redis-cli
127.0.0.1:6379> CONFIG GET dir  # 获取当前目录
1) "dir"
2) "/var/lib/redis"
[root@cs7 ~]# ls /var/lib/redis/
dump.rdb

  • Save备份(无持久化策略时),生成时在redis 当前目录中。
  • 恢复时只需将 dump.rdb 放入redis当前目录
    save 之后要关闭 才会保存到文件

备份恢复实例

[root@mysql-56 redis6380]# egrep "port|daemon|dir|logfile|dbfilename" redis.conf
port 6380
daemonize yes
logfile "./redis.log"
dbfilename dump-6380.rdb
dir /data/redis6380
[root@mysql-56 redis6380]# tree
.
├── appendonly.aof
├── dump-6380.rdb
├── redis.conf
├── redis.log
└── redis-server


[root@mysql-56 redis6380]# ./redis-server redis.conf
[root@mysql-56 redis6380]# redis-cli -p 6380
127.0.0.1:6380> KEYS *
(empty list or set)
127.0.0.1:6380> mset name lewen age 24
OK
127.0.0.1:6380> SHUTDOWN
not connected> exit
[root@mysql-56 redis6380]# ls
appendonly.aof  dump-6380.rdb  redis.conf  redis.log  redis-server
[root@mysql-56 redis6380]# mv dump-6380.rdb /tmp/
[root@mysql-56 redis6380]# mv appendonly.aof /tmp/

[root@mysql-56 redis6380]# ./redis-server redis.conf
[root@mysql-56 redis6380]# redis-cli -p 6380
127.0.0.1:6380> KEYS *
(empty list or set)
127.0.0.1:6380> SHUTDOWN
not connected>
[root@mysql-56 redis6380]# mv /tmp/dump-6380.rdb .
[root@mysql-56 redis6380]# ls
appendonly.aof  dump-6380.rdb  redis.conf  redis.log  redis-server
[root@mysql-56 redis6380]# ./redis-server redis.conf
[root@mysql-56 redis6380]# redis-cli -p 6380
127.0.0.1:6380> KEYS *
1) "age"
2) "name"

主从复制

主从配置

slaveof 192.168.1.1:6379 slave-read-only     # 只读模式 masterauth <password>        #主服务器设置密码后需要填写密码 min-slaves-to-write <number of slaves>     #从服务器不少于,才允许写入 min-slaves-max-lag <number of seconds>    #从服务器延迟不大于 CONFIG set slave-read-only yes Config set masterauth root info replication SLAVEOF NO ONE    #升级至 MASTER

127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=140,lag=1
slave1:ip=127.0.0.1,port=6382,state=online,offset=140,lag=1
master_replid:8b3a113a7708b59ec6da191eab8ddfa3a5ec2b92
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:140
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:140


127.0.0.1:6381> SLAVEOF 127.0.0.1 6380
OK
127.0.0.1:6382> SLAVEOF 127.0.0.1 6380
OK

127.0.0.1:6382> MGET name age
1) "lewen"
2) "24"
127.0.0.1:6381> SLAVEOF no one


基于 keepalived的自动故障切换
watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=
watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=
watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

Redis sentinel

redis 哨兵 实现主从复制master和slave 自动切换

Redis sentinel

·Redis-Sentinel 是 Redis官方推荐的高可用性(HA)解决方案,当用Redis做 Master-slave的高可用方案时,假如 master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel 本身也是一个独立运行的进程,它能监控多个 master-slave 集群,发现 master宕机后能进行自动切换。

功能

监控( Monitoring):Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。 提醒( Notification):当被监控的某个Redis服务器出现问题时,Sentinel可以通过API向管理员或者其他应用程序发送通知。 自动故障迁移( Automatic failover):当一个主服务器不能正常工时, Sentinel会开始一次自动故障迁移操作,它会将失效主服务器的其中一个从服务器升级为新的主服务器,并让失效主服务器的其他从服务器改为复制新的主服务器;当客户端试图连接失效的主服务器时,集群也会向客户端返回新主服务器的地址,使得集群可以使用新主服务器代替失效服务器。

Sentinel 命令

PING: 返回PONG SENTINEL masters:列出所有被监视的主服务器 SENTINEL slaves <master name> SENTINEL get-master-addr-by-name<master name>:返回给定名字的主服务器的IP地址和端口号。 SENTINEL reset <pattern>:重置所有名字和给定模式 pattern相匹配的主服务器。 SENTINEL failover <master name>:当主服务器失效时,在不询问其他 Sentinel意见的情况下,强制开始一次自动故障迁移。
查看配置文件

配置


cp src/redis-sentinel sentinel.conf 
vim sentinel.conf
port 26380
dir "."
sentinel monitor mcmaster 127.0.0.1 6381 1  # 主的个数,这里就写一个
sentinel down-after-milliseconds mymaster 60000
sentinel config-epoch mymaster O
#启动
./redis-sentinel /sentinel.conf
watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk= watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk= 实操配置 复制到哨兵文件到 /data/s1
[root@mysql-56 s1]# cat sentinel.conf
port 26379
daemonize yes
pidfile "/var/run/redis-sentinel.pid"
logfile "./sentinel.log"
dir "/data/s1/"
sentinel myid 1c83d3230453094e2878f2f89dcd609ec601e380
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 127.0.0.1 6381 1
sentinel down-after-milliseconds mymaster 10000
sentinel config-epoch mymaster 1

配置文件

指定监控 master sentinel monitor mymaster 127.0.0.1 6379 2 {2表示多少个 sentinel同意} 安全信息 sentinel auth-pass mymaster luyx30 超过15000毫秒后认为主机宕机 sentinel down-after-milliseconds mymaster 15000 ·当主从切换多久后认为主从切换失败 sentinel failover-timeout mymaster 100000 这两个配置后面的数量主从机需要一样, epoch为 master的版本 sentinel leader-epoch mymaster 1 sentinel config-epoch mymaster 1

演示

6380 挂了 会自动的 6381 成为master 当6380 恢复了以后,又可以加入成为slave 如下:
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=9326,lag=0
slave1:ip=127.0.0.1,port=6382,state=online,offset=9326,lag=0
master_replid:8b3a113a7708b59ec6da191eab8ddfa3a5ec2b92
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:9459
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:9459
127.0.0.1:6380> SHUTDOWN
not connected>


[root@mysql-56 s1]# redis-cli -p 6381
127.0.0.1:6381> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6382,state=online,offset=11106,lag=0
master_replid:15dc060e31823a40c0e971733dc0add4c3e960f0
master_replid2:8b3a113a7708b59ec6da191eab8ddfa3a5ec2b92
master_repl_offset:11106
second_repl_offset:10006
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:11106


Redis cluster



Redis集群

Reds集群是一个可以在多个Redis节点之间进行数据共享的设施(installation)。 Redis集群不支持那些需要同时处理多个键的Redis命合,因为执行这些命令需要在多个Redis节点之间移动数据,并且在高负载的情况下,这些命令将降低Redis集群的性能,并导致不可预测的行为 Redis集群通过分区(partition)来提供一定程度的可用性(availability):即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命合请求。 将数据自动切分(split)到多个节点的能力。 当集群中的一部分节点失效或者无法进行通讯时,仍然可以继续处理命令请求的能力。

前面是 主从复制的小集群

Redis 集群数据共享

  • Redis集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现:一个Redis集群包含16384个哈希槽( hash slot),数据库中的每个键都属于这16384个哈希槽的其中一个,集群使用公式CRC16(key)% 16384来计算键key属于哪个槽,其中CRC16(key)语句用于计算键key的CRC16校验和。
  • 节点A负责处理0号至5500号哈希槽。
  • 节点B负责处理5501号至11000号哈希槽。
  • 节点C负责处理11001号至16384号哈希槽

集群的复制

  • 为了使得集群在一部分节点下线或者无法与集群的大多数(majority)节点进行通讯的情况下,仍然可以正常运作,Redis集群对节点使用了主从复制功能:集群中的每个节点都有1个至N个复制品(replicate),其中一个复制品为主节点(master),而其余的N-1个复制品为从节点(slave)。
  • 在之前列举的节点A、B、C的例子中,如果节点B下线了,那么集群将无法正常运行,因为集群找不到节点来处理501号至11000号的哈希槽。
  • 假如在创建集群的时候(或者至少在节点B下线之前),我们为主节点B添加了从节点B1,那么当主节点B下线的时候,集群就会捋B1设置为新的主节点,并让它代替下线的主节点B,继续处理5501号至11000号的哈希槽,这样集群就不会因为主节点B的下线而无法正常运作了。
  • 不过如果节点B和B1都下线的话,Redis集群还是会停止运作。

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=


运行机制

所有的 redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。 节点的fail是通过集群中超过半数的 master节点检测失效时才生效 客户端与redis节点直连,不需要中间 proxy层.客户端不需要连接集群所有节点连接集群中任何一个可用节点即可
把所有的物理节点映射到[0~16383] slot上,cluster 负责维护 node slot key

注意

需要安装ruby支持 yum install ruby rubygems -y gem install redis <如果gem卡住不动,使用国内镜像> gemsources--addhttps://gems.ruby-china.org/--remove https://rubygems.org/ gem sources - [root@mysql-56 s1]# yum install ruby rubygems -y [root@mysql-56 s1]# gem install redis




[root@mysql-56 s1]# gem sources -a https://mirrors.ustc.edu.cn/rubygems/ https://mirrors.ustc.edu.cn/rubygems/ added to sources [root@mysql-56 s1]# gem sources --remove https://rubygems.org/ https://rubygems.org/ removed from sources [root@mysql-56 s1]# gem sources -l *** CURRENT SOURCES *** https://mirrors.ustc.edu.cn/rubygems/


配置文件中包含
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

创建多个实例

#!/bin/bash
rm -rf /data/700*
for no in {0..5}
do
    mkdir /data/700$no
    cd /data/700$no
    cp -r /data/redis6380/* ./    
    sed -i "s/port 6379/port 700$no/g" redis.conf
    sed -i "s/daemonize no/daemonize yes/g" redis.conf
    sed -i "s#/var/log/redis/redis.log#redis.log#g" redis.conf
    # sed -i "s/dump.rdb/dump_700$no.rdb/g" redis.conf
    # sed -i "s/appendonly.aof/appendonly_700$no.aof/g" redis.conf
    echo "cluster-enabled yes" >> redis.conf
    echo "cluster-config-file nodes.conf" >> redis.conf
    echo "cluster-node-timeout 5000" >> redis.conf
    sed -i "s/appendonly no/appendonly yes/g" redis.conf
    sed -i "s/redis_6379.pid/redis_700$no.pid/g" redis.conf
    sed -i "/dir/d" redis.conf
    echo 'dir "./"' >>redis.conf
    
done


启动实例

#!/bin/bash
for i in `ss -lntp|grep 700|egrep 'pid=[0-9]{4}'|awk -F '=|,' '{print $3}'`;do kill -9 $i;done
for no in {0..5}
do

    cd /data/700$no
    ./redis-server ./redis.conf

done

创建集群

/data/redis-trib.rb 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.rb程序的命合是 create,这表示我们希望创建一个新的集群。 选项 --replicas 1 表示我们希望为集群中的每个主节点创建一个从节点 之后跟着的其他参数则是实例的地址列表,我们希望程序使用这些地址所指示的实例来创建新集群。
# 新的创建集群方式 /data/redis-cli --cluster create 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 --cluster-replicas 1
watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk= 集群客户端 [root@txy redis-6.0.9]# redis-cli -c -p 7000 重新分片 ./redis-trib.rb reshard 127.0.0.1:7000
[root@txy redis-6.0.9]# redis-cli -c -p 7000
127.0.0.1:7000> set name lewf
-> Redirected to slot [5798] located at 127.0.0.1:7001
OK
127.0.0.1:7001> set name lewfd
OK
127.0.0.1:7001> set name lewfd
OK
127.0.0.1:7001> get name
"lewfd"

集群管理

集群状态 redis-cli -p 7000 cluster nodes |grep master 故障转移 redis-cli -p 7002 debug segfault 查看状态 redis-cli -p 7000 cluster nodes|grep master watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

增加新的节点

./redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000 变成某实例的从 redis 127.0.0.1:7006 > cluster replicate 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 删除一个节点 redis-trib del-node ip:port '<node-id>' 删除 master节点之前首先要使用 reshard 移除 master的全部 slot,然后再删除当前节点

状态说明

  • 集群最近一次向节点发送PING命合之后,过去了多长时间还没接到回复。
  • 节点最近一次返回PONG回复的时间。
  • 节点的配置纪元(configuration epoch):详细信息请参考Redis 集群规范。
  • 本节点的网络连接情况:例如 connected。
  • 节点目前包含的槽:例如 1270.0.1:7001 目前包含号码为5960至10921的哈希槽。


面试常问


集群 哨兵 持久化问题

redis qps

单实例 qps每天11万次
不要超过5万 最大3万






这篇关于Redis 实战笔记的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!