当前位置: 首页 > news >正文

Redis (三)

1、redis复制

        简单的概括就是主从复制,master以写为主,Slave以读为主,当master数据发生变化的时候,自动将更新的数据异步同步到其他的slave是数据库。

        使用这种机制的话,可以做到读写分离,可以减轻主机负担。使用这种方式的话可以容灾恢复,就是如果主机挂掉了。还有其他的数据备份,而且数据也是实时的。所以宕机的时候多啦保证!数据备份以及水平扩容支持高并发。

        配置从库不配置主库,对于权限信息,如果master配置了密码,需要密码才可以登录,那么slave就需要配置masterauth来设置校验的密码,否则的话master就会拒绝slave的访问请求。

1.1、相关命令

  • 使用info replication

    1. 可以查看复制节点的主从关系和配置信息

  • replicaof 主库ip 主库端口

    1. 配置在从机的配置文件中,配置主机的数据

  • slaveof 主库ip 主库端口

    1. 每次与master断开之后,都需要重新连接,除非你配置进redis.conf文件

    2. 在运行期间修改slave节点的信息,如果该数据库已经是某个主数据库的从数据库,那么会停止和原主数据库的同步关系,转而和新的主数据库同步

  • slaveof no one

    1. 使当前数据库停止与其他数据库的同步,转成主数据库,自立为王

1.2、配置

        一个master,然后两个slave,也讲就是说,需要三台虚拟机然而且每一个虚拟机上都安装redis,当然这只是基础的配置条件,然后接下来就是实现这种模式的具体配置。注意要给关闭每一个虚拟机的防火墙。

开启daemonize

daemonize yes

修改ip

bind 192.168.200.88 -::1

protected-mode

protected-mode no

指定端口

port 6379

指定当前的工作目录

dir /software/redis/redis-7.2.3/redisconf/backupfiles

pid文件名字,pidfile

pidfile /var/run/redis_6379.pid

log文件名字

logfile /software/redis/redislog/redis-log.log

本机密码

requirepass 123456

dump.rdb文件名字

dbfilename dump88.rdb

aof文件,appendfilename

暂时不开启

主机密码

replicaof 192.168.200.88 6379
masterauth "10100109"

1.2.1、主从复制

三台linux虚拟机,然后安装配置完成后正常启动连接!

查看主机日志文件如下

26152:M 04 Jan 2024 17:57:06.501 * Synchronization with replica 192.168.200.111:6380 succeeded
26152:M 04 Jan 2024 17:59:59.525 * Replica 192.168.200.99:6380 asks for synchronization
26152:M 04 Jan 2024 17:59:59.525 * Full resync requested by replica 192.168.200.99:6380
26152:M 04 Jan 2024 17:59:59.525 * Delay next BGSAVE for diskless SYNC
​
26152:M 04 Jan 2024 18:00:04.517 * Synchronization with replica 192.168.200.99:6380 succeeded
26152:M 04 Jan 2024 18:04:57.044 * Connection with replica 192.168.200.111:6380 lost.
26152:M 04 Jan 2024 18:05:12.186 * Replica 192.168.200.111:6381 asks for synchronization
26152:M 04 Jan 2024 18:05:12.187 * Partial resynchronization request from 192.168.200.111:6381 accepted. Sending 14 bytes of backlog starting from offset 673.

查看从机日志

6107:S 04 Jan 2024 18:05:12.189 * Ready to accept connections tcp
6107:S 04 Jan 2024 18:05:12.190 * Connecting to MASTER 192.168.200.88:6379
6107:S 04 Jan 2024 18:05:12.190 * MASTER <-> REPLICA sync started
6107:S 04 Jan 2024 18:05:12.190 * Non blocking connect for SYNC fired the event.
6107:S 04 Jan 2024 18:05:12.191 * Master replied to PING, replication can continue...
 

主机查看配置info replication

> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.200.99,port=6380,state=online,offset=1624,lag=0
slave1:ip=192.168.200.111,port=6381,state=online,offset=1624,lag=0
master_failover_state:no-failover
master_replid:ad3197cb5b7476962c1243102b7a135a8cfe83d5
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1624
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1624

从机查看配置,info replication

> info replication
# Replication
role:slave
master_host:192.168.200.88
master_port:6379
master_link_status:up
master_last_io_seconds_ago:10
master_sync_in_progress:0
slave_read_repl_offset:1820
slave_repl_offset:1820
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:ad3197cb5b7476962c1243102b7a135a8cfe83d5
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1820
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:267
repl_backlog_histlen:1554

测试

#主机
> set k1 v1
OK
​
#从机
> get k1
v1
​
> get k1
v1
​
1.2.1.1、总结

        配置过的从机是只能执行读操作,不能执行写操作,这样以来可以实现读写分离提高性能。

#从机写入
> set k2 v2
READONLY You can't write against a read only replica.

        假设主机启动后然后执行了多次的写操作后从机才启动,那么从机可以读取之前的写入的数据嘛,是这样的从机第一次启动的话会备份主机的之前的所有的数据做到同步,然后对于后续的主机的写操作同步的更新。

