从Redis分区的优缺点来看适合的应用场景

正文

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

  一、我们为什么要分区

  我们为什么要分区?分区的动机是什么?通常来说,Redis分区的好处大致有如下两个方面:

  性能的提升,单机Redis的网络I/O能力和计算资源是有限的,将请求分散到多台机器,充分利用多台机器的计算能力可网络带宽,有助于提高Redis总体的服务能力。

  存储的横向扩展,即使Redis的服务能力能够满足应用需求,但是随着存储数据的增加,单台机器受限于机器本身的存储容量,将数据分散到多台机器上存储使得Redis服务可以横向扩展。

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

  二、Redis分区基础

  实际应用中有很多分区的具体策略,举个例子,假设我们已经有了一组四个Redis实例分别为R0、R1、R2、R3,另外我们有一批代表用户的键,如:user:1,user:2,……等等,其中“user:”后面的数字代表的是用户的ID,我们要做的事情是把这些键分散存储在这四个不同的Redis实例上。怎么做呢?最简单的一种方式是范围分区(range partitioning),下面我们来看看基于范围分区怎么做。

  范围分区
  所谓范围分区,就是将一个范围内的key都映射到同一个Redis实例中,加入数据集还是上面提到的用户数据,具体做法如下:

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

  这种方法虽然简单,但是在实际应用中是很有效的,不过还是有问题:

  我们需要一张表,这张表用来存储用户ID范围到Redis实例的映射关系,比如用户ID0-10000的是映射到R0实例……。

  我们不仅需要对这张表进行维护,而且对于每种对象类型我们都需要一个这样的表,比如我们当前存储的是用户信息,如果存储的是订单信息,我们就需要再建一张映射关系表。

  如果我们想要存储的数据的key并不能按照范围划分怎么办,比如我们的key是一组uuid,这个时候就不好用范围分区了。

  因此,在实际应用中,范围分区并不是很好的选择,不用担心,我们还有更好的方法,接下来认识下哈希分区。

    哈希分区
  哈希分区跟范围分区相比一个明显的优点是哈希分区适合任何形式的key,而不像范围分区一样需要key的形式为object_name:<id>,而且分区方法也很简单,一个公式就可以表达:

  id=hash(key)%N

  其中id代表Redis实例的编号,公式描述的是首先根据key和一个hash函数(如crc32函数)计算出一个数值型的值。接着上面的例子,我们的第一个要处理的key是user:1,hash(user:1)的结果是93024922。

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

  当然除了上面提到的两种分区方法,还有很多其他的方法。比如一种从哈希分区演进而来的consistent hashing分区,相信信息可以参考我的另一篇文章《memcached分布式实现原理》,其已经被redis client和proxies实现了。

  三、不同的分区实现

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

  客户端实现

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

  客户端实现分区示意图

  代理实现

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


代理实现Redis分区示意图

  Redis和Memcached代理Twemoroxy都实现了代理分区。

  查询路由

  查询路由是Redis Cluster实现的一种Redis分区方式:

  查询路由Redis分区示意图

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

  四、Redis分区的缺点

  尽管Redis分区到现在为止,so far so good,但是Redis分区有一些致命的缺点,这导致一些Redis功能在分区的环境下并不能很好地工作,我们来看看:

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

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

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

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

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

  既然有问题,那么就需要解决方案,这个时候Pre-sharding来了,后面我们会介绍Pre-Sharding。

  五、持久存储用还是缓存

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

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

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

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

  六、Pre-Sharding

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

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

  鉴于Redis是很轻量级的服务(每个实例仅仅占用1M),对于上面的问题一种简单的解决办法是:

  我们可以开启多个Redis实例,尽管是一台物理机器,我们在刚开始的时候也可以开启多个实例。我们可以从中选择一些实例,比如32或64个实例来作为我们的工作集群。当一台物理机器存储不够的时候,我们可以将一般的实例移动到我们的第二台物理机上,依次类对,我们可以保证集群中Redis的实例数不变,又可以达到扩充机器的目的。

  怎么移动Redis实例呢?当需要将Redis实例移动到独立的机器上的时候,我们可以通过下面步骤实现:

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

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

  停止客户端。

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

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

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

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

  七、总结

  这篇文章在理解Redis分区概念的基础之上又介绍了Redis分区常见的几种实现方式及原理,最后根据实现中遇到的问题引入了Pre-Sharding解决方案。

  参考文献

  《Redis官方文档》

时间: 2024-09-30 15:38:36

从Redis分区的优缺点来看适合的应用场景的相关文章

使用Redis分区将数据分割到多个Redis实例

分区是将所有的数据分割到多个Redis实例的过程,所以每个Redis实例存放的是所有键值的子集. Redis分区主要有两个目标:1)允许使用多台计算机的内存来存放更大的数据.如果不做分区的话,单台计算机的内存又限制. 2)使用多台计算的计算能力和网络带宽. 有许多不同的分区场景, 参考资料: http://redis.io/topics/partitioning

