Redis多机数据库实现,主要分为以下几种:1.主从复制2.哨兵模式3.RedisCluster官方提供的集群模式(服务端)4.Jedis分片cluster(clientsharding)5.使用中间件代理,比如codis,其中前三个是server端方案,后两个是client端分区方案,类似分表分库master-的方案从复制(Master-SlaveReplication):实现主从复制(Master-SlaveReplication)的工作原理:从节点服务启动并连接到主节点后,会主动发送一个SYNC命令。Master服务主节点收到同步命令后,会启动后台存储进程,收集所有接收到的修改数据集的命令。后台进程执行完毕后,Master会将整个数据库文件传输给Slave,完成一次完整的同步。从节点服务接收到数据库文件数据后,保存并加载到内存中。之后Master主节点继续将收集到的所有修改命令和新的修改命令依次发送给Slave,Slave将执行本次这些数据修改命令,从而实现最终的数据同步。如果Master和Slave之间的链接断开,Slave可以自动重新连接到Master,但是连接成功后,会自动进行全量同步。主从模式的优缺点优点:同一个Master可以同步多个Slave。Slave也可以接受来自其他Slave的连接和同步请求,可以有效分担Master的同步压力。因此,我们可以把Redis的Replication架构看成一个图结构。MasterServer以非阻塞的方式为Slaves提供服务。所以在Master-Slave同步过程中,客户端仍然可以提交查询或者修改请求。SlaveServer也以非阻塞的方式完成数据同步。在同步过程中,如果客户端提交查询请求,Redis返回同步前的数据。为了减轻Master的读操作压力,Slave服务器可以为客户端提供只读操作服务,而写服务仍然必须由Master来完成。尽管如此,系统的可扩展性还是得到了极大的提高。Master可以将保存数据的操作交给Slave,这样就避免了Master中需要一个独立的进程来完成这个操作。支持主从复制,master会自动同步数据到slave,可以实现读写分离。缺点:Redis没有自动容错和恢复功能。主机和从机宕机会导致前端部分读写请求失败。需要等待机器重启或者手动切换前端IP才能恢复。宿主机宕机,宕机前部分数据无法及时同步到从机,切换IP后会引入数据不一致,降低系统的可用性。Redis的主从复制采用的是全量复制。在复制过程中,主机会fork出一个子进程对内存进行快照,并将子进程的内存快照保存为文件发送给从机。此过程需要确保主机有足够的空闲内存。如果快照文件较大,对集群的服务能力影响很大,复制过程会在从机新加入集群或从机与宿主机网络断开重连时进行,即网络波动会导致主机与主机之间的全量数据复制,给实际的系统运行带来很大的麻烦。Redis很难支持在线扩容,当集群容量达到上限时,在线扩容会变得非常复杂。为了避免这个问题,运维人员必须保证系统上线时有足够的空间,造成资源的极大浪费。其实redis的主从模式很简单,在实际生产环境中很少用到。我不推荐在实际生产环境中使用主从模式来提供系统的高可用。之所以不推荐,是因为主从模式的缺点,在数据量非常大的时候,或者需要系统高可用的时候,也是不稳定的。Sentinel模式:Redis2.6版本开始提供该模式,但当时该版本的模式不稳定。直到Redis2.8版本,sentinel模式才趋于稳定,无论是master-slave模式还是sentinel模式,这两种模式都存在一个不能水平扩展的问题,这两种模式的高可用特性将被受Master主节点内存限制。哨兵(sentinel)进程用于监控redis集群中Master主服务器的工作状态。当Master主服务器出现故障时,可以在Master和Slave服务器之间切换,保证系统的高可用性。哨兵(sentinel)进程监控(Monitoring)的作用:哨兵(sentinel)会不断的检查你的Master和Slave是否运行正常。通知:当被监控的Redis节点出现问题时,sentinel可以通过API向管理员或其他应用发送通知。自动故障转移:当一个master不能正常工作时,sentinel会启动一次自动故障转移操作,将故障master的其中一个slave升级为新的master,并让故障master的其他slave复制新的Master;当client尝试连接失效的Master时,cluster也会将新Master的地址返回给client,这样cluster就可以使用当前的Master来替代失效的Master。Master和Slave服务器切换后,Master的redis.conf、Slave的redis.conf和sentinel.conf的配置文件内容会相应变化,即redis.conf配置中多了一行slaveofMaster主服务器Configuration文件,sentinel.conf的监控目标会相应改变。Sentinel进程是如何工作的每个Sentinel进程每秒向整个集群中的Master主服务器、Slave从服务器和其他Sentinel进程发送一次PING命令。如果一个实例(instance)距离最后一次对PING命令的有效回复的时间超过down-after-milliseconds选项指定的值,则该实例将被Sentinel进程标记为主观下线(SDOWN)。如果一个Master服务器被标记为主观下线(SDOWN),所有正在监视Master主服务器的哨兵(sentinel)进程必须每秒确认一次Master主服务器确实进入了主观下线状态。当有足够的哨兵(sentinel)进程(大于等于配置文件中指定的值)确认Master主服务器在指定时间范围内进入主观下线状态(SDOWN),则Master主服务器会被标记为目标下线(ODOWN)一般情况下,每个哨兵(sentinel)进程都会每隔10秒向集群中的所有Master主服务器和Slave从服务器发送INFO命令。当Master主服务器被哨兵(sentinel)进程标记为客观下线(ODOWN)时,Sentinel(哨兵)进程向下线Master主服务器的所有Slave从服务器发送INFO命令的频率将从一次变为每10秒到每秒一次。如果没有足够多的哨兵(sentinel)进程同意Master主服务器下线,那么Master主服务器的客观下线状态就会被移除。如果Master主服务器再次向Sentinel(哨兵)进程发送PING命令并返回有效回复,Master主服务器主观下线状态将被解除。sentinel模式的优缺点优点:Sentinel集群模式是基于master-slave模式,master-slave的所有优点,sentry模式同样具备。主从可以切换,故障可以转移,系统可用性更好。哨兵模式是主从模式的升级,系统更健壮,可用性更高。缺点:Redis难以支持在线扩容,当集群容量达到上限时,在线扩容会变得非常复杂。为了避免这个问题,运维人员必须保证系统上线时有足够的空间,造成资源的极大浪费。复杂配置Redis官方Cluster集群模式RedisCluster是一种服务器分片技术,3.0版本正式推出。集群通过分片共享数据,并提供复制和故障转移功能。Redis集群通常由多个节点组成;最初,每个节点都是独立的,需要连接起来形成一个工作集群。Redis中的集群分为主节点和从节点。主节点用于处理槽;从节点用于复制一个主节点,当复制的主节点下线时,代替下线的主节点继续处理命令请求。集群模式将在下一篇文章中详细讲解。Jedis分片集群是一种客户端分区方案。RedisSharding可以说是Redis集群出来之前业界常用的一种方式。客户端已经决定了数据存储在哪个redis节点或者从哪个redis节点读取。主要思想是利用哈希算法对Redis数据的key进行哈希处理,通过哈希函数将特定的key映射到特定的Redis节点。幸运的是,JavaRedis客户端驱动Jedis已经支持RedisSharding功能,即ShardedJedis和ShardedJedisPoolJedis结合缓冲池的RedisSharding实现具有以下特点:采用一致性哈希算法,将key和节点名哈希在同时,再映射Match,使用的算法是MURMUR_HASH。使用一致性哈希而不是简单的类似哈希的模映射的主要原因是当添加或删除节点时,不会因为重新匹配而重新哈希。一致性哈希只影响相邻节点的key分布,影响较小。ShardedJedis为了避免一致性哈希只影响相邻节点带来的节点分配压力,ShardedJedis会为每个Redis节点根据其名称(不是,Jedis会分配一个默认名称)虚拟出160个虚拟节点进行哈希。根据weight权重,还可以虚拟出160倍的虚拟节点。使用虚拟节点进行映射匹配,在增加或减少Redis节点时,可以在Redis节点之间更均匀地移动和重新分配键,而不是只影响相邻节点。ShardedJedis支持keyTagPattern模式,即提取一部分keyTag进行sharding,这样通过对key的合理命名,可以将一组相关的key放到同一个Redis节点中,这对于避免跨节点非常重要访问相关数据。当然,RedisSharding这种轻量灵活的方式必然会损害集群的其他能力。比如在扩容的时候,想增加Redis节点的时候,即使使用一致性哈希,毕竟还是会有键匹配不上而丢失。这时候就需要进行键值迁移。Redis作为轻量级的客户端分片,处理Redis的key-value迁移是不现实的,需要应用层允许Redis中的数据丢失或者从后端数据库重新加载数据。但是有时候,突破缓存层,直接访问数据库层,会给系统访问带来很大的压力。使用中间件代理客户端向代理组件发送请求,代理组件解析客户端的数据,将请求转发到正确的节点,最后将结果回复给客户端。优点:简化客户端分布式逻辑,客户端透明接入,切换成本低,代理转发和存储分离。缺点:多了一层代理层,增加了架构部署的复杂度和性能损失。