#主机写
> Linux-master-redis connected!
> set k2 v2
OK
> set k3 v3
OK
​
#启动从机,访问数据正常
> linux-111-6381 connected!
> get k2
v2
> get k3
v3

        主机宕机的话会出现什么操作,是从机变主机?数据读取失败?是这样的从机还是老老实实的做从机,等待主机恢复,而且读取数据正常没有影响。

#主机宕机
shutdown
​
#从机读写
> get k1
v1
> set k4 v4
READONLY You can't write against a read only replica.

        主机重启不影响之前建立的关系

#主机
> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.200.111,port=6381,state=online,offset=10316,lag=1
slave1:ip=192.168.200.99,port=6380,state=online,offset=10316,lag=0
master_failover_state:no-failover
master_replid:0fc82d3e3251195aec8a42cc1b350b54a5435054
master_replid2:ad3197cb5b7476962c1243102b7a135a8cfe83d5
master_repl_offset:10316
second_repl_offset:10289
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:10289
repl_backlog_histlen:28
> set k4 v4
OK
​
#从机读取
> get k4
v4

        欧克,上面是使用配置文件的方式来使用,也就是写死的这种情况,但是我们还有可以使用命令的方式来进行配置,接下来停掉两个从机,然后注释掉之前的配置文件,然后测试不同的情况。

# replicaof 192.168.200.88 6379

        重启后查看主从配置

#三台都是主机!
> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:c69b05376562297a6868fc0311814cb9d0233331
master_replid2:0fc82d3e3251195aec8a42cc1b350b54a5435054
master_repl_offset:12174
second_repl_offset:12175
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:12175
repl_backlog_histlen:0

        好滴,指定主机使用命令,发现连接以后数据同步!

#从机执行
SLAVEOF 192.168.200.88 6379

        测试关机后的从机,重启后使用主从关系命令设置后,关系失效,也就是说使用命令的方式的话是临时的,只有使用配置文件的话是可以永久生效的。

1.2.2、叠叠乐

        这个不看也大致可以猜出来就是,一个主机的从机可以是另外一个从机的主机!也就是说即使是从机也可以接受其他的从机的连接以及数据同步,这样的话可以分担主机的写压力!为了方便演示就不在使用配置文件了,采用命令的方式使用比较方便。

#主机
192.168.200.88 
​
#从机 ————主机
192.168.200.99
​
#从机
192.168.200.111
​
#欧克当我连接完毕后发现数据已经同步完成,接下来测试不同的情况
​
#主机写看从机的从机的数据同步
> set k5 v5
OK
​
> SLAVEOF 192.168.200.88 6379
OK
> get k5
v5
​
> SLAVEOF 192.168.200.99  6380
OK
> get k5
v5
​
#对于从机的从机来讲,从机也是主机(哈哈哈),那么他可以写嘛
> set k6 v6
READONLY You can't write against a read only replica.
​
​
#主机挂了,从机的从机可以写嘛,不可以,但是可以读!
> linux-99-6380 connected!
> get k1
v1
> set k6 v6
READONLY You can't write against a read only replica.

1.2.3、自立门户

        使用命令可以,然当前的redis服务器脱离主从关系,变为主机。

> linux-111-6381 connected!
> SLAVEOF no one
OK
> set k6 v6
OK

1.3、总结

1.3.1、工作模式

        slave启动成功连接master后会发送一个同步的命令,然后对于初次连接的话,slave会将master中的数据全部复制copy,做到数据的同步,然后salve自身原有的数据会被master数据覆盖清除。

首次连接、全量复制

        master节点收到sync命令后会开始在后台保存快照(即RDB持久化,主从复制时会触发RDB),同时收集所有接收到的用于修改数据集命令缓存起来,master节点执行RDB持久化完后,master将rdb快照文件和所有缓存的命令发送到所有slave,以完成一次完全同步,而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中,从而完成复制初始化。

心跳持续、保持通信

        master发出PING包的周期,默认是10秒

repl-ping-replica-period 10

进入平稳、增量复制

        Master继续将新的所有收集到的修改命令自动依次传给slave,完成同步。

从机下线,重连续传

        master会检查backlog里面的offset,master和slave都会保存一个复制的offset还有一个masterId,offset是保存在backlog中的。Master只会把已经复制的offset后面的数据复制给Slave,类似断点续传。

1.3.2、缺点

        复制延时,信号衰减,大概的意思就是,要满足高可用的方式工作的话,需要在一个主机上挂载很多的从机,数据在同步的时候会有演示,从机越多问题越明显。

        由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。

主机挂掉,从机还是只能读,直到主机重启。(无人值守---哨兵)

2、哨兵模式

        哨兵模式就是可以监控redis的运行状态呢,然后如果主机发生了故障会根据投票数自动将某一个从库转换成为新的主库,然后对外提供服务。不在需要人工的干预。

