数据库前沿趋势抢先看,尽在 3 月 25 日 OceanBase 开发者大会!报名戳 了解详情
写点什么

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:1413539

评论

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

DAPP开发丨流动性质押智能合约系统开发

l8l259l3365

轻松解决企业数据高延时,华为云全球加速GA使用更灵活!

科技之光

【低成本“上云”】华为云ECS,助力企业数字化转型!

科技说

华为云ECS,最专业的云服务专家

科技说

同是弹性公网IP,华为云弹性公网IP的优势有哪些?

科技说

react源码中的协调与调度

flyzz177

React

远程办公小助手——华为云虚拟专用网络VPN

爱尚科技

架构训练营 模块四

张建闯

架构实战营

华为云全球加速GA,敲开企业跨境业务的大门

科技之光

华为云弹性云服务器ECS,助力企业业务持续稳定运行

科技说

耳东的2022 年度总结

耳东@Erdong

年度总结

react源码中的生命周期和事件系统

flyzz177

React

华为云虚拟专用网络VPN,如何解决企业出海难题

爱尚科技

SCQA模型

印無印

表达 讲故事能力

React源码分析8-状态更新的优先级机制

flyzz177

React

react源码中的hooks

flyzz177

React

React源码分析8-状态更新的优先级机制

flyzz177

React

前端工程师leetcode算法面试必备-二分搜索算法(中)

js2030code

JavaScript LeetCode

华为云虚拟专用网络VPN,为企业铺就数据上云的安全路

爱尚科技

【深入浅出Sentinel原理及实战】「基础实战专题」零基础实现服务流量控制实战开发指南(2)

洛神灬殇

微服务 Alibaba Alibaba技术 1月日更 Sentinel 系统

华为云弹性云服务器,助推多行业数字化转型

科技说

5分钟搞懂分布式可观测性

俞凡

架构 微服务 最佳实践 云原生

前端工程师leetcode算法面试必备-二分搜索算法(下)

js2030code

JavaScript LeetCode

拒绝内卷挖掘境外新蓝海,华为云虚拟专用网络VPN有多特别?

爱尚科技

10 分钟带你一览 SOFAStack 的 2022!

SOFAStack

开源 云原生 中间件

从非洲到全球,看华为云连接CC如何助力出海企业更好发展

科技之光

大数据时代来临,华为云ECS为企业释放数据生产力

科技说

深入理解 Linux 物理内存分配全链路实现

bin的技术小屋

Linux 操作系统 内核 内存分配

华为云VPN为企业数据上云保驾护航

爱尚科技

华为云全球加速GA,赋能现代企业出海加速发展

科技之光

华为云全球加速GA的“加速”,你真的了解嘛?

科技之光

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