1,解决应用服务器的cpu和内存压力前端
2,减小io的读操做,减轻io的压力(内存中读取)node
3,关系型数据库扩展性,不强,难以改变表的结构nginx
1,nosql数据库没有关联关系,数据结构简单,扩展容易redis
2,数据读写快,可以每秒胜任几十万的并发,处理速度快算法
1,数据高并发读写sql
2,海量数据读写数据库
3,对不规则数据也就是扩展性要求高的数据后端
1,须要事务支持,虽然它也有事务可是没有关系型数据库的那么成熟吧缓存
2,基于sql进行操做服务器
1,主从复制
2,哨兵模式
3,Redis官方提供的Cluster集群模式(服务端)
4,Jedis sharding集群(客户端sharding)
5,利用中间件代理,好比豌豆荚的codis等
实现主从复制(Master-Slave Replication)的工做原理:Slave从节点服务启动并链接到Master以后,它将主动发送一个SYNC命令。Master服务主节点收到同步命令后将启动后台存盘进程,同时收集全部接收到的用于修改数据集的命令,在后台进程执行完毕后,Master将传送整个数据库文件到Slave,以完成一次彻底同步。而Slave从节点服务在接收到数据库文件数据以后将其存盘并加载到内存中。此后,Master主节点继续将全部已经收集到的修改命令,和新的修改命令依次传送给Slaves,Slave将在本次执行这些数据修改命令,从而达到最终的数据同步。
若是Master和Slave之间的连接出现断连现象,Slave能够自动重连Master,可是在链接成功以后,一次彻底同步将被自动执行。
主从复制配置
修改从节点的配置文件:slaveof masterip masterport
若是设置了密码,就要设置:masterauth master-password
主从模式的优缺点
优势:
同一个Master能够同步多个Slaves。
Slave一样能够接受其它Slaves的链接和同步请求,这样能够有效的分载Master的同步压力。所以咱们能够将Redis的Replication架构视为图结构。
Master Server是以非阻塞的方式为Slaves提供服务。因此在Master-Slave同步期间,客户端仍然能够提交查询或修改请求。
Slave Server一样是以非阻塞的方式完成数据同步。在同步期间,若是有客户端提交查询请求,Redis则返回同步以前的数据
为了分载Master的读操做压力,Slave服务器能够为客户端提供只读操做的服务,写服务仍然必须由Master来完成。即使如此,系统的伸缩性仍是获得了很大的提升。
Master能够将数据保存操做交给Slaves完成,从而避免了在Master中要有独立的进程来完成此操做。
支持主从复制,主机会自动将数据同步到从机,能够进行读写分离。
缺点:
Redis不具有自动容错和恢复功能,主机从机的宕机都会致使前端部分读写请求失败,须要等待机器重启或者手动切换前端的IP才能恢复。
主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,下降了系统的可用性。
Redis的主从复制采用全量复制,复制过程当中主机会fork出一个子进程对内存作一份快照,并将子进程的内存快照保存为文件发送给从机,这一过程须要确保主机有足够多的空余内存。若快照文件较大,对集群的服务能力会产生较大的影响,并且复制过程是在从机新加入集群或者从机和主机网络断开重连时都会进行,也就是网络波动都会形成主机和从机间的一次全量的数据复制,这对实际的系统运营形成了不小的麻烦。
Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源形成了很大的浪费。
建议:
其实redis的主从模式很简单,在实际的生产环境中是不多使用的,也不建议在实际的生产环境中使用主从模式来提供系统的高可用性,之因此不建议使用都是由它的缺点形成的,在数据量很是大的状况,或者对系统的高可用性要求很高的状况下,主从模式也是不稳定的。
该模式是从Redis的2.6版本开始提供的,可是当时这个版本的模式是不稳定的,直到Redis的2.8版本之后,这个哨兵模式才稳定下来,不管是主从模式,仍是哨兵模式,这两个模式都有一个问题,不能水平扩容,而且这两个模式的高可用特性都会受到Master主节点内存的限制。
Sentinel(哨兵)进程是用于监控redis集群中Master主服务器工做的状态,在Master主服务器发生故障的时候,能够实现Master和Slave服务器的切换,保证系统的高可用。
Sentinel(哨兵)进程的做用
监控(Monitoring): 哨兵(sentinel) 会不断地检查你的Master和Slave是否运做正常。
提醒(Notification):当被监控的某个Redis节点出现问题时, 哨兵(sentinel) 能够经过 API 向管理员或者其余应用程序发送通知。
自动故障迁移(Automatic failover):当一个Master不能正常工做时,哨兵(sentinel) 会开始一次自动故障迁移操做,它会将失效Master的其中一个Slave升级为新的Master, 并让失效Master的其余Slave改成复制新的Master;当客户端试图链接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可使用如今的Master替换失效Master。Master和Slave服务器切换后,Master的redis.conf、Slave的redis.conf和sentinel.conf的配置文件的内容都会发生相应的改变,即,Master主服务器的redis.conf配置文件中会多一行slaveof的配置,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主服务器的主观下线状态就会被移除。
哨兵模式的优缺点
优势:
哨兵集群模式是基于主从模式的,全部主从的优势,哨兵模式一样具备。
主从能够切换,故障能够转移,系统可用性更好。
哨兵模式是主从模式的升级,系统更健壮,可用性更高。
缺点:
Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源形成了很大的浪费。
配置复杂
Redis Cluster是一种服务器Sharding技术,3.0版本开始正式提供。
在这个图中,每个蓝色的圈都表明着一个redis的服务器节点。它们任何两个节点之间都是相互连通的。客户端能够与任何一个节点相链接,而后就能够访问集群中的任何一个节点。对其进行存取和其余操做。
Redis集群数据分片
在redis的每个节点上,都有这么两个东西,一个是插槽(slot)能够理解为是一个能够存储两个数值的一个变量这个变量的取值范围是:0-16383。还有一个就是cluster我我的把这个cluster理解为是一个集群管理的插件。当咱们的存取的key到达的时候,redis会根据crc16的算法得出一个结果,而后把结果对 16384 求余数,这样每一个 key 都会对应一个编号在 0-16383 之间的哈希槽,经过这个值,去找到对应的插槽所对应的节点,而后直接自动跳转到这个对应的节点上进行存取操做。
还有就是由于若是集群的话,是有好多个redis一块儿工做的,那么,就须要这个集群不是那么容易挂掉,因此呢,理论上就应该给集群中的每一个节点至少一个备用的redis服务。这个备用的redis称为从节点(slave)。那么这个集群是如何判断是否有某个节点挂掉了呢?
首先要说的是,每个节点都存有这个集群全部主节点以及从节点的信息。
它们之间经过互相的ping-pong判断是否节点能够链接上。若是有一半以上的节点去ping一个节点的时候没有回应,集群就认为这个节点宕机了,而后去链接它的备用节点。若是某个节点和全部从节点所有挂掉,咱们集群就进入faill状态。还有就是若是有一半以上的主节点宕机,那么咱们集群一样进入发力了状态。这就是咱们的redis的投票机制,具体原理以下图所示:
投票过程是集群中全部master参与,若是半数以上master节点与master节点通讯超时(cluster-node-timeout),认为当前master节点挂掉.
何时整个集群不可用(cluster_state:fail)?
若是集群任意master挂掉,且当前master没有slave.集群进入fail状态,也能够理解成集群的slot映射[0-16383]不完整时进入fail状态. ps : redis-3.0.0.rc1加入cluster-require-full-coverage参数,默认关闭,打开集群兼容部分失败.
若是集群任意master挂掉,且当前master没有slave.集群进入fail状态,也能够理解成集群的slot映射[0-16383]不完整时进入fail状态. ps : redis-3.0.0.rc1加入cluster-require-full-coverage参数,默认关闭,打开集群兼容部分失败.
Redis 3.0的集群方案有如下两个问题。
一个Redis实例具有了“数据存储”和“路由重定向”,彻底去中心化的设计。这带来的好处是部署很是简单,直接部署Redis就行,不像Codis有那么多的组件和依赖。但带来的问题是很难对业务进行无痛的升级,若是哪天Redis集群出了什么严重的Bug,就只能回滚整个Redis集群。
对协议进行了较大的修改,对应的Redis客户端也须要升级。升级Redis客户端后谁能确保没有Bug?并且对于线上已经大规模运行的业务,升级代码中的Redis客户端也是一个很麻烦的事情。
Redis Cluster是Redis 3.0之后才正式推出,时间较晚,目前能证实在大规模生产环境下成功的案例还不是不少,须要时间检验。
Redis Sharding能够说是在Redis cluster出来以前业界广泛的采用方式,其主要思想是采用hash算法将存储数据的key进行hash散列,这样特定的key会被定为到特定的节点上。
庆幸的是,Java Redis客户端驱动Jedis已支持Redis Sharding功能,即ShardedJedis以及结合缓存池的ShardedJedisPool
Jedis的Redis Sharding实现具备以下特色:
采用一致性哈希算法,将key和节点name同时hashing,而后进行映射匹配,采用的算法是MURMUR_HASH。采用一致性哈希而不是采用简单相似哈希求模映射的主要缘由是当增长或减小节点时,不会产生因为从新匹配形成的rehashing。一致性哈希只影响相邻节点key分配,影响量小。
为了不一致性哈希只影响相邻节点形成节点分配压力,ShardedJedis会对每一个Redis节点根据名字(没有,Jedis会赋予缺省名字)会虚拟化出160个虚拟节点进行散列。根据权重weight,也可虚拟化出160倍数的虚拟节点。用虚拟节点作映射匹配,能够在增长或减小Redis节点时,key在各Redis节点移动再分配更均匀,而不是只有相邻节点受影响。
ShardedJedis支持keyTagPattern模式,即抽取key的一部分keyTag作sharding,这样经过合理命名key,能够将一组相关联的key放入同一个Redis节点,这在避免跨节点访问相关数据时很重要。
固然,Redis Sharding这种轻量灵活方式必然在集群其它能力方面作出妥协。好比扩容,当想要增长Redis节点时,尽管采用一致性哈希,毕竟仍是会有key匹配不到而丢失,这时须要键值迁移。
做为轻量级客户端sharding,处理Redis键值迁移是不现实的,这就要求应用层面容许Redis中数据丢失或从后端数据库从新加载数据。但有些时候,击穿缓存层,直接访问数据库层,会对系统访问形成很大压力。
中间件的做用是将咱们须要存入redis中的数据的key经过一套算法计算得出一个值。而后根据这个值找到对应的redis节点,将这些数据存在这个redis的节点中。
经常使用的中间件有这几种
Twemproxy
Codis
nginx
具体用法就不赘述了,能够自行百度。
客户端分片(sharding)须要客户端维护分片算法,这是一种静态的分片方案,须要增长或者减小Redis实例的数量,须要手工调整分片的程序。利用中间件的状况则会影响到redis的性能,具体看中间件而定,毕竟全部请求都要通过中间件一层过滤官方提供方案,现时点成功案例很少。