2.1、哨兵模式功能

  • 主从监控:可以监控主机和从机的运行状态是不是正常

  • 消息通知:哨兵可以将故障转移的结果发送给客户端

  • 故障转移:如果master异常,那么会进行主从的切换,将其中的一个slave作为新的master

  • 配置中心:客户端通过连接哨兵来获得当前的redis服务的主节点的地址

2.2、哨兵模式架构

        首先要说明为什么要用哨兵的集群(奇数防止投票数一样的情况。)呐,第一点就是,只配置一个哨兵,那么哨兵挂掉后,然后主机也挂掉,那么整个哨兵模式就白搭了。所以配置集群可以避免这中情况,第二点就是防止专断,就是如果主机只是因为网络延时导致哨兵判断失误,然后将当前的主机判定为挂掉重新选举主机,多台可以投票判断(民主方式)。

2.2.1、配置方式

        上面是我们的redis.conf文件,然后就是按照上面的架构模式配置的话,要配置六台虚拟机,直接把电脑撑爆,太离谱没钱加装内存条!首先不建议直接在原配置文件上修改,所以还是和之前一样将原配置文件复制到指定的文件夹然后配置。

[root@localhost redis-7.2.3]# cp sentinel.conf /software/redis/redis-7.2.3/redisconf/sentinel.conf

        除了配置和配置redis.conf的基础配置项之外,还要配置额外的如下配置

首先在sentinel.conf配置参数,除了配置主从复制的参数之外,然后还有加上监视的主机的信息

sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 192.168.111.169 6379 2
设置要监控的master服务器,quorum表示最少有几个哨兵认可客观下线,同意故障迁移的法定票数。

        quorum:确认客观下线的最少的哨兵数量,只有哨兵的投票数大于这个最小的数量的时候才会确认这个主机挂掉了,我们知道,网络是不可靠的,有时候一个sentinel会因为网络堵塞而误以为一个master redis已经死掉了,在sentinel集群环境下需要多个sentinel互相沟通来确认某个master是否真的死了,quorum这个参数是进行客观下线的一个依据,意思是至少有quorum个sentinel认为这个master有故障,才会对这个master进行下线以及故障转移。因为有的时候,某个sentinel节点可能因为自身网络原因,导致无法连接master,而此时master并没有出现故障,所以,这就需要多个sentinel都一致认为该master有问题,才可以进行下一步操作,这就保证了公平性和高可用。

配置监视主机的密码,master设置了密码,连接master服务的密码

sentinel auth-pass <master-name> <password>     
sentinel auth-pass mymaster 111111

指定多少毫秒之后,主节点没有应答哨兵,此时哨兵主观上认为主节点下线

sentinel down-after-milliseconds <master-name> <milliseconds>

配置表示允许并行同步的slave个数,当Master挂了后,哨兵会选出新的Master,此时,剩余的slave会向新的master发起同步数据

sentinel parallel-syncs <master-name> <nums>

故障转移的超时时间,进行故障转移时,如果超过设置的毫秒,表示故障转移失败

sentinel failover-timeout <master-name> <milliseconds>

配置当某一事件发生时所需要执行的脚本

sentinel notification-script <master-name> <script-path> 

客户端重新配置主节点参数脚本

sentinel client-reconfig-script <master-name> <script-path>

样板:

bind 0.0.0.0
daemonize yes
protected-mode no
port 26381
logfile "/myredis/sentinel26381.log"
pidfile /var/run/redis-sentinel26381.pid
dir "/myredis"
sentinel monitor mymaster 192.168.111.169 6379 2
sentinel auth-pass mymaster 111111 
#主机以及哨兵
root      22727      1  0 22:23 ?        00:00:00 redis-server 192.168.200.88:6379
root      26236      1  1 22:26 ?        00:00:00 redis-sentinel 192.168.200.88:26379 [sentinel]
​
#从机以及哨兵
[root@localhost sentinel]# ps -ef|grep redis|grep -v grep
root      22745      1  0 22:23 ?        00:00:00 redis-server 192.168.200.99:6379
root      26484      1  0 22:26 ?        00:00:00 redis-sentinel 192.168.200.99:26379 [sentinel]
​
[root@jiangyiqing sentinel]# ps -ef|grep redis|grep -v grep
root      22486      1  0 22:23 ?        00:00:00 redis-server 192.168.200.111:6379
root      26571      1  1 22:26 ?        00:00:00 redis-sentinel 192.168.200.111:26379 [sentinel]

条件有限只能这样演示数据!

查看哨兵日志,发现一切正常你,三个哨兵构成集群。

