数据库缓存服务——Redis(企业级)

目录

一、Redis 主从复制

1、Redis主从复制特性

2、Redis主从复制原理

3、Redis命令的传播

4、Redis复制的一致性问题

5、Redis复制安全性提升

6、Redis主从复制实战

二、RedisHA Sentinel集群

1、Redis Sentinel功能

2、Redis Sentinel的工作流程

3、Redis Sentinel服务器连接

发现并连接主服务器

发现并连接从服务器

 4、Redis Sentinel

 5、Redis Sentinel(哨兵)实现 Redis 的高可用性实战

1、master部署sentinel

2、配置文件解释:

3、slave-1部署sentinel

4、slave-2部署sentinel

5、sentinel操作

6、哨兵模式下的主从测试

三、Redis Cluster去中心化集群

1、为什么要用redis-cluster集群?

2、什么是Redis-Cluster

 1、redis-cluster特点

2、redis-cluster数据分布

3、redis cluster 主从模式

4、集群操作

1、客户端登录

2、集群添加节点

3、集群删除节点

5、主从切换

 redis面试问题整理

elk相关面试


一、Redis 主从复制

1、Redis主从复制特性

  • 使用异步复制
  • 一个主服务器可以有多个从服务器
  • 从服务器也可以有自己的从服务器
  • 复制功能不会阻塞主服务器
  • 可以通过复制功能来让主服务器免于执行持久化操作,由从服务器去执行持久化操作即可
  • 关闭主服务器持久化时,复制功能的数据时完全安全的
  • 当配置Redis复制功能时,强烈建议打开主服务器的持久化功能。否则的话,由于延迟问题应该要避免部署的服务自动拉起

2、Redis主从复制原理

redis主从同步有两种方式(或者说两个阶段):全同步和部分同步

主从刚刚连接的时候,进行全同步;全同步结束后,进行部分同步。当然,如果有需要,slave在任何时候都可以发起全同步。

redis的策略是,无论如何,首先会尝试进行部分同步,如不成功,要求从机进行全同步,并启动BGSAVE...BGSAVE结束后,传输RDB文件,如果成功,允许从机进行部分同步,并传输积压空间中的数据。

主从同步的机制:

  • 从机向主服务器发送SYNC(请求同步)命令。
  • 接到SYNC命令的主服务器会调用BGSAVE命令,创建一个RDB文件,并使用缓冲区记录接下来执行的所有写命令。
  • 当主服务器执行完BFSAVE命令时,它会向从服务器发送RDB文件,而从服务器则会接收并载入这个文件。
  • 主服务器将缓冲区储存的所有写命令发送给从服务器执行。

3、Redis命令的传播

在主从服务器完成同步之后,主服务器每执行一个命令,它都会将被执行的写命令发送给从服务器执行,这个操作被称为“命令传播”(command propagate)

命令传播是一个持续的过程:只要复制人在继续,命令传播就会一直进行,使得主从服务器的状态可以一直保持一致

4、Redis复制的一致性问题

 

 在读写分离环境下,客户端向主服务器发送写命令SET n 10086,主服务器在执行这个写命令后,向客户端返回回复,并将这个写命令传播给从服务器。

接到回复的客户端继续向从服务器发送读命令GRT n,并且因为网络状态的原因,客户端的GET命令比主服务器传播的SET命令更快到达了从服务器。

因为从服务器n的值还未被更新,所以客户端在从服务器读取到的将是一个错误(过期)的n值。

5、Redis复制安全性提升

主服务器在至少有N个从服务器的情况下,才执行写操作。从redis2.8开始,为保证数据的安全性,可以通过配置,让主服务器只在有至少N个当前已连接服务器的情况下,才执行写命令。

不过,因为redis使用异步复制,所以主服务器发送的写数据并不一定被从服务器接收到,因此,数据丢失的可能性任然存在。

通过一下两个参数保证数据的安全:

min-slaves-to-write <number of slaves>
min-slaves-max-lag <number of seconds>

解释:

要求至少有1个slave,数据复制和同步的延迟不能超过10秒,如果说一旦所有的slave,数据复制和同步的延迟都超过了10秒,那么这个时候,master就不会再接受任何请求了

减少异步复制的数据丢失

有了min-slaves-max-lag这个配置,就可以确保说,一旦slave复制数据和ack延迟太长,就认为可能master宕机后损失的数据太多了。那么就拒绝写请求,这样就可以吧master宕机时由于部分数据未同步到slave导致的数据丢失降低到可控的范围内

减少脑裂的数据丢失

如果一个master出现了脑裂,跟其他slave丢了连接,那么上面两个配置可以确保说,如果不能继续给指定数量的slave发送数据,而且slae超过10秒没有给自己ack消息,那么直接拒绝客户端的写请求,这样脑裂后的旧master就不会接受client的新数据,也就避免了数据丢失

上面的配置就确保了,如果跟任何一个slave丢了数据,在10秒后发现没有slave给自己ack,那么就拒绝新的写请求,因此在脑裂场景下,最多就丢失10秒的数据

6、Redis主从复制实战

准备三台服务器:

master:192.168.242.144

slave-1:192.168.242.145

slave-29:12.168.242.146

三台都安装redis(yum安装)

[root@localhost ~]# yum -y install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
[root@localhost ~]# yum -y --enablerepo=remi install redis

master修改配置文件:

[root@localhost ~]# vim /etc/redis.conf   #删除原文件所有内容,输入下面的内容
bind 192.168.242.144 127.0.0.1       #127.0.0.1写不写都可以
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile /var/log/redis/redis.log
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
dir /var/lib/redis
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-diskless-load disabled
repl-disable-tcp-nodelay no
replica-priority 100
acllog-max-len 128
requirepass redis       #设置的redis的登录密码
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
lazyfree-lazy-user-del no
oom-score-adj no
oom-score-adj-values 0 200 800
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
jemalloc-bg-thread yes

slave-1修改配置文件

