写点什么

NoSQL 架构实践(二)——以 NoSQL 为主

  • 2011-03-11
  • 本文字数:3247 字

    阅读完需:约 11 分钟

前面一篇《 NoSQL 架构实践(一)——以 NoSQL 为辅》主要介绍了以 NoSQL 为辅助的架构,这种架构实施起来比较简单,易于理解,由于其中也使用了传统的关系数据库,让开发者更容易控制 NoSQL 带来的风险。接下来我们继续深入下去,换另外一个角度,“以 NoSQL 为主”来架构系统。

(三)纯 NoSQL 架构

只使用 NoSQL 作为数据存储。

图 4- 纯 NoSQL 架构

在一些数据结构、查询关系非常简单的系统中,我们可以只使用 NoSQL 即可以解决存储问题。这样不但可以提高性能,还非常易于扩展。手机凤凰网的前端展示系统就使用了这种方案。

在一些数据库结构经常变化,数据结构不定的系统中,就非常适合使用NoSQL 来存储。比如监控系统中的监控信息的存储,可能每种类型的监控信息都不太一样。这样可以避免经常对MySQL 进行表结构调整,增加字段带来的性能问题。

这种架构的缺点就是数据直接存储在NoSQL 中,不能做关系数据库的复杂查询,如果由于需求变更,需要进行某些查询,可能无法满足,所以采用这种架构的时候需要确认未来是否会进行复杂关系查询以及如何应对。

非常幸运的是,有些NoSQL 数据库已经具有部分关系数据库的关系查询特性,他们的功能介于key-value 和关系数据库之间,却具有key-value 数据库的性能,基本能满足绝大部分web 2.0 网站的查询需求。比如:

MongoDB就带有关系查询的功能,能解决常用的关系查询,所以也是一种非常不错的选择。下面是一些 MongoDB 的资料:

虽然 Foursquare 使用 MongoDB 的宕机事件的出现使人对 MongoDB 的自动 Shard 提出了质疑,但是毫无疑问,MongoDB 在 NoSQL 中,是一个优秀的数据库,其单机性能和功能确实是非常吸引人的。由于上面的例子有详细的介绍,本文就不做 MongoDB 的使用介绍。

Tokyo Tyrant数据库带有一个名为 table 的存储类型,可以对存储的数据进行关系查询和检索。一个 table 库类似于 MySQL 中的一个表。下面我们看一个小演示:

我们要存储一批用户信息,用户信息包含用户名 (name), 年龄 (age),email,最后访问时间 (lastvisit),地区 (area)。下面为写入的演示代码:

复制代码
<?php
$tt = new TokyoTyrantTable ( "127.0.0.1", 1978 );
$tt->vanish ();// 清空
$id = $tt->genUid ();// 获取一个自增 id
//put 方法提供数据写入。 put ( string $key , array $columns );
$tt->put ( $id, array ("id" => $id, "name" => "zhangsan", "age" => 27, "email" => "zhangsan@gmail.com", "lastvisit" =>strtotime ( "2011-3-5 12:30:00" ), "area" => " 北京 " ) );
$id = $tt->genUid ();
$tt->put ( $id, array ("id" => $id, "name" => "lisi", "age" => 25, "email" => "lisi@126.com", "lastvisit" => strtotime( "2011-3-3 14:40:44" ), "area" => " 北京 " ) );
$id = $tt->genUid ();
$tt->put ( $id, array ("id" => $id, "name" => "laowang", "age" => 37, "email" => "laowang@yahoo.com", "lastvisit" =>strtotime ( "2011-3-5 08:30:12" ), "area" => " 成都 " ) );
$id = $tt->genUid ();
$tt->put ( $id, array ("id" => $id, "name" => "tom", "age" => 21, "email" => "tom@hotmail.com", "lastvisit" =>strtotime ( "2010-12-10 13:12:13" ), "area" => " 天津 " ) );
$id = $tt->genUid ();
$tt->put ( $id, array ("id" => $id, "name" => "jack", "age" => 21, "email" => "jack@gmail.com", "lastvisit" =>strtotime ( "2011-02-24 20:12:55" ), "area" => " 天津 " ) );
// 循环打印数据库的所有数据库
$it = $tt->getIterator ();
foreach ( $it as $k => $v ) {
print_r ( $v );
}
?>