#启动后测试主从正常,然后测试主机挂掉,然后使用命令哪一个从机会成为主机
​
#首先查看数据没有问题
> get k1
v1
​
#然后随机挑选从机查看状态是不是选举出来新的主机
> info replication
# Replication
role:slave
master_host:192.168.200.99
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_read_repl_offset:250240
slave_repl_offset:250240
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:85db2fa7fc5bf6864636b8a376da63f06e4ea4e3
master_replid2:e43a6c37a2ce62bdf26cbff3113e9b735518c7fe
master_repl_offset:250240
second_repl_offset:250076
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:477
repl_backlog_histlen:249764
​
#发现主机的ip已经跟换,然后说明配置的哨兵模式起作用
​
#测试在新选举的主机上写操作
> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.200.111,port=6379,state=online,offset=295068,lag=1
master_failover_state:no-failover
master_replid:85db2fa7fc5bf6864636b8a376da63f06e4ea4e3
master_replid2:e43a6c37a2ce62bdf26cbff3113e9b735518c7fe
master_repl_offset:295209
second_repl_offset:250076
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:218877
repl_backlog_histlen:76333
> set k2 v2
OK
​
#测试从机读取
> get k2
v2
​
#测试之前挂掉的主机重启后,谁是master
> info replication
# Replication
role:slave
master_host:192.168.200.99
master_port:6379
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_read_repl_offset:252218
slave_repl_offset:252218
master_link_down_since_seconds:-1
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:fefb137f28d435ed43656ac31e88e94e66be09c6
master_replid2:e43a6c37a2ce62bdf26cbff3113e9b735518c7fe
master_repl_offset:252218
second_repl_offset:250076
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:250076
repl_backlog_histlen:2143
#很明显之前的主机启动后并没有成为master而是成为slave,但是不知道为什么,刚刚用新产生的master做了一次写操作,然后另外的从机可以读取,但是对于刚启动的挂掉的主机却读取不到数据!!
​
> get k2
null

测试挂掉的烧饼日志

2.3、工作流程

        当一个主从配置中的master失效之后,sentinel可以选举出一个新的master,用于自动接替原master的工作,主从配置中的其他redis服务器自动指向新的master同步数据。一般建议sentinel采取奇数台,防止某一台sentinel无法连接到master导致误切换。

        首先按照配置好的redis的哨兵框架,哨兵正常的监视着主机的状态,但是突然有一天...

2.3.1、SDown主观下线

        所谓主观下线(Subjectively Down, 简称 SDOWN)指的是单个Sentinel实例对服务器做出的下线判断,即单个sentinel认为某个服务下线(有可能是接收不到订阅,之间的网络不通等等原因)。主观下线就是说如果服务器在[sentinel down-after-milliseconds]给定的毫秒数之内没有回应PING命令或者返回一个错误消息, 那么这个Sentinel会主观的(单方面的)认为这个master不可以用了,o(╥﹏╥)o

        sentinel配置文件中的down-after-milliseconds设置了判断主观下线的时间长度。表示master被当前sentinel实例认定为失效的间隔时间,这个配置其实就是进行主观下线的一个依据,master在多长时间内一直没有给Sentine返回有效信息,则认定该master主观下线。也就是说如果多久没联系上redis-servevr,认为这个redis-server进入到失效(SDOWN)状态。

        那么多哨兵就你一个说不行就不行,肯定是不可以的!

2.3.2、ODown客观下线

        ODOWN需要一定数量的sentinel,多个哨兵达成一致意见才能认为一个master客观上已经宕掉。( 民主决议,少数服从多数!),这里就使用到了quorum参数,投个票吧,然后看赞同宕机的有多少,如果大于quorum参数就可以认主机宕机啦,意思是至少有quorum个sentinel认为这个master有故障才会对这个master进行下线以及故障转移。因为有的时候,某个sentinel节点可能因为自身网络原因导致无法连接master,而此时master并没有出现故障,所以这就需要多个sentinel都一致认为该master有问题,才可以进行下一步操作,这就保证了公平性和高可用。

        好好好,也知道主机是宕机啦,那要选出一个主机吧,那么多兵,你说这个,我说那个!难搞

2.3.3、哨兵兵王

        当主节点被判断客观下线以后,各个哨兵节点会进行协商,先选举出一个领导者哨兵节点(兵王)并由该领导者节点,也即被选举出的兵王进行failover(故障迁移)。怎么说,谁是兵王,投个票吧!

        选出领导者使用的是Raft算法!监视该主节点的所有哨兵都有可能被选为领导者,选举使用的算法是Raft算法;Raft算法的基本思路是先到先得

        即在一轮选举中,哨兵A向B发送成为领导者的申请,如果B没有同意过其他哨兵,则会同意A成为领导者

        欧克,兵王有啦,该解决问题了叭

2.3.4、故障迁移
2.3.4.1、新主登基

        兵王选出来一个slave成为master,好嘛,有什么规则嘛,别不明不白的就选了!

  • redis.conf文件中,优先级slave-priority或者replica-priority最高的从节点(数字越小优先级越高 )

  • 复制偏移位置offset最大的从节点,就是谁的数据更接近master的数据

  • 最小Run ID的从节点,字典顺序ASCII码

2.3.4.2、群臣俯首

        执行slaveof no one命令让选出来的从节点成为新的主节点,并通过slaveof命令让其他节点成为其从节点,Sentinel leader会对选举出的新master执行slaveof no one操作,将其提升为master节点。Sentinel leader向其它slave发送命令,让剩余的slave成为新的master节点的slave。