[root@localhost ~]# vim /etc/redis.conf   #删除原文件所有内容,输入下面的内容
bind 192.168.242.145
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile /var/log/redis/redis.log
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
dir /var/lib/redis
replicaof 192.168.242.145 6379      #master的ip 端口
masterauth redis    #master的认证密码
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-diskless-load disabled
repl-disable-tcp-nodelay no
replica-priority 100
acllog-max-len 128
requirepass redis   #本机redis的登录密码
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
lazyfree-lazy-user-del no
oom-score-adj no
oom-score-adj-values 0 200 800
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
jemalloc-bg-thread yes

slave-2修改配置文件

[root@localhost ~]# vim /etc/redis.conf   #删除原文件所有内容,输入下面的内容
bind 192.168.242.146
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile /var/log/redis/redis.log
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
dir /var/lib/redis
replicaof 192.168.242.145 6379      #master的ip 端口
masterauth redis                    #master的认证密码
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-diskless-load disabled
repl-disable-tcp-nodelay no
replica-priority 100
acllog-max-len 128
requirepass redis                   #本机redis的登录密码
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
lazyfree-lazy-user-del no
oom-score-adj no
oom-score-adj-values 0 200 800
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
jemalloc-bg-thread yes

依次启动三台服务器的redis服务

[root@localhost ~]# systemctl start redis

验证服务

master:
[root@localhost ~]# redis-cli -a redis -h 192.168.242.144
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.242.145,port=6379,state=online,offset=70,lag=1
slave1:ip=192.168.242.146,port=6379,state=online,offset=70,lag=1
master_failover_state:no-failover
master_replid:a9ce8d3b8be47c945730bc8599705bcc8ecf9176
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:70
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:70
127.0.0.1:6379> set name 123
OK

slave-1:
redis-cli -a redis -h 192.168.242.145
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.242.145:6379> get name
"123"
slave-2:
192.168.242.146:6379> get name
"123"

二、RedisHA Sentinel集群

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

Sentinel 是一个监视器,它可以根据被监视实例的身份和状态来判断应该执行何种动作。

1、Redis Sentinel功能

Sentinel的主要功能包括主节点存活检测、主从运行情况检测、自动故障转移(failover)、主从切换。Redis的Sentinel最小配置是一主一从。 Redis的Sentinel系统可以用来管理多个Redis服务器,该系统可以执行以下四个任务:

  • 监控:Sentinel会不断的检查主服务器和从服务器是否正常运行
  • 通知:当被监控的某个redis服务器出现问题,Sentinel或通过API脚本向管理员或者其他的应用程序发送通知
  • 自动故障转移:当主节点不能正常进行工作时,Sentinel会开始一次自动的故障转移操作,它会将与失效主节点的主从关系的一个从节点升级为新的主节点,并且将其他从节点只想新的主节点。
  • 配置提供者:在redis sentinel模式下,客户端应用在初始化时,连接的是sentinel节点集合,从中获取主节点的信息

2、Redis Sentinel的工作流程

由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器,以及所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求 。如下图:

 Sentinel负责监控集群中的所有主、从Redis,当发现主故障时,Sentinel会在所有的从中选一个成为新的主。并且会把其余的从变为新主的从。同时那台有问题的旧主也会变为新主的从,也就是说当旧的主即使恢复时,并不会恢复原来的主身份,而是作为新主的一个从。

在Redis高可用架构中,Sentinel往往不是只有一个,而是有3个或者以上。目的是为了让其更加可靠,毕竟主和从切换角色这个过程还是蛮复杂的。

3、Redis Sentinel服务器连接

发现并连接主服务器

sentinel会与被监视的主服务器创建两个网络连接:

 命令连接用于向主服务器发送命令。

订阅连接用于订阅指定的频道,从而发现监视同一主服务器的其他 Sentinel。

发现并连接从服务器

 4、Redis 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 意见的情况下,强制开始一次自动故障迁移。

 5、Redis Sentinel(哨兵)实现 Redis 的高可用性实战

在上面那个实验基础上进行,实验环境:

master:192.168.242.144 (sentinel01)

slave-1:192.168.242.145 (sentinel02)

slave-29:12.168.242.146 (sentinel03)

1、master部署sentinel

[root@localhost ~]# vim /etc/redis-sentinel.conf   #删除原文件所有内容,输入下面的内容
port 26379
daemonize no
pidfile /var/run/redis-sentinel.pid
logfile /var/log/redis/sentinel.log
dir /tmp
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes

2、配置文件解释:

# 端口
port 26379
# 是否后台启动
daemonize yes
# 保护模式如果开启只接受回环地址的ipv4和ipv6地址链接,拒绝外部链接,而且正常应该配置多个哨兵,避免一个哨兵出现独裁情况,如果配置多个哨兵那如果开启也会拒绝其他sentinel的连接。导致哨兵配置无法生效。
protected-mode no  
# pid文件路径
pidfile /var/run/redis-sentinel.pid
# 日志文件路径
logfile "/var/log/redis/sentinel.log"
# 定义工作目录
dir /tmp
# 定义Redis主的别名, IP, 端口,这里的2指的是需要至少2个Sentinel认为主Redis挂了才最终会采取下一步行为
sentinel monitor mymaster 127.0.0.1 6379 2
#如果redis配置了密码,那这里必须配置认证,否则不能自动切换
sentinel auth-pass mymaster redispass    
# 如果mymaster 30秒内没有响应,则认为其主观失效
sentinel down-after-milliseconds mymaster 30000
# 如果master重新选出来后,其它slave节点能同时并行从新master同步数据的台数有多少个,显然该值越大,所有slave节点完成同步切换的整体速度越快,但如果此时正好有人在访问这些slave,可能造成读取失败,影响面会更广。最保守的设置为1,同一时间,只能有一台干这件事,这样其它slave还能继续服务,但是所有slave全部完成缓存更新同步的进程将变慢。
sentinel parallel-syncs mymaster 1
# 该参数指定一个时间段,在该时间段内没有实现故障转移成功,则会再一次发起故障转移的操作,单位毫秒
sentinel failover-timeout mymaster 180000
# 不允许使用SENTINEL SET设置notification-script和client-reconfig-script。
sentinel deny-scripts-reconfig yes