比如我们需要查询年龄为 21 岁的所有用户:

复制代码
<?php
$tt = new TokyoTyrantTable ( "127.0.0.1", 1978 );
$query = $tt->getQuery ();
// 查询年龄为 21 岁的用户
$query->addCond ( “age”, TokyoTyrant::RDBQC_NUMEQ, “21” );
print_r ( $query->search () );
?>

查询所有在 2011 年 3 月 5 日之后登陆的用户:

复制代码
<?php
$tt = new TokyoTyrantTable ( "127.0.0.1", 1978 );
$query = $tt->getQuery ();
$query->addCond ( “lastvisit”, TokyoTyrant::RDBQC_NUMGE, strtotime ( "2011-3-5 00:00:00" ) );
print_r ( $query->search () );
?>

从上面的示例代码可以看出,使用起来是非常简单的,甚至比 SQL 语句还要简单。 Tokyo Tyrant的表类型存储还提供了给字段建立普通索引和倒排全文索引,大大增强了其检索功能和检索的性能。

所以,完全用 NoSQL 来构建部分系统,是完全可能的。配合部分带有关系查询功能的 NoSQL,在开发上比 MySQL 数据库更加快速和高效。

(四)以 NoSQL 为数据源的架构

数据直接写入 NoSQL,再通过 NoSQL 同步协议复制到其他存储。根据应用的逻辑来决定去相应的存储获取数据。

图 5 - 以 NoSQL 为数据源

纯 NoSQL 的架构虽然结构简单,易于开发,但是在应付需求的变更、稳定性和可靠性上,总是给开发人员一种风险难于控制的感觉。为了降低风险,系统的功能不局限在 NoSQL 的简单功能上,我们可以使用以 NoSQL 为数据源的架构。

在这种架构中,应用程序只负责把数据直接写入到 NoSQL 数据库就 OK,然后通过 NoSQL 的复制协议,把 NoSQL 数据的每次写入,更新,删除操作都复制到 MySQL 数据库中。同 时,也可以通过复制协议把数据同步复制到全文检索实现强大的检索功能。在海量数据下面,我们也可以根据不同的规则,把数据同步复制到设计好的分表分库的 MySQL 中。这种架构:

  • 非常灵活。可以非常方便的在线上系统运行过程中进行数据的调整,比如调整分库分表的规则、要添加一种新的存储类型等等。
  • 操作简单。只需要写入 NoSQL 数据库源,应用程序就不用管了。需要增加存储类型或者调整存储规则的时候,只需要增加同步的数据存储,调整同步规则即可,无需更改应用程序的代码。
  • 性能高。数据的写入和更新直接操作 NoSQL,实现了写的高性能。而通过同步协议,把数据复制到各种适合查询类型的存储中(按照业务逻辑区分不同的存储),能实现查询的高性能,不像以前 MySQL 一种数据库就全包了。或者就一个表负责跟这个表相关的所有的查询,现在可以把一个表的数据复制到各种存储,让各种存储用自己的长处来对外服务。
  • 易扩展。开发人员只需要关心写入 NoSQL 数据库。数据的扩展可以方便的在后端由复制协议根据规则来完成。

这种架构需要考虑数据复制的延迟问题,这跟使用 MySQL 的 master-salve 模式的延迟问题是一样的,解决方法也一样。

在这种以 NoSQL 为数据源的架构中,最核心的就是 NoSQL 数据库的复制功能的实现。而当前的几乎所有的 NoSQL 都没有提供比较易于使用的复制接口来完成这种架构,对 NoSQL 进行复制协议的二次开发,需要更高的技术水平,所以这种架构看起来很好,但是却不是非常容易实现的。我的开源项目 PHPBuffer 中有个实现 Tokyo Tyrant 复制的例子,虽然是 PHP 版本的,但是很容易就可以翻译成其他语言。通过这个例子的代码,可以实现从 Tokyo Tyrant 实时的复制数据到其他系统中。