2.3.4.3、旧主臣服

        将之前已下线的老master设置为新选出的新master的从节点,当老master重新上线后,它会成为新master的从节点,Sentinel leader会让原来的master降级为slave并恢复正常工作。

        欧克,看这工作量还挺多,哨兵来完成不需要人工干预。

3、redis集群

        首先为了高并发提高性能,引入读写分离也就是主从复制,然后中间考虑到主机宕机的问题,从机无动于衷干等着主机恢复,为了这个问题提出哨兵模式,哨兵模式的引入可以解决主机宕机后的故障迁移,配置新的主机来完成写的任务,但事实上我们从头到尾还是只有一台主机,写的压力也太大。

        由于数据量过大,单个Master复制集难以承担,因此需要对多个复制集进行集群,形成水平扩展每个复制集只负责存储整个数据集的一部分,这就是Redis的集群,其作用是提供在多个Redis节点间共享数据的程序集。

        redis集群支持多个master,每一个mater有可以挂载多个slave,然后这样的话就可以实现,读写分离、指出数据的高可用以及支持海量的数据的读写存储操作,同时由于cluster自带Sentine的故障转移机制,内置了高可用的支持,无需再使用哨兵功能。而且客户端和redis的节点的连接,不在需要连接集群中所有的节点,只需要任意连接集群中的一个节点基于可以,槽位slot负责分配到给各个物理服务器节点,有对对应的集群来负责维护节点、插槽和数据之间的关系。

3.1、槽位Slot、分片

3.1.1、槽位

        redis集群没有使用一致性hash,而是引入了哈希槽的概念,redis集群有16384个哈希槽,每一个key通过CRC16

        校验后对16384取模来决定放置哪个槽,集群的每一个节点负责一部分的hash槽,如果集群有三个节点:

3.1.2、分片

        分片是什么?使用Redis集群时我们会将存储的数据分散到多台redis机器上,这称为分片。简言之,集群中的每个Redis实例都被认为是整个数据的一个分片。

        如何找到给定key的分片,为了找到给定key的分片,我们对key进行CRC16(key)算法处理并通过对总分片数量取模。然后,使用确定性哈希函数,这意味着给定的key将多次始终映射到同一个分片,我们可以推断将来读取特定key的位置。

3.1.3、优势

        最大优势,方便扩缩容和数据分派查找。这种结构很容易添加或者删除节点,比如如果我想新添加个节点D,我需要从节点 A、B、C中得部分槽到D上,如果我想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可。由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态。

3.1.4、slot槽位映射的方式
3.1.4.1哈希取余分区

3.1.4.1.1、优点:

        简单粗暴,直接有效,只需要预估好数据规划好节点,例如3台、8台、10台,就能保证一段时间的数据支撑。使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求(并维护这些请求的信息),起到负载均衡+分而治之的作用。

3.1.4.1.2、缺点:

        原来规划好的节点,进行扩容或者缩容就比较麻烦了,不管扩缩,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化:Hash(key)/3会变成Hash(key) /?。此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。

        某个redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。

3.1.4.2、一致性hash算法分区

        设计目标是为了解决分布式缓存数据变动和映射问题,某个机器宕机了,分母数量改变了,自然取余数不OK了。提出一致性Hash解决方案。目的是当服务器个数发生变动时,尽量减少影响客户端到服务器的映射关系。

3.1.4.2.1、一致性hash环
    一致性哈希算法必然有个hash函数并按照算法产生hash值,这个算法的所有可能哈希值会构成一个全量集,这个集合可以成为一个hash空间[0,2^32-1],这个是一个线性空间,但是在算法中,我们通过适当的逻辑控制将它首尾相连(0 = 2^32),这样让它逻辑上形成了一个环形空间。

        它也是按照使用取模的方法,前面笔记介绍的节点取模法是对节点(服务器)的数量进行取模。而一致性Hash算法是对2^32取模,简单来说,一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-2^32-1(即哈希值是一个32位无符号整形),整个哈希环如下图:

        整个空间按顺时针方向组织,圆环的正上方的点代表0,0点右侧的第一个点代表1,以此类推,2、3、4、……直到2^32-1,也就是说0点左侧的第一个点代表2^32-1, 0和2^32-1在零点中方向重合,我们把这个由2^32个点组成的圆环称为Hash环。

3.1.4.2.2、节点映射

        将集群中各个IP节点映射到环上的某一个位置。将各个服务器使用Hash进行一个哈希,具体可以选择服务器的IP或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。假如4个节点NodeA、B、C、D,经过IP地址的哈希函数计算(hash(ip)),使用IP地址哈希后在环空间的位置如下:

3.1.4.2.3、key的存储位置

        当我们需要存储一个kv键值对时,首先计算key的hash值,hash(key),将这个key使用相同的函数Hash计算出哈希值并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器,并将该键值对存储在该节点上。

        如我们有Object A、Object B、Object C、Object D四个数据对象,经过哈希计算后,在环空间上的位置如下:根据一致性Hash算法,数据A会被定为到Node A上,B被定为到Node B上,C被定为到Node C上,D被定为到Node D上。

3.1.4.2.4、优点