3、slave-1部署sentinel

[root@localhost ~]# vim /etc/redis-sentinel.conf   #删除原文件所有内容,输入下面的内容
port 26379
daemonize no
pidfile /var/run/redis-sentinel.pid
logfile /var/log/redis/sentinel.log
dir /tmp
sentinel monitor mymaster 192.168.242.144 6379 2
sentinel auth-pass mymaster redis
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes

4、slave-2部署sentinel

[root@localhost ~]# vim /etc/redis-sentinel.conf   #删除原文件所有内容,输入下面的内容
port 26379
daemonize no
pidfile /var/run/redis-sentinel.pid
logfile /var/log/redis/sentinel.log
dir /tmp
sentinel monitor mymaster 192.168.242.144 6379 2
sentinel auth-pass mymaster redis
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes

在redis正常运行的前提下,依次启动sentinel01、sentinel02、sentinel03

[root@localhost ~]# systemctl restart redis-sentinel.service

5、sentinel操作

master:192.168.242.144:
[root@localhost ~]# redis-cli -p 26379
127.0.0.1:26379> sentinel master mymaster
 1) "name"
 2) "mymaster"
 3) "ip"
 4) "192.168.242.144"
 5) "port"
 6) "6379"
....

slave-1:192.168.242.145:
127.0.0.1:26379> sentinel master mymaster
 1) "name"
 2) "mymaster"
 3) "ip"
 4) "192.168.242.144"
 5) "port"
 6) "6379"
....

slave-2:192.168.242.146:
127.0.0.1:26379> sentinel master mymaster
 1) "name"
 2) "mymaster"
 3) "ip"
 4) "192.168.242.144"
 5) "port"
 6) "6379"
....

6、哨兵模式下的主从测试

模拟停止master上的Redis,查看Redis的主从变化,如下:

master:192.168.242.144
[root@localhost ~]# systemctl stop redis

slave-2:192.168.242.145
[root@localhost ~]# tailf /var/log/redis/sentinel.log
16759:X 19 May 2022 18:06:54.252 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
16759:X 19 May 2022 18:06:54.254 * Sentinel new configuration saved on disk
16759:X 19 May 2022 18:06:54.254 # Sentinel ID is ba4e6bd5770d4fac5284f25f491af6976756fcbe
16759:X 19 May 2022 18:06:54.254 # +monitor master mymaster 192.168.242.144 6379 quorum 2
16759:X 19 May 2022 18:06:54.258 * +slave slave 192.168.242.145:6379 192.168.242.145 6379 @ mymaster 192.168.242.144 6379
16759:X 19 May 2022 18:06:54.259 * Sentinel new configuration saved on disk
16759:X 19 May 2022 18:06:54.259 * +slave slave 192.168.242.146:6379 192.168.242.146 6379 @ mymaster 192.168.242.144 6379
16759:X 19 May 2022 18:06:54.260 * Sentinel new configuration saved on disk
16759:X 19 May 2022 18:06:57.894 * +sentinel sentinel 6e9ebf7a1cb6874e58d1f3164f996b7a0dfd2d50 192.168.242.146 26379 @ mymaster 192.168.242.144 6379
16759:X 19 May 2022 18:06:57.896 * Sentinel new configuration saved on disk
这些都是刚开始的日志文件内容,等个30秒左右


16759:X 19 May 2022 18:10:17.738 # +sdown master mymaster 192.168.242.144 6379
16759:X 19 May 2022 18:10:17.860 * Sentinel new configuration saved on disk
16759:X 19 May 2022 18:10:17.860 # +new-epoch 1
16759:X 19 May 2022 18:10:17.861 * Sentinel new configuration saved on disk
16759:X 19 May 2022 18:10:17.861 # +vote-for-leader 6e9ebf7a1cb6874e58d1f3164f996b7a0dfd2d50 1
16759:X 19 May 2022 18:10:18.762 # +config-update-from sentinel 6e9ebf7a1cb6874e58d1f3164f996b7a0dfd2d50 192.168.242.146 26379 @ mymaster 192.168.242.144 6379
16759:X 19 May 2022 18:10:18.762 # +switch-master mymaster 192.168.242.144 6379 192.168.242.146 6379
16759:X 19 May 2022 18:10:18.763 * +slave slave 192.168.242.145:6379 192.168.242.145 6379 @ mymaster 192.168.242.146 6379
16759:X 19 May 2022 18:10:18.763 * +slave slave 192.168.242.144:6379 192.168.242.144 6379 @ mymaster 192.168.242.146 6379
16759:X 19 May 2022 18:10:18.765 * Sentinel new configuration saved on disk
可以看到,日志内容显示,mymaster主服务器宕机了,将原来的主服务器mymaster192.168.242.144换为现在的192.168.242.146为新的主服务器

回到新的主服务器master上验证:

192.168.242.146:
[root@localhost ~]# redis-cli -p 26379
127.0.0.1:26379> sentinel master mymaster
 1) "name"
 2) "mymaster"
 3) "ip"
 4) "192.168.242.146"
 5) "port"
 6) "6379"

注意:

如果旧主重新加入后数据不同步解决方案:

可能之前是主节点,没有配置从节点的连接信息 如:masterauth 连接密码,当master转变为slave后,由于他没有密码,所以他不能从新的master同步数据,随之导致 info replication 的时候,同步状态为 down ,所以只需要修改 redis.conf 中的 masterauth 为 对应的密码。

只需要在旧主服务器的redis配置文件中任意地方添加masterauth (新主服务器的redis密码)