总结

以 NoSQL 为主的架构应该算是对 NoSQL 的一种深度应用,整个系统的架构以及代码都不是很复杂,但是却需要一定的 NoSQL 使用经验才行。

参考链接:

关于作者

孙立,目前为去哪儿网( qunar.com ) 高级系统架构师。曾就职于凤凰网、ku6 和搜狐。多年互联网从业经验和程序开发,对分布式搜索引擎的开发,高并发,大数据量网站系统架构优化,高可用性,可伸缩性,分布式系统缓存, 数据库分表分库(sharding)等有丰富的经验,并且对运维监控和自动化运维控制有经验。是开源项目 phplock,phpbuffer 的作者。近期开发了一个 NOSQL 数据库存储 INetDB, 是 NoSQL 数据库爱好者。


感谢张凯峰对本文的策划及审校。

2011-03-11 21:1413568

评论

发布
暂无评论
发现更多内容

云图说|云上攻击早知道,少不了这个“秘密武器”!

华为云开发者联盟

安全 云服务 云端

区块链钱包APP开发,开发搭建数字货币钱包

13530558032

8.3红黑树原理与性能特性

张荣召

企业级软件的核心价值

Learun

敏捷开发 快速开发 企业开发 企业应用

函数式编程:如何高效简洁地对数据查询与变换

华为云开发者联盟

编程 面向对象 数据处理

8.2常见数据结构与Hash表原理分析

张荣召

8.4经典算法

张荣召

高性能IO模型:为什么单线程Redis能那么快?

小Q

Java redis 学习 架构 面试

飞书的「背道而驰」

ToB行业头条

用废旧纸箱DIY智能宠物喂食器!旅行在外远程投喂“二狗子”

智能物联实验室

物联网 DIY 智能硬件

数字货币交易所开发定制,币币撮合交易开发商

13530558032

区块链带来的业务流程优化是数字化转型最深层次的变革

CECBC

区块链 数字化

区块链USDT系统开发解决方案,USDT支付系统技术开发

13530558032

Mock服务设计与实现:MySQL驱动字节码修改增强

华为云开发者联盟

MySQL 数据库 sql

架构师训练营 1 期 - 第八周作业(vaik)

行之

微服务下,使用 ELK 进行日志采集以及统一处理

华为云开发者联盟

微服务 Kibana ELK

重磅发布!Flink Forward Asia 2020 在线峰会预约开启!

Apache Flink

flink

缓存与数据库一致性策略

洛神灬殇

Week 8 命题作业

阿泰

简要分析近几年商业软件开发平台的现状

Learun

企业 企业开发 企业应用

建行数字债券允许比特币交易?官方回应了!业内人士:交易架构的创新值得赞赏

CECBC

比特币 债券

区块链赋能供应链金融 | 应用优势与四类常见模式

CECBC

区块链 供应商审核

自己写歌怎么编曲?4款超好用编曲软件推荐

奈奈的杂社

编曲 音频制作 midi daw

8.1文件与磁盘IO:如何把磁盘的读写速度提升十万倍?

张荣召

架构师第一期作业(第8周)

Cheer

作业

阿里P10带你深度剖析:淘宝网是如何基于Spring Cloud微服务框架搭建大型电商平台设计

Java架构追梦

Java 架构 面试 微服务 SpringCloud

数字货币合约交易所系统开发技术

薇電13242772558

区块链 数字货币

企业级软件的核心价值

Marilyn

敏捷开发

简要分析近几年商业软件开发平台的现状

Marilyn

快速开发 企业开发

技术分析:AnalyticDB强力支撑双11

数据库 互联网 数据分析 双十一 数据舱

作业--week08

张荣召

NoSQL架构实践(二)——以NoSQL为主_Java_孙立_InfoQ精选文章