容错性

        假设Node C宕机,可以看到此时对象A、B、D不会受到影响。一般的,在一致性Hash算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。简单说,就是C挂了,受到影响的只是B、C之间的数据且这些数据会转移到D进行存储。

扩展性

        数据量增加了,需要增加一台节点NodeX,X的位置在A和B之间,那收到影响的也就是A到X之间的数据,重新把A到X的数据录入到X上即可,不会导致hash取余全部数据重新洗牌。

3.1.4.2.5、缺点

Hash环的数据倾斜问题

        一致性Hash算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题,

例如系统中只有两台服务器:

        为了在节点数目发生改变时尽可能少的迁移数据,将所有的存储节点排列在收尾相接的Hash环上,每个key在计算Hash后会顺时针找到临近的存储节点存放。而当有节点加入或退出时仅影响该节点在Hash环上顺时针相邻的后续节点。 这样的结构在加入和删除节点只影响哈希环中顺时针方向的相邻的节点,对其他节点无影响。但是由于数据的分布和节点的位置有关,因为这些节点不是均匀的分布在哈希环上的,所以数据在进行存储时达不到均匀分布的效果。

3.1.4.3、哈希槽分区

        首先哈希槽可以解决一致性哈希算法当节点数量少的时候,导致的数据分布不均匀的情况,哈希槽的实质就是一个数组,[0-2^14-1]形成一个hash slot空间。

        解决均匀分配的问题,在数据和节点之间又加入了一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系,现在就相当于节点上放的是槽,槽里放的是数据。

        槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配

                一个集群只能有16384个槽,编号0-16383(0-2^14-1)。这些槽会分配给集群中的所有主节点,分配策略没有要求。

        集群会记录节点和槽的对应关系,解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取模,余数是几key就落入对应的槽里。HASH_SLOT = CRC16(key) mod 16384。以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。

相关文章:

Redis (三)

1、redis复制 简单的概括就是主从复制&#xff0c;master以写为主&#xff0c;Slave以读为主&#xff0c;当master数据发生变化的时候&#xff0c;自动将更新的数据异步同步到其他的slave是数据库。 使用这种机制的话&#xff0c;可以做到读写分离&#xff0c;可以减轻主机负担…...

CompletableFuture超详解与实践

0.背景 一个接口可能需要调用 N 个其他服务的接口&#xff0c;这在项目开发中还是挺常见的。举个例子&#xff1a;用户请求获取订单信息&#xff0c;可能需要调用用户信息、商品详情、物流信息、商品推荐等接口&#xff0c;最后再汇总数据统一返回。 如果是串行&#xff08;按…...

Maven之私服

1 介绍 团队开发现状分析私服是一台独立的服务器&#xff0c;用于解决团队内部的资源共享与资源同步问题Nexus Sonatype公司的一款maven私服产品 下载地址&#xff1a;https://help.sonatype.com/repomanager3/download win版安装包&#xff1a;https://pan.baidu.com/s/1wk…...

#define宏定义的初探

前言&#xff1a; 最基本的#define定义方式 #define可以定义宏&#xff0c;这点相信大家并不陌生&#xff0c;其定义的方式十分简单&#xff0c;给大家随便来一个最简单、最基础的定义方式看看&#xff1a; #include<stdio.h> #define a 3 int main() { printf(&quo…...

机器学习 -决策树的案例

场景 我们对决策树的基本概念和算法其实已经有过了解&#xff0c;那我们如何利用决策树解决问题呢&#xff1f; 构建决策树 数据准备 我们准备了一些数据如下&#xff1a; # 定义新的数据集 new_dataSet [[晴朗, 是, 高, 是],[雨天, 否, 低, 否],[阴天, 是, 中, 是],[晴朗…...

04、Kafka ------ 各个功能的作用解释(Cluster、集群、Broker、位移主题、复制因子、领导者副本、主题)

目录 启动命令&#xff1a;CMAK的用法★ 在CMAK中添加 Cluster★ 在CMAK中查看指定集群★ 在CMAK中查看 Broker★ 位移主题★ 复制因子★ 领导者副本和追随者副本★ 查看主题 启动命令&#xff1a; 1、启动 zookeeper 服务器端 小黑窗输入命令&#xff1a; zkServer 2、启动 …...

1、C语言:数据类型/运算符与表达式

数据类型/运算符/表达式 1.数据类型与长度2.常量3.声明4. 运算符5. 表达式 1.数据类型与长度 基本数据类型 类型说明char字符型&#xff0c;占用一个字节&#xff0c;可以存放本地字符集中的一个字符int整型&#xff0c;通常反映了所有机器中整数的最自然长度float单精度浮点…...

[ffmpeg系列 03] 文件、流地址(视频)解码为YUV

一 代码 ffmpeg版本5.1.2&#xff0c;dll是&#xff1a;ffmpeg-5.1.2-full_build-shared。x64的。 文件、流地址对使用者来说是一样。 流地址(RTMP、HTTP-FLV、RTSP等)&#xff1a;信令完成后&#xff0c;才进行音视频传输。信令包括音视频格式、参数等协商。 接流的在实际…...