旧主服务器:192.168.242.144
[root@localhost ~]# vim /etc/redis.conf 
...
masterauth "redis"
..
重启redis,然后再验证数据是否能够同步
192.168.242.146:
[root@localhost ~]# redis-cli -a redis -h 192.168.242.146
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.242.146:6379> set zzz 456
OK

192.168.242.144:
[root@localhost ~]# redis-cli -a redis -h 192.168.242.144
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.242.144:6379> get zzz
"456"
#数据同步成功

三、Redis Cluster去中心化集群

Redis Cluster是Redis官方提供的分布式解决方案。当遇到内存、并发、流量等瓶颈是,就可以采用Cluster架构达到负载均衡目的。官方文档:https://redis.io/topics/cluster-tutorial

1、为什么要用redis-cluster集群?

1、首先redis单实例主要有单点。容量有限,流量上限的问题。

redis单点故障,可以通过主从复制replication。和自动故障转移sentinel哨兵机制。但redis单master实例提供写服务,仍然有容量和压力问题,因此需要数据分区,构建多个master实例同时提供读写服务(不仅限于从replica节点提供读服务)。

2、并发问题

redis官方声称可以达到10万/s,每秒执行10万条命令

假如业务需要每秒100万的命令执行呢?

解决方案如下

1、正确的应该是考虑分布式,加机器,把数据分布到不同的位置,分摊集中式的压力,一堆机器做一件事,还需要一定的机制保证数据分区,并且数据在各个主master节点间不能混乱,当然最好还能支持在线数据热迁移的特性。

2、什么是Redis-Cluster

为何要搭建Redis集群。Redis是在内存中保存数据的,而我们的电脑一般内存都不大,这也就意味着Redis不适合存储大数据,Redis更适合处理高并发,一台设备的存储能力是有限的,但是多台设备协同合作,就可以让内存增大很多倍,这就需要用到集群。

redis集群搭建的方式有多种,例如使用客户端分片、Twemproxy、Codis等,但从redis3.0之后版本支持redis-cluster集群,他是Redis官方提出的解决方案:

Redis-Cluster采用无中心化结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接,其中redis-cluster架构图如下:

 1、redis-cluster特点

1、所有的redis节点彼此互联(PING_PONG机制),内部使用二进制协议优化传输速度和宽带。

2、客户端与redis节点直连,不需要中间proxy层,客户端不需要连接集群所有节点,连接集群中任何一个节点即可。

3、节点的fail是通过及群众超过半数的节点检测失效时才生效。

2、redis-cluster数据分布

rediscluster集群中有16348个哈希槽,每个redis实例负责一部分slot,集群中的所有信息通过节点数据交换而更新。一个hash slot中会有很多key和value。

3、数据分布存储原理

redis集群使用数据分片(sharding)来实现:Redis集群中内置了16384个哈希槽,当需要在redis集群中放置一个key-value时。redis先对key使用crc16算法算出一个结果,然后把结果对16384求余数(集群使用公式CRC16(key)%16384),这样每个key都会对应一个编号在0-16383之间的哈希槽,那么redis就会把这个key分配到对应范围的节点上了。同样,当连接三个节点任何一个节点想要获取这个key时,也会有这样的算法,然后内部跳转到存放这个key节点上获取数据。

例如三个节点:哈希槽分布的值如下:

cluster1:0-5460

cluster2:5461-10922

cluster3:10923-16383

这种将哈希槽分布到不同节点的做法使得用户可以很容易地向集群中添加或者删除节点。比如说:

  • 如果用户将新节点D添加到集群中,那么集群只需要将节点A、B、C中的某些槽移动到节点D上就可以了。
  • 如果用户要从集群中移除节点A,那么集群只需要将节点A中的所有哈希槽移动到节点B和C,然后再移除空白(不包含任何哈希槽)的节点A就可以了

因为将一个哈希槽从一个节点移动到另一个节点不会造成节点阻塞,所以无论是添加新节点还是移除已有节点,又或者改变某个节点包含的哈希槽数量,都不会造成集群下线。

3、redis cluster 主从模式

redis cluster为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或者多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会从这个从节点选取一个来充当主节点,从而保证集群不会挂掉。

1、主从切换机制

选举过程是集群中所有master参与,如果半数以上master节点与故障点通信超过(cluster-node-timeout),认为该节点故障,自动触发故障转移操作。#故障节点对应的从节点自动升级为主节点

2、什么时候整个集群就不能用了?

如果集群任意一个主节点挂掉了,且当前主节点没有从节点,则集群无法继续,因为我们不再有办法为这个节点承担范围内的哈希槽提供服务。但是,如果这个主节点和所对应的从节点同时失败,则redis cluster无法继续运行。

4、redis cluster集群部署

环境准备:

1.准备三机器,关闭防火墙和selinux

2.制作解析并相互做解析。

注:规划架构两种方案,一种是单机多实例,这里我们采用多机器部署:

三台机器,每台机器上面两个redis实例,一个master一个slave,第一列做主库,第二列做备库

#记得选出控制节点

10.0.0.129  redis-1  7000 7001

10.0.0.130  redis-2  7002 7003

10.0.0.131  redis-3  7004 7005

三台机器做同样操作

1、安装redis

[root@redis-1 ~]# mkdir /data
[root@redis-1 ~]# yum -y install gcc automake autoconf libtool make
[root@redis-1 ~]# wget https://download.redis.io/releases/redis-6.2.0.tar.gz
[root@redis-1 ~]# tar xzvf redis-6.2.0.tar.gz -C /data/
[root@redis-1 ~]# cd /data
[root@redis-1 data]# mv redis-6.2.0 redis
[root@redis-1 data]# cd redis
[root@redis-1 redis]# make
[root@redis-1 redis]# mkdir /data/redis/data   #创建存放数据的目录

2、创建节点目录

[root@redis-1 redis]# mkdir cluster
[root@redis-1 redis]# cd cluster
[root@redis-1 cluster]# mkdir 7000 7001   #目录名字自定义,不过将实例的目录名与端口对应起来方便管理

