Redis 键值数据库中持久化对象

395 阅读10分钟

这是我参与更文挑战的第1天,活动详情查看: 更文挑战

Redis 键值数据库中持久化对象

摘要——本文介绍了一种持久化对象的方法在 Redis 中提供了键值数据库。模式专注于竞争和失败条件下对象的一致性。提议的模式对云存储实现很有用需要速度和可扩展性。 一、简介最近开始的“NoSQL 运动”带来了对键值数据库或存储的大量关注(从现在开始在 KVS 上)。云 Web 应用程序需要快速请求和使用关系数据库(从现在开始 RDBMS)有时可能是架构中的主要瓶颈 3 。然而,这并不意味着 RDBMS 应该是避免了。问题是它们被用作泛型每个问题的构建块。简化的 KVS 带来速度快,而且提供的也很少。这导致重大转变从数据持久层到开发人员的责任。NoSQL 很容易理解为反 SQL,但它应该可以理解为“不仅是SQL”。KVS 不适合取代关系数据库,但提供更好的方法满足非功能性需求,尤其是在云中架构。这些数据库或商店无法提供ACID 风格的交易。但是,对象持久化需要保持一致。这可以通过良好的在架构中实现的设计模式和组件级别。在本文中,示例模式为给出了在 KVS 中存储对象并在某种程度上进行了比较到 RDBMS 持久性。本文的其余部分组织如下:首先云应用程序架构的一些背景和给出了 KVS 的关键概念。KVS的一些比较针对 RDBMS 也完成了。然后介绍对象给出了 KVS 中的持久性。在这些主要原则之后在对象持久化方面,不同的 KVS 实现是简单比较然后Redis KVS的关键概念被解释。一个Redis特定的对象实现持久性用伪代码示例来说明。在最后一部分的实现进行了评估和示例与 ActiveRedis 一起使用(Ruby on Rails 对象持久性)库)与粗略的性能测试一起显示。

