分享

Redis 3.0中文官方文档翻译计划(8) ——分片

旧收音机 发表于 2015-4-12 17:04:06 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 1 15718
本帖最后由 旧收音机 于 2015-4-25 17:42 编辑

问题导读
1、分片为何有用?
2、分片基础是什么?
3、分片有哪些实现方式?
4、分片有哪些缺点?
5、Redis分片作为数据存储还是缓存呢?
6、预分片是怎样实现的?
7、Redis集群和分片之间的关联是什么?
8、Twemproxy怎么用来集群分片?










分片(partitioning)就是将你的数据拆分到多个Redis实例的过程,这样每个实例将只包含所有键的子集。本文第一部分将向你介绍分片的概念,第二部分将向你展示Redis分片的可选方案。

    分片为何有用(Why useful)
    Redis的分片承担着两个主要目标:
  • 允许使用很多电脑的内存总和来支持更大的数据库。没有分片,你就被局限于单机能支持的内存容量。
  • 允许伸缩计算能力到多核或多服务器,伸缩网络带宽到多服务器或多网络适配器。


    分片基础(Basics)
    有很多不同的分片标准(criteria)。假想我们有4个Redis实例R0,R1,R2,R3,还有很多表示用户的键,像user:1,user:2,…等等,我们能找到不同的方式来选择一个指定的键存储在哪个实例中。换句话说,有许多不同的办法来映射一个键到一个指定的Redis服务器。
    最简单的执行分片的方式之一是范围分片(range partitioning),通过映射对象的范围到指定的Redis实例来完成分片。例如,我可以假设用户从ID 0到ID 10000进入实例R0,用户从ID 10001到ID 20000进入实例R1,等等。
    这套办法行得通,并且事实上在实践中被采用,然而,这有一个缺点,就是需要一个映射范围到实例的表格。这张表需要管理,不同类型的对象都需要一个表,所以范围分片在Redis中常常并不可取,因为这要比替他分片可选方案低效得多。
    一种范围分片的替代方案是哈希分片(hash partitioning)。这种模式适用于任何键,不需要键像object_name:<id>这样的饿形式,就像这样简单:
  • 使用一个哈希函数(例如,crc32哈希函数)将键名转换为一个数字。例如,如果键是foobar,crc32(foobar)将会输出类似于93024922的东西。
  • 对这个数据进行取模运算,以将其转换为一个0到3之间的数字,这样这个数字就可以映射到我的4台Redis实例之一。93024922模4等于2,所以我知道我的键foobar应当存储到R2实例。注意:取模操作返回除法操作的余数,在许多编程语言总实现为%操作符。

    有许多其他的方式可以分片,从这两个例子中你就可以知道了。一种哈希分片的高级形式称为一致性哈希(consistent hashing),被一些Redis客户端和代理实现。

    分片的不同实现(Different implementations)
    分片可由软件栈中的不同部分来承担。
  • 客户端分片(Client side partitioning)意味着,客户端直接选择正确的节点来写入和读取指定键。许多Redis客户端实现了客户端分片。
  • 代理协助分片(Proxy assisted partitioning)意味着,我们的客户端发送请求到一个可以理解Redis协议的代理上,而不是直接发送请求到Redis实例上。代理会根据配置好的分片模式,来保证转发我们的请求到正确的Redis实例,并返回响应给客户端。Redis和Memcached的代理Twemproxy实现了代理协助的分片。
  • 查询路由(Query routing)意味着,你可以发送你的查询到一个随机实例,这个实例会保证转发你的查询到正确的节点。Redis集群在客户端的帮助下,实现了查询路由的一种混合形式(请求不是直接从Redis实例转发到另一个,而是客户端收到重定向到正确的节点)。


    分片的缺点(Disadvantages)
    Redis的一些特性与分片在一起时玩转的不是很好:
  • 涉及多个键的操作通常不支持。例如,你不能对映射在两个不同Redis实例上的键执行交集(事实上有办法做到,但不是直接这么干)。
  • 涉及多个键的事务不能使用。
  • 分片的粒度(granularity)是键,所以不能使用一个很大的键来分片数据集,例如一个很大的有序集合。
  • 当使用了分片,数据处理变得更复杂,例如,你需要处理多个RDB/AOF文件,备份数据时你需要聚合多个实例和主机的持久化文件。
  • 添加和删除容量也很复杂。例如,Redis集群具有运行时动态添加和删除节点的能力来支持透明地再均衡数据,但是其他方式,像客户端分片和代理都不支持这个特性。但是,有一种称为预分片(Presharding)的技术在这一点上能帮上忙。


    数据存储还是缓存(Store or cache)
    尽管无论是将Redis作为数据存储还是缓存,Redis的分片概念上都是一样的,但是作为数据存储时有一个重要的局限。当Redis作为数据存储时,一个给定的键总是映射到相同的Redis实例。当Redis作为缓存时,如果一个节点不可用而使用另一个节点,这并不是一个什么大问题,按照我们的愿望来改变键和实例的映射来改进系统的可用性(就是系统回复我们查询的能力)。
    一致性哈希实现常常能够在指定键的首选节点不可用时切换到其他节点。类似的,如果你添加一个新节点,部分数据就会开始被存储到这个新节点上。
    这里的主要概念如下:
  • 如果Redis用作缓存,使用一致性哈希来来实现伸缩扩展(scaling up and down)是很容易的。
  • 如果Redis用作存储,使用固定的键到节点的映射,所以节点的数量必须固定不能改变。否则,当增删节点时,就需要一个支持再平衡节点间键的系统,当前只有Redis集群可以做到这一点,但是Redis集群现在还处在beta阶段,尚未考虑再生产环境中使用。


   预分片(Presharding)
    我们已经知道分片存在的一个问题,除非我们使用Redis作为缓存,增加和删除节点是一件很棘手的事情,使用固定的键和实例映射要简单得多。
    然而,数据存储的需求可能一直在变化。今天我可以接受10个Redis节点(实例),但是明天我可能就需要50个节点。
    因为Redis只有相当少的内存占用(footprint)而且轻量级(一个空闲的实例只是用1MB内存),一个简单的解决办法是一开始就开启很多的实例。即使你一开始只有一台服务器,你也可以在第一天就决定生活在分布式的世界里,使用分片来运行多个Redis实例在一台服务器上。
    你一开始就可以选择很多数量的实例。例如,32或者64个实例能满足大多数的用户,并且为未来的增长提供足够的空间。
    这样,当你的数据存储需要增长,你需要更多的Redis服务器,你要做的就是简单地将实例从一台服务器移动到另外一台。当你新添加了第一台服务器,你就需要把一半的Redis实例从第一台服务器搬到第二台,如此等等。
    使用Redis复制,你就可以在很小或者根本不需要停机时间内完成移动数据:
  • 在你的新服务器上启动一个空实例。
  • 移动数据,配置新实例为源实例的从服务。
  • 停止你的客户端。
  • 更新被移动实例的服务器IP地址配置。
  • 向新服务器上的从节点发送SLAVEOF NO ONE命令。
  • 以新的更新配置启动你的客户端。
  • 最后关闭掉旧服务器上不再使用的实例。


    Redis分片的实现(Implementations)
    到目前为止,我们从理论上讨论了Redis分片,但是实践情况如何呢?你应该使用什么系统呢?

    Redis集群(Redis Cluster)
    Redis集群是自动分片和高可用的首选方式。当前还不能完全用于生产环境,但是已经进入了beta阶段,所以我们推荐你开始小试牛刀。你可以从集群教程(请持续关注本公众账号后续文章,译者注)中获取更多Redis集群的相关信息。
    一旦Redis集群可用,以及支持Redis集群的客户端可用,Redis集群将会成为Redis分片的事实标准。
    Redis集群是查询路由和客户端分片的混合模式。

    Twemproxy
    Twemproxy是Twitter开发的一个支持Memcached ASCII和Redis协议的代理。它是单线程的,由C语言编写,运行非常的快。他是基于Apache 2.0许可的开源项目。
    Twemproxy支持自动在多个Redis实例间分片,如果节点不可用时,还有可选的节点排除支持(这会改变键和实例的映射,所以你应该只在将Redis作为缓存是才使用这个特性)。
    这并不是单点故障(single point of failure),因为你可以启动多个代理,并且让你的客户端连接到第一个接受连接的代理。
    从根本上说,Twemproxy是介于客户端和Redis实例之间的中间层,这就可以在最下的额外复杂性下可靠地处理我们的分片。这是当前我们建议的处理Redis分片的方式。你可以阅读更多关于Twemproxy的信息(作者的这篇博客文章http://antirez.com/news/44 ,译者注)。

    支持一致性哈希的客户端
    Twemproxy之外的可选方案,是使用实现了客户端分片的客户端,通过一致性哈希或者别的类似算法。有多个支持一致性哈希的Redis客户端,例如Redis-rb和Predis。
    请查看完整的Redis客户端列表,看看是不是有支持你的编程语言的,并实现了一致性哈希的成熟客户端。




相关内容:
            Redis 3.0官方文档翻译计划(1)  ——Redis介绍

             Redis 3.0官方文档翻译计划(2) ——从入门到精通(上)

             Redis 3.0官方文档翻译计划(3) ——从入门到精通(中)

            Redis 3.0官方文档翻译计划(4) ——从入门到精通(下)

           Redis 3.0中文官方文档翻译计划(5) ——使用Redis实现Twitter(上)

            Redis 3.0中文官方文档翻译计划(6) ——使用Redis实现Twitter(下)

          Redis 3.0中文官方文档翻译计划(7) ——使用Redis作为LRU缓存

            Redis 3.0中文官方文档翻译计划(8) ——分片

           Redis 3.0中文官方文档翻译计划(9) ——复制

          Redis 3.0中文官方文档翻译计划(10) ——持久化

          Redis 3.0中文官方文档翻译计划(11) ——集中插入

           Redis 3.0中文官方文档翻译计划(12) ——高可用(上)

          Redis 3.0中文官方文档翻译计划(13) ——高可用(下)

          Redis 3.0中文官方文档翻译计划(14) ——高可用客户端指引

          Redis 3.0中文官方文档翻译计划(15) ——集群(上)
          Redis 3.0中文官方文档翻译计划(16) ——集群(中)

          Redis 3.0中文官方文档翻译计划(17) ——集群(下)



已有(1)人评论

跳转到指定楼层
LeucotheaShi 发表于 2015-4-13 09:32:40
讲得很详细的呢~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条