[root@redis-2 redis]# mkdir cluster
[root@redis-2 redis]# cd cluster
[root@redis-2 cluster]# mkdir 7002 7003

[root@redis-3 redis]# mkdir cluster
[root@redis-3 redis]# cd cluster
[root@redis-3 cluster]# mkdir 7004 7005

3、先编辑好一个配置文件,然后将这个配置文件拷贝到其他节点目录中

[root@redis-1 cluster]# cp /data/redis/redis.conf 7000/
[root@redis-1 cluster]# vim 7000/redis.conf
bind 10.0.0.129  #每个实例的配置文件修改为对应节点的ip地址
port 7000   #监听端口,运行多个实例时,需要指定规划的每个实例不同的端口号
daemonize yes #redis后台运行
pidfile /var/run/redis_7000.pid #pid文件,运行多个实例时,需要指定不同的pid文件
logfile /var/log/redis_7000.log #日志文件位置,运行多实例时,需要将文件修改的不同。
dir /data/redis/data #存放数据的目录
appendonly yes #开启AOF持久化,redis会把所接收到的每一次写操作请求都追加到appendonly.aof文件中,当redis重新启动时,会从该文件恢复出之前的状态。
appendfilename "appendonly.aof"  #AOF文件名称
appendfsync everysec #表示对写操作进行累积,每秒同步一次
以下为打开注释并修改
cluster-enabled yes #启用集群
cluster-config-file nodes-7000.conf #集群配置文件,由redis自动更新,不需要手动配置,运行多实例时请注修改为对应端口
cluster-node-timeout 5000 #单位毫秒。集群节点超时时间,即集群中主从节点断开连接时间阈值,超过该值则认为主节点不可以,从节点将有可能转为master
cluster-replica-validity-factor 10 #在进行故障转移的时候全部slave都会请求申请为master,但是有些slave可能与master断开连接一段时间了导致数据过于陈旧,不应该被提升为master。该参数就是用来判断slave节点与master断线的时间是否过长。(计算方法为:cluster-node-timeout * cluster-replica-validity-factor,此处为:5000 * 10 毫秒)
cluster-migration-barrier 1 #一个主机将保持连接的最小数量的从机,以便另一个从机迁移到不再被任何从机覆盖的主机
cluster-require-full-coverage yes #集群中的所有slot(16384个)全部覆盖,才能提供服务

#注:
所有节点配置文件全部修改切记需要修改的ip、端口、pid文件...避免冲突。确保所有机器都修改。
[root@redis-1 cluster]# cp 7000/redis.conf 7001/
[root@redis-1 cluster]# vim 7001/redis.conf
bind 10.0.0.129   #这个手动修改,其他的使用%s/7000/7001/g
port 7001
daemonize yes 
pidfile /var/run/redis_7001.pid 
logfile /var/log/redis_7001.log  
cluster-config-file nodes-7001.conf
其他的不变
...
[root@redis-1 cluster]# scp 7000/redis.conf 10.0.0.130:/data/redis/cluster/7002
[root@redis-1 cluster]# scp 7000/redis.conf 10.0.0.130:/data/redis/cluster/7003
[root@redis-1 cluster]# scp 7000/redis.conf 10.0.0.130:/data/redis/cluster/7004
[root@redis-1 cluster]# scp 7000/redis.conf 10.0.0.130:/data/redis/cluster/7005
[root@redis-2 cluster]# vim 7002/redis.conf
bind 10.0.0.130   #这个手动修改,其他的使用%s/7000/7002/g
port 7002
daemonize yes 
pidfile /var/run/redis_7002.pid 
logfile /var/log/redis_7002.log  
cluster-config-file nodes-7002.conf
其他的不变
...

[root@redis-2 cluster]# vim 7003/redis.conf
bind 10.0.0.130   #这个手动修改,其他的使用%s/7000/7003/g
port 7003
daemonize yes 
pidfile /var/run/redis_7003.pid 
logfile /var/log/redis_7003.log  
cluster-config-file nodes-7003.conf
其他的不变
...
[root@redis-3 cluster]# vim 7004/redis.conf
bind 10.0.0.131   #这个手动修改,其他的使用%s/7000/7003/g
port 7004
daemonize yes 
pidfile /var/run/redis_7004.pid 
logfile /var/log/redis_7004.log  
cluster-config-file nodes-7004.conf
其他的不变
...

[root@redis-2 cluster]# vim 7005/redis.conf
bind 10.0.0.131   #这个手动修改,其他的使用%s/7000/7005/g
port 7005
daemonize yes 
pidfile /var/run/redis_7005.pid 
logfile /var/log/redis_7005.log  
cluster-config-file nodes-7005.conf
其他的不变
...

4、启动三台机器上的每个节点

[root@redis-1 ~]# cd /data/redis/src/
[root@redis-1 src]# ./redis-server ../cluster/7000/redis.conf &
[root@redis-1 src]# ./redis-server ../cluster/7001/redis.conf &

[root@redis-2 ~]# cd /data/redis/src/
[root@redis-2 src]# ./redis-server ../cluster/7002/redis.conf &
[root@redis-2 src]# ./redis-server ../cluster/7003/redis.conf &

[root@redis-3 ~]# cd /data/redis/src/
[root@redis-3 src]# ./redis-server ../cluster/7004/redis.conf &
[root@redis-3 src]# ./redis-server ../cluster/7005/redis.conf &

查看端口

 5、创建集群:在其中一个节点上操作就可以

redis节点搭建起来之后,需要完成redis cluster集群搭建,搭建集群过程中,需要保证6个redis实例都是运行状态。

redis是根据ip和port的顺序,确定master和slave,所以要排好序,再执行。

[root@redis-1 src]# ./redis-cli --cluster create --cluster-replicas 1 10.0.0.129:7000 10.0.0.129:7001 10.0.0.130:7002 10.0.0.130:7003 10.0.0.131:7004 10.0.0.131:7005 
...
Can I set the above configuration? (type 'yes' to accept): yes  #写yes同意
...
[OK] All 16384 slots covered.  完成


 6、查看集群状态可连接集群中的任一节点。此处连接了集群中的节点