二、一个RCHITECTURAL动机Web 应用程序需要尽可能快地处理请求可能的。大多数请求主要由读取组成从数据库。Brewers CAP 定理说,在分布式环境,如云,我们有三个要求-评论:一致性、可用性和分区容错性,但是我们只能拥有这三个中的两个。这是什么意思是系统对数据的操作需要一致,它必须可供用户使用,并且必须存储数据在多个位置。为了满足这三者,我们可以选择两个并通过变通方法解决第三个要求。而不是编写我们的应用程序来满足 ACID 要求 -ment(原子性、一致性、持久性和隔离性)我们使用 BASE 方法编写我们的架构((基本上可用、软状态和最终一致) 。这意味着我们尽最大努力保持数据可用,但对于例如,如果某些网络链接出现故障,我们仍然提供服务我们可以访问的数据。对数据的修改是保证最终执行,例如通过推迟将操作写入作业队列。由于网络的性质请求是独立的并且有一些他们之间的时间,这种方法可以非常成功。在架构级别上删除 ACID 还为我们提供了也有机会将其删除到数据库级别。这是KVS 选项变得有趣的地方。通常大部分操作是读取和扩展 Web 应用程序手段扩大读取。

三、KVS VS关系型数据库RDBMS 在修改时必须满足 ACID 要求 -数据。这使得分区数据跨不同物理位置很难,因为数据需要全部写入OK 之前的位置可以返回。还有写操作往往因为硬盘IO成为瓶颈。RDBMS 也有固定的模式,这可以例如导致带有大量未使用列的臃肿表格设计。KVS 的设计非常简单。可以保存一个值用唯一的密钥。该值可以稍后加载同样的钥匙。这通常称为散列寻址R.Morris在 1968 年已经描述过。KV 不积极支持关系或全文查询,但可以更好匹配某些情况。这种情况的例子是存储操作数据、元数据、日志记录、消息队列、缓存和提供预先计算的数据。一种方法实现 KVS 是将密钥存储在内存中并持久化要异步归档的数据集。当 KVS 服务器处于重新启动,所有数据都从该文件加载到内存中。与 KVS 相比,RDBMS 具有明显的优势:它们是测试良好,有良好的管理工具和编程可用的模式。另一方面,键值是公平的新的,他们每个人都有不同的方法并且只擅长在一个非常狭窄的部分 有时 RDBMS 和 KVS 之间的区别几乎不存在。例如在使用 MySQL 时通过索引主键,它可以非常好地执行并且根据需要也可以比分区更容易当前的 KVS 实现。还有一些操作,比如在应用程序级别进行排序可以更快数据适合那个。没有单一的技术实现可扩展的系统。这样的系统必须结合不同的技术和建筑设计。开发人员熟悉 RDBMS 和事实作为成熟的系统,它们更容易理解,可能有足够的理由不考虑 KVS 选项。另一方面,可扩展性要求可能会迫使考虑一下。

四、PERSISTING对象KVS对象传统上持久存在于 RDBMS 中,对象是关系映射器 (ORM)。虽然 KVS 实现不同,对于持久性有一些共同的要求。A. 对象对象是在宿主中实现的类的实例语。由于对象和方法等的结构在代码,实体本身由其唯一标识符定义,并且属性值。简单的属性类型,如字符串、整数、布尔值和浮点数适合存储在 KVS 中。对象的集合可以定义为唯一标识符。从这些标识符我们可以得到所有创建这些对象所需的数据库中的属性。可以使用以下键存储对象属性 -值对 ClassName:Identifier:AttributeName ⇒ 值。示例:具有两个属性作为单独键的汽车汽车:34:颜色 ⇒ 绿色汽车 ,速度 ⇒ 120这种方法可能有问题,如下所述部分。B. 对象的一致性读取和写入的并发使以前的方法有问题,因为 KVS 不提供相同类型的传输我们在 RDBMS 世界中习惯的操作。如果这是不考虑,它可能导致潜在的不一致。为了示例在属性读取操作期间,并发更新操作可以修改同一个对象。当对象返回到应用程序,它可以有一些旧的和一些新的价值观。此外,当删除一个对象时,有可能执行被终止,例如电源故障和只有部分属性被删除。C. 适配器的动机KVS之间需要对象持久化适配器和应用程序,即使操作是微不足道的。使用应用程序和 KVS 之间的适配器有助于避免竞争条件和其他编程错误。也有可能利用为某些 ORM 设计的组件KVS 适配器实现它时的接口。D. 无模式数据模型并非所有实例都完全具有与其他人相同的属性。有些可能有属性只存在于所有对象中的少数。无模式数据模型在开发阶段很有用,但也有趣的生产。例如,管理员可以为某些实例动态添加属性,并且应用程序可以设计为仅显示这些属性存在于实例中。无模式方法确实如果架构是设计好的,则不必等同于混乱支持它。中提供了一个简单的例子评价章节。V. K EY -值存储KVS 有不同的实现,大多数其中一些还没有完全成熟。云服务有定义了一系列新问题,就像 Facebook 的先驱者一样亚马逊正在用自己的方式解决这些问题Cassandra 和 Dynamo 等分布式实现。这些分布式的大规模 KVS 已被证明是有效的对他们来说很好,但规模较小(不是很大)Web 应用程序它们可能太重了。我们得到的东西授予 RDBMS 之类的索引数据,提供查询语言和观点目前正在研究中 。较小规模的 KVS 实现包括例如CouchDB、MongoDB 和 Redis。他们各不相同其他,适用于不同类型的任务。例如MongoDB 提供了类似查询语言的关系型数据库本质上是一个文档数据库。所有这三个支持数据的分区和复制等级。大多数实验对象持久性适配器是可用于所有实现。

五、Redis 不支持复杂的查询或索引,但支持数据结构作为值。很简单,它也是许多人最快的 KVS 实现基本操作。速度和数据结构很有趣可用于简单对象持久性的组合。Redis 中的数据结构通常称为Redis数据类型。这些包括字符串、列表、集合、排序集合和哈希。Redis 提供了可以用来修改的命令这些类型。例如 list 支持普通的 list 操作,像推和流行。整个数据集都保存在内存中,因此可以不超过物理 RAM 的数量。Redis 服务器写入以可配置的时间间隔将整个数据集写入磁盘。这也可以进行配置,以便始终写入每次修改磁盘前返回OK。主从复制是也可用,集群目前正在开发中。原子命令和 Redis 事务每个Redis命令都是原子执行的。对于前-充足的 INCR 命令增加键的整数值原子地。两个单独的命令不是原子的将它们与 Redis 事务结合起来。Redis 中的事务实际上是排队的命令按原子顺序执行。如果一个命令引发一个错误,队列中的所有其他命令仍然处理。Redis 在命令后开始排队命令MULTI 并在一个原子事务中执行那些执行。A. 排序集和哈希排序集类似于 RDBMS 索引。排序集包含按特殊整数值排序的成员分数。例如“ZADD Foo:all 10 10”存储值 10键 Foo:all 得分为 10。哈希是键和套装内的键值对能够存储对象属性。例如“HMSETCat:2:attributes color black age 20" 添加两个键值与键 Cat:2:attributes 配对。

六、我执行在以下实现中,每个持久化对象都有其自己唯一的整数标识符。基于此标识符的密钥Foo:id:attributes 包含对象属性被创建(假设该对象名为 Foo)。此密钥存储属性作为 Redis 哈希。当对象被创建时,一个特殊的排序集 Foo:all 更新为包含标识符。和这个“主”集可以知道对象是否被持久化或不。因为写操作是不同的原子操作,写入的并发性会导致对象不一致。