UDN-企业互联网技术人气社区

板块导航

浏览  : 952
回复  : 0

[讨论交流] Redis分区(Partitioning)概论

[复制链接]
哥屋恩的头像 楼主
发表于 2016-5-17 19:08:18 | 显示全部楼层 |阅读模式

  摘要

  Redis Partitioning也即Redis分区,简单的说就是将数据分布到不同的redis实例中,因此对于每个redis实例所存储的内容仅仅是所有内容的一个子集。分区(Partitioning)不仅仅是Redis中的概念,几乎是所有数据存储系统都会涉及到的概念,这篇文章将会在理解分区基本概念的基础之上进一步了解Redis对分区的支持。

  我们为什么要分区

  使用Redis为什么要分区?分区的动机是什么?通常来说,Redis分区的两个主要目的如下:

  更好的利用多台机器的存储资源横向扩展,毕竟单台机器的存储资源是有限的。

  更好的利用多台计算机的处理器资源、网络带宽资源。

  总的来说,分区使得我们本来受限于单台计算机硬件资源的问题不再是问题,存储不够?计算资源不够?带宽不够?我们都可以通过增加机器来解决这些问题。

  分区(Partitioning)基础

  实际应用中有很多分区应用场景,想象一下,我们有四个Redis实例R0、R1、R2、R3和很多用来代表用户的键,如:user:1,user:2,……等等。我们可以有很多种方法来选择用来存储我们的key的Redis实例。也就是说我们有很多种将key映射到Redis Server的方法。最简单的一种方式是范围分区(range partitioning)。

  范围分区

  所谓范围分区,即将一个范围的对象映射到某一个实例中。举个例子:

  我们可以将ID从0到10000的对象映射到R0,而将ID从10001到20000的对象映射到R1实例,一次类推。

  这种方法在实际应用中是很有效的,然而那么问题来了:

  我们需要一张表,这张表用来存储范围到Redis实例的映射关系。

  我们不仅需要对这张表进行维护,而且对于每种对象类型我们都需要一个这样的表。

  因此,在实际应用中,使用范围分区并不值得,因为我们还有更好的方法,我们接下来认识下哈希分区。

  哈希分区

  哈希分区模式适合任何形式的key,而不像范围分区一样需要key的形式为object_name:,而且分区方法很简单:

  根据key和一个hash函数(如crc32 hash函数)计算出一个数值型的值。例如,如果key是foobar,crc32(foobar)的结果是93024922。

  对结果进行取模,取模的目的是计算出一个介于0到3之间的值,因此这个值才可以被映射到我们的一台Redis Server上面。比如93024922%4结果是2,因此我们就会知道foobar将要被存储在R2上面。

  当然除了上面提到的两种分区方法,还有很多其他的方法。比如一种从哈希分区演进而来的consistent hashing分区,其已经被redis client和proxies实现了。

  不同的分区实现

  分区可以在redis软件栈的不同部分被实现,我们来看看:

  客户端实现:即key在redis客户端就决定了要被存储在那台Redis实例中。

  代理实现:即客户端将请求发往代理服务器,代理服务器实现了Redis协议,因此代理服务器可以代理客户端和Redis服务器通信。代理服务器通过配置的分区schema来将客户端的请求转发到正确的Redis实例中,同时将反馈消息返回给客户端。Redis和Memcached代理Twemoroxy都实现了代理分区。

  查询路由:即我们可以将查询请求随机的发送到任意一个Redis实例,这个Redis实例负责将请求转发至正确的Redis实例中。Redis集群实现了一个通过和客户端协作的hybrid来做查询路由。

  Redis分区的缺点

  一些Redis功能在分区的环境下并不能很好的工作,我们来看看:

  多键操作是不被支持的。比如我们将要批量操作的键被映射到不同的Redis实例中。

  多键的Redis事务是不被支持的。

  分区的最小粒度是键,因此我们不能将关联到一个键的很大的数据集映射到不同的实例。

  当应用分区的时候,数据的处理是非常复杂的,比如我们需要处理多个rdb/aof文件,将分布在不同实例的文件聚集到一起备份。

  添加和删除机器是很复杂的,例如Redis集群支持几乎运行时透明的因为增加或减少机器而需要做的rebalancing,然而像客户端和代理分区这种方式是不支持这种功能的,这个时候Pre-sharding来了。

  存储 OR 缓存

  尽管数据分区对于Redis来说无论是数据存储还是缓存,在概念上都是一样的,然而对于数据存储还是有一个很大的限制。当我们使用Redis来作为存储的时候,每一个key必须一致被映射到同一个Redis实例。而当Redis被当做缓存使用的时候,对于这个key,如果一个实例不能用了,这个key还可以被映射到其他的实例中。

  Consistent hashing实现通常使得当一个key被映射到的实例不能用的时候将这个key映射到其他实例成为可能。类似,如果增加了一台机器,一部分的key将会被映射到这台新的机器上,我们需要了解的两个概念如下:

  如果Redis被用来当做缓存,且要求容易增加或删除机器,使用consistent hashing是非常简单的。

  如果Redis被用来当做(持久)存储,一个固定的key到实例的映射是需要的,因此我们不能够再灵活的添加或删除机器。否则,我们需要在增加或删除机器的时候系统能够rebalace,当前Redis Cluster已经支持。

  预分布式

  通过上面的介绍,我们知道Redis分区应用是有问题的,除非我们只是使用Redis当做缓存,否则对于增加机器或删除机器是非常麻烦的。

  然而,通常我们Redis容量变动在实际应用中是非常常见的,比如今天我需要10台Redis机器,明天可能就需要50台机器了。

  鉴于Redis是很长轻量级的服务(每个实例仅仅占用1M),对于上面的问题一种简单的解决办法是,我们可以开启多个Redis实例,尽管是一台物理机器,我们在刚开始的时候也可以开启多个实例。我们可以从中选择一些实例,比如32或64个实例来作为我们的工作集群。当一台物理机器存储不够的时候,我们可以将一般的实例移动到我们的第二台物理机上,一次类对,我们可以保证集群中Redis的实例数不变,又可以达到扩充机器的目的。

  怎么移动Redis实例呢,看:

  在新的物理机上启动一个新的Redis实例。

  将新的物理机作为要移动的那台的slave机器。

  停止客户端。

  更新将要被移动的那台Redis实例的IP地址。

  对于slave机器发送SLAVEOF ON ONE命令。

  使用新的IP启动Redis客户端。

  关闭不再使用的那个Redis实例。

  Redis分区

  通过上面的内容,我们已经学习了Redis分区相关的理论只是,那么我们怎么实践呢?常用的Redis分区方法下面几种:

  Redis Cluster

  Twemproxy

  客户端consistent hashing

  参考文献

  《Redis官方文档》

原文作者:佚名 来源:开发者头条
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部