# 登录集群客户端,-c标识以集群方式登录
[root@redis-3 src]# ./redis-cli -h 10.0.0.129 -c -p 7000
10.0.0.129:7000> ping
PONG
10.0.0.129:7000> cluster info   #查看集群信息
...
10.0.0.129:7000> cluster nodes   #查看集群实例
c6d68c418703daa99ae4e1d6508b8851551e9e21 10.0.0.130:7002@17002 slave 50891d2bbe5f228b7f22c32763fdc30a95f1aae3 0 1653912918005 14 connected
a99f4424e6aeb4f51069a57be141a9c7b65dfec8 10.0.0.129:7001@17001 master - 0 1653912918504 15 connected 0-1364 12288-16383
50891d2bbe5f228b7f22c32763fdc30a95f1aae3 10.0.0.131:7005@17005 master - 0 1653912918000 14 connected 6826-12287
b4f58fdba2d44fa02efe23b1fc3ee387c3159284 10.0.0.129:7000@17000 myself,master - 0 1653912919000 13 connected 1365-6825
a30d771ab57c8512304e775f337d65a2a90e85e6 10.0.0.131:7004@17004 slave a99f4424e6aeb4f51069a57be141a9c7b65dfec8 0 1653912920013 15 connected
fee769d4118fc9d7cda3f58f2bb158d2bd982c00 10.0.0.130:7003@17003 slave b4f58fdba2d44fa02efe23b1fc3ee387c3159284 0 1653912919008 13 connected

4、集群操作

1、客户端登录

[root@redis-1 src]# ./redis-cli -h 10.0.0.131 -c -p 7004
10.0.0.131:7004> set names 456
-> Redirected to slot [6659] located at 10.0.0.129:7000
OK
10.0.0.129:7000>

读
[root@redis-1 src]# ./redis-cli -h 10.0.0.130 -c -p 7003
10.0.0.130:7003> get names
-> Redirected to slot [6659] located at 10.0.0.129:7000
"456"

2、集群添加节点

准备一台新机器,修改主机名,做域名解析,其他3台机器添加这个机器的域名解析

cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.129 redis-1
10.0.0.130 redis-2
10.0.0.131 redis-3
10.0.0.132 redis-4

[root@redis-4 ~]# mkdir /data
[root@redis-4 ~]# yum -y install gcc automake autoconf libtool make
[root@redis-4 ~]# wget https://download.redis.io/releases/redis-6.2.0.tar.gz
[root@redis-4 ~]# tar xzvf redis-6.2.0.tar.gz -C /data/
[root@redis-4 ~]# cd /data/
[root@redis-4 data]# mv redis-6.2.0/ redis
[root@redis-4 data]# cd redis/
[root@redis-4 redis]# make    #编译
[root@redis-4 redis]# mkdir data  #创建数据目录
[root@redis-4 redis]# mkdir cluster
[root@redis-4 redis]# mkdir cluster/{7006,7007}  #创建集群节点

redis-1:
[root@redis-1 src]# scp /data/redis/cluster/7000/redis.conf 10.0.0.131:/data/redis/cluster/7006
[root@redis-1 src]# scp /data/redis/cluster/7000/redis.conf 10.0.0.131:/data/redis/cluster/7007

redis-4:
vim /data/redis/cluster/7006/redis.conf
vim /data/redis/cluster/7007/redis.conf
开始修改配置文件略...和之前一样,注意修改不一样的地方:端口、ip、pid文件...
启动
[root@redis-4 src]# ./redis-server ../cluster/7006/redis.conf &
[root@redis-4 src]# ./redis-server ../cluster/7007/redis.conf &

1、准备好之后开始添加节点,将cluster4添加到集群中

[root@redis-1 src]# ./redis-cli --cluster add-node 10.0.0.132:7006 10.0.0.129:7000
...
[OK] New node added correctly.

查看节点信息
./redis-cli -h 10.0.0.129 -c -p 7000
10.0.0.129:7000> cluster nodes
可以看到新增的节点

详细解释

详细解释:
runid: 该行描述的节点的id。
ip:prot: 该行描述的节点的ip和port
flags: 逗号分隔的标记位,可能的值有:
1.master: 该行描述的节点是master
2.slave: 该行描述的节点是slave
3.fail?:该行描述的节点可能不可用
4.fail:该行描述的节点不可用(故障)
master_runid: 该行描述的节点的master的id,如果本身是master则显示-
ping-sent: 最近一次发送ping的Unix时间戳,0表示未发送过
pong-recv:最近一次收到pong的Unix时间戳,0表示未收到过
config-epoch: 主从切换的次数
link-state: 连接状态,connnected 和 disconnected
hash slot: 该行描述的master中存储的key的hash的范围

2、给新节点hash槽分配

需要给新节点进行hash槽分配,这样该主节才可以存储数据,(如果有数据记得提前先将数据同步然后在从其他节点迁移槽到新节点。)

./redis-cli --cluster reshard 10.0.0.132:7006
...
How many slots do you want to move (from 1 to 16384)? 4000 #输入要分配的槽数量
What is the receiving node ID?  0aed4a95f08a8993ade091343e0267474b4b4094 #输入接收槽的节点id,通过cluster nodes 查看新增的10.0.0.132:7006 的id

Please enter all the source node IDs.
  Type 'all' to use all the nodes as source nodes for the hash slots.
  Type 'done' once you entered all the source nodes IDs.
输入: all
然后输入输入yes确认

此时再通过cluster nodes查看节点,可以看到新节点分配的槽为0-1332 5461-6794 10923-12255

3、给新添加的主节点添加对应的从节点