python算法每日一练:连续子数组的最大和

这是一道关于动态规划的算法题&#xff1a; 题目描述&#xff1a; 给定一个整数数组 nums&#xff0c;请找出该数组中连续子数组的最大和&#xff0c;并返回这个最大和。 示例&#xff1a; 输入&#xff1a;[-2, 1, -3, 4, -1, 2, 1, -5, 4] 输出&#xff1a;6 解释&#xff…...

一个vue3的tree组件

https://download.csdn.net/download/weixin_41012767/88709466...

新手练习项目 4:简易2048游戏的实现(C++)

名人说&#xff1a;莫听穿林打叶声&#xff0c;何妨吟啸且徐行。—— 苏轼《定风波莫听穿林打叶声》 Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#xff09; 目录 一、效果图二、代码&#xff08;带注释&#xff09;三、说明 一、效果图 二、代码&#xff08;带…...

2023年度总结:技术沉淀、持续学习

2023年度总结&#xff1a;技术沉淀、持续学习 一、引言 今年是我毕业的第二个年头&#xff0c;也是完整的一年&#xff0c;到了做年终总结的时候了 这一年谈了女朋友&#xff0c;学习了不少技术&#xff0c;是充实且美好的一年&#xff01; 首先先看年初定的小目标&#xf…...

Unity 利用UGUI之Slider制作进度条

在Unity中使用Slider和Text组件可以制作简单的进度条。 首先在场景中右键->UI->Slider&#xff0c;新建一个Slider组件&#xff1a; 同样方法新建一个Text组件&#xff0c;最终如图&#xff1a; 创建一个进度模拟脚本&#xff0c;Slider_Progressbar.cs using System.C…...

OCS2 入门教程(四)- 机器人示例

系列文章目录 前言 OCS2 包含多个机器人示例。我们在此简要讨论每个示例的主要特点。 System State Dim. Input Dim. Constrained Caching Double Integrator 2 1 No No Cartpole 4 1 Yes No Ballbot 10 3 No No Quadrotor 12 4 No No Mobile Manipul…...

FreeRTOS学习第6篇–任务状态挂起恢复删除等操作

目录 FreeRTOS学习第6篇--任务状态挂起恢复删除等操作任务的状态设计实验IRReceiver_Task任务相关代码片段实验现象本文中使用的测试工程 FreeRTOS学习第6篇–任务状态挂起恢复删除等操作 本文目标&#xff1a;学习与使用FreeRTOS中的几项操作&#xff0c;有挂起恢复删除等操作…...

BLE Mesh蓝牙组网技术详细解析之Access Layer访问层(六)

目录 一、什么是BLE Mesh Access Layer访问层&#xff1f; 二、Access payload 2.1 Opcode 三、Access layer behavior 3.1 Access layer发送消息的流程 3.2 Access layer接收消息的流程 3.3 Unacknowledged and acknowledged messages 3.3.1 Unacknowledged message …...

Netlink 通信机制

文章目录 前言一、Netlink 介绍二、示例代码参考资料 前言 一、Netlink 介绍 Netlink套接字是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC) ,也是网络应用程序与内核通信的最常用的接口。 在Linux 内核中&#xff0c;使用netlink 进行应用与内核通信的应用有…...

2024.1.8每日一题

LeetCode 回旋镖的数量 447. 回旋镖的数量 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定平面上 n 对 互不相同 的点 points &#xff0c;其中 points[i] [xi, yi] 。回旋镖 是由点 (i, j, k) 表示的元组 &#xff0c;其中 i 和 j 之间的距离和 i 和 k 之间的欧式…...

看了致远OA的表单设计后的思考

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; https://gitee.com/nbacheng/n…...

mmdetection训练自己的数据集

mmdetection训练自己的数据集 这里写目录标题 mmdetection训练自己的数据集一&#xff1a; 环境搭建二&#xff1a;数据集格式转换(yolo转coco格式)yolo数据集格式coco数据集格式yolo转coco数据集格式yolo转coco数据集格式的代码 三&#xff1a; 训练dataset数据文件配置config…...

MySQL取出N列里最大or最小的一个数据

如题&#xff0c;现在有3列&#xff0c;都是数字类型&#xff0c;要取出这3列里最大或最小的的一个数字 -- N列取最小 SELECT LEAST(temperature_a,temperature_b,temperature_c) min FROM infrared_heat-- N列取最大 SELECT GREATEST(temperature_a,temperature_b,temperat…...

编写.NET的Dockerfile文件构建镜像

创建一个WebApi项目&#xff0c;并且创建一个Dockerfile空文件&#xff0c;添加以下代码&#xff0c;7.0代表的你项目使用的SDK的版本&#xff0c;构建的时候也需要选择好指定的镜像tag FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443F…...

【C语言】浙大版C语言程序设计(第三版) 练习7-4 找出不是两个数组共有的元素