Git,SVN的优缺点及适合的范围,开源项目?公司项目?

使用git不久,粗浅理解: 1)适用对象不同.Git适用于参与开源项目的开发者.他们由于水平高,更在乎的是效率而不是易用性.Svn则不同,它适合普通的公司开发团队.使用起来更加容易. 2)使用的场合不同.Git适用于通过Internet,有多个开发角色的单个项目开发,Svn适合企业内部由项目经理统一协调的多个并行项目的开发. 3)权限管理策略不同.Git没有严格的权限管理控制,只要有帐号,就可以导出.导入代码,甚至执行回退操作.Svn则有严格的权限管理,可以按组.按个人进行针对某个子目录的权限控

Redis3.0集群crc16算法php客户端实现方法(php取得redis3.0集群中redis数据所在的redis分区插槽,并根据分区插槽取得分区所在redis服务器地址)

数据分区        Redis集群将数据分区后存储在多个节点上,即不同的分区存储在不同的节点上,每个节点可以存储多个分区.每个分区在Redis中也被称为"hash slot",Redis集群中总共规划了16384个分区. 例如:当集群中有3个节点时,节点A将包含0-5460分区,节点B将包含5461-10922分区,节点C将包含10923-16383分区. 每个key将会存储到一个唯一的分区中,每个分区其实就是一组key的集合,两者对应关系为:key的CRC16校验码%16384=

Golang适合高并发场景的原因分析

典型的两个现实案例: 我们先看两个用Go做消息推送的案例实际处理能力. 360消息推送的数据: 16台机器,标配:24个硬件线程,64GB内存 Linux Kernel 2.6.32 x86_64 单机80万并发连接,load 0.2~0.4,CPU 总使用率 7%~10%,内存占用20GB (res) 目前接入的产品约1280万在线用户 2分钟一次GC,停顿2秒 (1.0.3 的 GC 不给力,直接升级到 tip,再次吃螃蟹) 15亿个心跳包/天,占大多数. 京东云消息推送系统 (团队人数:4

使用socket.io+redis来实现基本的聊天室应用场景

本文根据socket.io与redis来实现基本的聊天室应用场景,主要表现于多个浏览器之间的信息同步和实时更新. 首先看下基本的应用场景:多个浏览器同时跟webServer连接,可实时获取webServer推送的数据,如显示某一项实时更新的数据,多个client之间同步消息等. 这里,需要使用到socket.io和redis的publish机制. 1, socket.io连接于浏览器和nodejs的http服务器之间,可用于二者之间同步数据. 2, redis是一种key-value的数据库,可

cardova(Phone GAP)适合应用的场景

我们公司最近在做一个项目,客户要求用最短的时间,实现Android和IOS两个版本的app开发,而功能的要求,基本上是把一个在线的Web系统给移动终端化.所以我们最后决定使用Cardova来实现,一方面我们认为他们要求的功能和本地设备的关联较小,对实际的及时性和效率要求不太高,另外一个方面.要求周期短,时间成本浪费不起.所以Cardova应该是最理想的选择.Cardova的优势是一次性编码,可以同时生成Android.IOS.WinPhone等多个版本,开发效率极高,而且使用HTML+CSS+j

Redis 分区

分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集. 分区的优势 通过利用多台计算机内存的和值,允许我们构造更大的数据库. 通过多核和多台计算机,允许我们扩展计算能力:通过多台计算机和网络适配器,允许我们扩展网络带宽. 分区的不足 redis的一些特性在分区方面表现的不是很好: 涉及多个key的操作通常是不被支持的.举例来说,当两个set映射到不同的redis实例上时,你就不能对这两个set执行交集操作. 涉及多个key的redis事务不能使用. 当使用分区时,数据

第十一课——codis-server的高可用,对比codis和redis cluster的优缺点

[作业描述] 1.配置codis-ha 2.总结对比codis的集群方式和redis的cluster集群的优缺点 ================================================================================= 一.codis-ha的部署配置 ##codis-ha要独立于codis集群,单独配置,也是基于go环境的 1.go方式下载codis-ha: go get github.com/ngaut/codis-ha 2.进入cod

Redis分区

分区 分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集. 分区的优势 通过利用多台计算机内存的和值,允许我们构造更大的数据库. 通过多核和多台计算机,允许我们扩展计算能力:通过多台计算机和网络适配器,允许我们扩展网络带宽. 分区的不足 redis的一些特性在分区方面表现的不是很好: 涉及多个key的操作通常是不被支持的.举例来说,当两个set映射到不同的redis实例上时,你就不能对这两个set执行交集操作. 涉及多个key的redis事务不能使用. 当使用分区时