[root@redis-4 src]# ./redis-cli --cluster add-node 10.0.0.132:7007 10.0.0.132:7006 --cluster-slave --cluster-master-id 0aed4a95f08a8993ade091343e0267474b4b4094  #master的id
...
[OK] New node added correctly.
查看集群信息,可以看到新增接的从节点

4、平衡各个主节点的槽

任一一台机器操作
./redis-cli --cluster rebalance --cluster-threshold 1 10.0.0.129:7000
...
################################
登录测试
./redis-cli -h 10.0.0.132 -c -p 7007
10.0.0.132:7007> ping
PONG
10.0.0.132:7007> get name
-> Redirected to slot [6659] located at 10.0.0.129:7000
"456"

3、集群删除节点

#注意:这个地方需要提一下的就是:如果要下线节点6,节点7,请务必先下线从节点,并且节点6的slot的迁移到其他节点了,如果先线下节点6的话 会发产生故障切换,节点7成主节点了
在移除某个redis节点之前,首先不能在登入该节点当中,否则不能正常移除该节点。

退出所有链接的客户端,然后在任意一台机器执行
[root@redis-1 src]# ./redis-cli --cluster del-node 10.0.0.132:7007 dbad32bd47cc177de61109b96447d1f1ef6db2fc #该节点的id
...
>>> Sending CLUSTER RESET SOFT to the deleted node.
[root@redis-1 src]# ./redis-cli -h 10.0.0.129 -c -p 7000
10.0.0.129:7000> CLUSTER NODES
...可以看到7007从节点被删除

删除主节点:带有槽的节点

需要先将该主节点的槽删除,在删除之前可以先看一下该节点的槽点有多少个,然后最好平均分到其他节点上

将6节点上面的槽迁移到其他节点:
ip+port:要移除的节点
cluster-from:移除节点的id
cluster-to:接受槽主节点的id,需要将4096平均移动到不同的主节点,需要写不同接受槽的主节点id
cluster-slots:移除槽的数量

[root@redis-1 src]# ./redis-cli --cluster reshard 10.0.0.132:7006 --cluster-from 0aed4a95f08a8993ade091343e0267474b4b4094 --cluster-to 50891d2bbe5f228b7f22c32763fdc30a95f1aae3 --cluster-slots 1365 --cluster-yes

[root@redis-1 src]# ./redis-cli --cluster reshard 10.0.0.132:7006 --cluster-from 0aed4a95f08a8993ade091343e0267474b4b4094 --cluster-to b4f58fdba2d44fa02efe23b1fc3ee387c3159284 --cluster-slots 1365 --cluster-yes

[root@redis-1 src]# ./redis-cli --cluster reshard 10.0.0.132:7006 --cluster-from 0aed4a95f08a8993ade091343e0267474b4b4094 --cluster-to a30d771ab57c8512304e775f337d65a2a90e85e6 --cluster-slots 1366 --cluster-yes

然后查看节点信息,会发现7006节点上的槽为0

10.0.0.129:7000> CLUSTER nodes
如果报错:
[root@redis-1 src]# ./redis-cli --cluster del-node 10.0.0.132:7006 0aed4a95f08a8993ade091343e0267474b4b409
>>> Removing node 308320db4284c9b203aff1d3d9a145616856f681 from cluster 10.0.0.132:7006
[ERR] Node 10.0.0.132:7006 is not empty! Reshard data away and try again.

需要重新查看一下槽有没有全部移动完成。如果没有需要重新指定数量移动。这是因为还有槽不能直接移除master。

删除7006master节点

[root@redis-1 src]# ./redis-cli --cluster del-node 10.0.0.132:7006 0aed4a95f08a8993ade091343e0267474b4b409
...
>>> Sending CLUSTER RESET SOFT to the deleted node.

在查看节点信息,会发现7006节点没有了
10.0.0.129:7000> CLUSTER nodes
可以看到变成了三主三从

5、主从切换

[root@redis-3 src]# ps aux |grep redis
root       6134  0.2  0.5 164900 10084 ?        Ssl  11:28   0:42 ./redis-server 10.0.0.131:7004 [cluster]
root       6140  0.2  0.6 171044 12256 ?        Ssl  11:28   0:43 ./redis-server 10.0.0.131:7005 [cluster]
root       6808  0.0  0.0 112676   976 pts/0    R+   15:58   0:00 grep --color=auto redis
[root@redis-3 src]# kill -9 6134 
[root@redis-3 src]# ./redis-cli -h 10.0.0.129 -c -p 7000
10.0.0.129:7000> cluster nodes

 可以看到这个7004端口这个redis已经失效了

[root@redis-3 src]# ./redis-server ../cluster/7004/redis.conf &
[1] 6818
[root@redis-3 src]# 
[1]+  完成                  ./redis-server ../cluster/7004/redis.conf
[root@redis-3 src]# ./redis-cli -h 10.0.0.129 -c -p 7000
10.0.0.129:7000> cluster nodes

 可以看到该端口的redis重启后变成了7001的从节点。实现了主从切换

 redis面试问题整理

一、如何解决Redis,mysql双写一致性?
1.最经典的缓存+数据库读写的模式:
读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。
更新的时候,先更新数据库,然后再删除缓存。
2.给缓存设置过期时间,这种方案下,可以对存入缓存的数据设置过期时间,所有的写操作以数据库为准,也就是说如果数据库写成功,缓存更新失败,那么只要到达过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存。

二、缓存雪崩
数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机。
产生雪崩的简单过程:
1、redis集群大面积故障
2、缓存失效,但依然大量请求访问缓存服务redis
3、redis大量失效后,大量请求转向到mysql数据库,mysql的调用量暴增,很快就扛不住了,甚至直接宕机
4、由于大量的应用服务依赖mysql和redis的服务,这个时候很快会演变成各服务器集群的雪崩,最后网站彻底崩溃。
#解决:
1.缓存的高可用性
缓存层设计成高可用,防止缓存大面积故障。即使个别节点、个别机器、甚至是机房宕掉,依然可以提供服务,例如 Redis Sentinel 和 Redis Cluster 都实现了高可用。