前言 最近在学习浙大版的《C语言程序设计》&#xff08;第三版&#xff09;教材&#xff0c;同步在PTA平台上做对应的练习题。这道练习题花了比较长的时间&#xff0c;于是就写篇博文记录一下我的算法和代码。 2024.01.03 题目 练习7-4 找出不是两个数组共有的元素 作者 张彤…...

7.27 SpringBoot项目实战 之 整合Swagger

文章目录 前言一、Maven依赖二、编写Swagger配置类三、编写接口配置3.1 控制器Controller 配置描述3.2 接口API 配置描述3.3 参数配置描述3.4 忽略API四、全局参数配置五、启用增强功能六、调试前言 在我们实现了那么多API以后,进入前后端联调阶段,需要给前端同学提供接口文…...

创建第一个SpringMVC项目,入手必看!

文章目录 创建第一个SpringMVC项目&#xff0c;入手必看&#xff01;1、新建一个maven空项目&#xff0c;在pom.xml中设置打包为war之前&#xff0c;右击项目添加web框架2、如果点击右键没有添加框架或者右击进去后没有web框架&#xff0c;点击左上角file然后进入项目结构在模块…...

go 切片长度与容量的区别

切片的声明 切片可以看成是数组的引用&#xff08;实际上切片的底层数据结构确实是数组&#xff09;。在 Go 中&#xff0c;每个数组的大小是固定的&#xff0c;不能随意改变大小&#xff0c;切片可以为数组提供动态增长和缩小的需求&#xff0c;但其本身并不存储任何数据。 …...

回归和分类区别

回归任务&#xff08;Regression&#xff09;&#xff1a; 特点&#xff1a; 输出是连续值&#xff0c;通常是实数。任务目标是预测或估计一个数值。典型应用包括房价预测、销售额预测、温度预测等。 目标&#xff1a; 最小化预测值与真实值之间的差异&#xff0c;通常使用…...

docker nginx滚动日志配置

将所有日志打印到控制台 nginx.conf user nginx; worker_processes auto; # 日志打印控制台 error_log /dev/stdout; #error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid;events {worker_connections 1024; }http {include /etc/nginx/m…...

大数据分析案例-基于LinearRegression回归算法构建房屋价格预测模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…...

React-hook-form-mui(一):基本使用

前言 在项目开发中&#xff0c;我们选择了ReactMUI作为技术栈。在使用MUI构建form表单时&#xff0c;我们发现并没有与antd类似的表单验证功能&#xff0c;于是我们选择了MUI推荐使用的react-hook-form-mui库去进行验证。但是发现网上关于这个库的使用方法和demo比较少且比较简…...

网站备案时 首页/武汉网站seo推广公司

mysql相关的三个函数有&#xff1a; NOW()函数以YYYY-MM-DD HH:MM:SS返回当前的日期时间&#xff0c;可以直接存到DATETIME字段中。CURDATE()以’YYYY-MM-DD’的格式返回今天的日期&#xff0c;可以直接存到DATE字段中。CURTIME()以’HH:MM:SS’的格式返回当前的时间&#xff0…...

扬中做网站/网站有吗免费的

相信大家开始玩gitlabjenkins的时候对着两个工具有肯定有一定了解&#xff0c;我就不做详细解释了&#xff0c;下面就跟大家简单的说下gitlab&#xff0c;jenkins之间工作关系&#xff1a; GitLab是一个代码仓库&#xff0c;用来管理代码。Jenkins是一个自动化服务器&#xff0…...

免费域名申请网站大全下载/重庆排名优化整站优化

前言一 编程规约 一 命名风格二 常量定义三 代码格式四 OOP规约五 集合处理六 并发处理七 控制语句八 注释规约九 其它 二 异常日志 一 异常处理二 日志规约 三 MySQL数据库 一 建表规约二 索引规约三 SQL语句四 ORM映射 四 工程结构 一 应用分层二 二方库依赖三 服务器 五 安全…...

wordpress上一页下一页/网站百度权重

中国正式掌管世界“物联网”!凭借物联网实现以“中国为中心&#xff0c;物联天下、全球经济一体化的“地球村”&#xff01;因为世界贸易离不开物联网&#xff01;而进入物联网的外国企业只有获8%的利益&#xff0c;其中92%的利益归中国所有&#xff0c;换句话说&#xff0c;资…...

响应式网站 图片处理/百度广告一天多少钱

一、HBase介绍1、基本概念HBase是一种Hadoop数据库&#xff0c;经常被描述为一种稀疏的&#xff0c;分布式的&#xff0c;持久化的&#xff0c;多维有序映射&#xff0c;它基于行键、列键和时间戳建立索引&#xff0c;是一个可以随机访问的存储和检索数据的平台。HBase不限制存…...

贵阳网站设计企业/武汉百度推广seo

向量化 无论使用哪门编程语言&#xff0c;使用该编程语言内置的函数总要比自己手写的函数快很多&#xff0c;如Octave中直接对矩阵A和B进行A*B即可实现矩阵乘法&#xff0c;且效率比自己手写高得多。故&#xff0c;倘若能将数据简化&#xff0c;并应用于内置函数中&#xff0c…...