2.缓存降级
可以利用ehcache等本地缓存(暂时支持),主要还是对源服务访问进行限流、资源隔离(熔断)、降级等。
当访问量剧增、服务出现问题仍然需要保证服务还是可用的。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级,这里会涉及到运维的配合。
降级的最终目的是保证核心服务可用,即使是有损的。
在进行降级之前要对系统进行梳理,比如:哪些业务是核心(必须保证),哪些业务可以容许暂时不提供服务(利用静态页面替换)等,以及配合服务器核心指标,来后设置整体。

3.Redis备份和快速预热
1)Redis数据备份和恢复
2)快速缓存预热

4.提前演练
最后,建议还是在项目上线前,演练缓存层宕掉后,应用以及后端的负载情况以及可能出现的问题,对高可用提前预演,提前发现问题。

三、缓存穿透
缓存穿透是指查询一个一不存在的数据。例如:从缓存redis没有命中,需要从mysql数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。
解决:
如果查询数据库也为空,直接设置一个默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库。设置一个过期时间或者当有值的时候将缓存中的值替换掉即可。

四、缓存并发
这里的并发指的是多个redis的client同时set key引起的并发问题。其实redis自身就是单线程操作,多个client并发操作,按照先到先执行的原则,先到的先执行,其余的阻塞。

五、缓存预热
缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。
这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!
解决:
1、直接写个缓存刷新页面,上线时手工操作下;
2、数据量不大,可以在项目启动的时候自动进行加载;
目的就是在系统上线前,将数据加载到缓存中。

其他面试:
1.Redis官方为什么不提供Windows版本?
因为目前Linux版本已经相当稳定,而且用户量很大,无需开发windows版本,反而会带来兼容性等问题。
2.一个字符串类型的值能存储最大容量是多少?
512M
3.Redis集群方案什么情况下会导致整个集群不可用?
有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用。
4.说说Redis哈希槽的概念?
Redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。
5.Redis集群之间是如何复制的?
异步复制
6.Redis集群最大节点个数是多少?
16384个。
7.Redis集群如何选择数据库?
Redis集群目前无法做数据库选择,默认在0数据库。
8.怎么测试Redis的连通性?
ping
9.如何与Redis互动?
安装服务器后,您可以运行redis安装提供的Redis客户端,也可以打开命令提示符并使用以下命令:
redis-cli
10.使用Redis有什么好处?
Redis非常快。
它支持服务器端锁定。
它有一个丰富的客户端库。
这是一个很好的反击。
它支持原子操作。
11.使用Redis有哪些缺点/限制?
它是单线程的。
它对一致哈希的客户端支持有限。
它具有很大的持久性开销。
它没有广泛部署。
12.Redis和RDBMS有什么区别?
Redis是NoSQL数据库,而RDBMS是SQL数据库。
Redis遵循键值结构,而RDBMS遵循表结构。
Redis非常快,而RDBMS相对较慢。
Redis将所有数据集存储在主存储器中,而RDBMS将其数据集存储在辅助存储器中。
Redis通常用于存储小型和常用文件,而RDBMS用于存储大文件。
Redis仅为Linux,BSD,Mac OS X,Solaris提供官方支持。它目前没有为Windows提供官方支持,而RDBMS提供对两者的支持
13.什么是redis的事务?
a)事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
b)事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
14.Redis单点吞吐量
单点TPS达到8万/秒,QPS达到10万/秒,补充下TPS和QPS的概念
1.QPS: 应用系统每秒钟最大能接受的用户访问量
每秒钟处理完请求的次数,注意这里是处理完,具体是指发出请求到服务器处理完成功返回结果。可以理解在server中有个counter,每处理一个请求加1,1秒后counter=QPS。
2.TPS: 每秒钟最大能处理的请求数
每秒钟处理完的事务次数,一个应用系统1s能完成多少事务处理,一个事务在分布式处理中,可能会对应多个请求,对于衡量单个接口服务的处理能力,用QPS比较合理。

问题2:Redis的多数据库机制,了解多少?
正常:Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,单机下的redis可以支持16个数据库(db0 ~ db15)
集群: 在Redis Cluster集群架构下只有一个数据库空间,即db0。因此,我们没有使用Redis的多数据库功能!

问题3:Redis集群机制中,你觉得有什么不足的地方吗?
假设我有一个key,对应的value是Hash类型的。如果Hash对象非常大,是不支持映射到不同节点的!只能映射到集群中的一个节点上!还有就是做批量操作比较麻烦!

问题4:懂Redis的批量操作么?
正常: 比如mset、mget操作等
集群: 我们在生产上采用的是Redis Cluster集群架构,不同的key会划分到不同的slot中,因此直接使用mset或者mget等操作是行不通的。

问题6:你们有对Redis做读写分离么?
正常:没有做
集群:不做读写分离。我们用的是Redis Cluster的架构,是属于分片集群的架构。而redis本身在内存上操作,不会涉及IO吞吐,即使读写分离也不会提升太多性能,Redis在生产上的主要问题是考虑容量,单机最多10-20G,key太多降低redis性能.因此采用分片集群结构,已经能保证了我们的性能。其次,用上了读写分离后,还要考虑主从一致性,主从延迟等问题,徒增业务复杂度。

​​​​​​​elk相关面试

1.ELK能做什么?
ELK组件在海量日志系统的运维中,可用于解决:
分布式日志数据集中式查询和管理
系统监控,包含系统硬件和应用各个组件的监控
故障排查
安全信息和事件管理
报表功能

2.ES与关系数据库对比
在 ES 中,文档归属于一种 类型 (type) ,而这些类型存在于索引 (index) 中,类比传统关系型数据库
DB -> Databases -> Tables -> Rows -> Columns
关系型      数据库          表            行              列  

ES -> Indices   -> Types  -> Documents -> Fields
ES       索引            类型            文档           域(字段)

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值