`
willko
  • 浏览: 386582 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

NoSQL数据转储(同步)方式

阅读更多
在使用数据库方面,我们经常会遇到读/写瓶颈,只要不是达到门户级的瓶颈,多数情况都能很好的解决。这段时间NoSQL的崛起,极大的方便解决写瓶颈。写瓶颈的解决方法是先把数据缓冲到NoSQl中,然后定时转储回RMDB里,毕竟RMDB的查询能力更强。所以,会遇到一个问题,就是数据怎么同步回RMDB?

假如,有这样的应用场景,我们使用了NoSQL来存储文章点击数(pv),并定时将点击数存储到MySQL里。

一.用户触发转储
首先给文章增加一个最后同步数据的时间戳,用于记录上次同步数据的时间戳,每次都先对比下最后同步时间是否大于n,大于n的话就同步回MySQL,然后将这次同步的时间戳保存回去。这个最后同步时间戳不一定要保存到MySQL里,如果使用了Memcached的话,可以保存到Memcached就可以了。

缺点:
1.如果静态化了,用户将触发不到这个机制
2.每次会有少量数据没同步到MySQL,因为没有达到时间间隔N的话就触发不了
3.并发大话,可能同一时间内会同步多次,所以要尽快保存最后同步时间戳,或者利用memcached的add方法来模拟锁,add方法如果key存在的话返回false,返回false表示被锁,可以不同步点击数。

二.Redis
Redis最明显的优势是支持数据结构,其次就是高性能。

1.Multiple DB
Redis可以更换db,一个Redis我们可以划分多个db。用于存储不同维度的数据,避免混合在一起,例如,日志相册分db存储,更管各的。

2.KEYS
KEYS可以返回所有的复合模式的Key,Redis天生对遍历Key提供了很良好的支持。

3.SADD和SMEMBERS
Redis支持set结构,可以用set结构来存储有更新的文章id,然后通过这个列表去同步数据。
SADD对于已经存在的元素是不会添加到集合中的,也就是元素在set里是唯一的。SMEMBERS可以返回set里的所有元素。
也就是说,set里只是用来保存点击数有变动的文章id,然后通过这些文章id,去其它NoSQL里读取点击数,同步到数据库。

缺点:
1.专门部署Redis似乎不太值得
2.Redis是基于定时内存转储了,可能丢失部分数据
3.Redis太依赖内存,数据大于内存,使用swap,性能下降

三.遍历Memcached
虽然遍历Memcached不是一个好的方法,但是相信有其适用的场景。使用stats items和stats cachedump能得到所有的key。

1.扩展memcache
class Memcache_Plus extends Memcache {

	public function getKeys() {
		$items = $this->getStats('items');
		$keys = array();

			$serverItems = $items['items'];

			foreach ($serverItems as $slabId => $item) {
				$slabKeys = $this->getStats('cachedump', $slabId, 0);

					foreach ($slabKeys as $slabKey => $slabKeyStatus) {
						$keys[] = $slabKey;
					}
			}

		return $keys;
	}

	public function getExtendedKeys() {
		$items = $this->getExtendedStats('items');
		$keys = array();

		foreach ($items as $server) {
			$serverItems = $server['items'];

			foreach ($serverItems as $slabId => $item) {
				$slabKeys = $this->getExtendedStats('cachedump', $slabId, 0);

				foreach ($slabKeys as $slabServer => $slabServerKeys) {
					foreach ($slabServerKeys as $slabServerKey => $slabServerKeyStatus) {
						$keys[] = $slabServerKey;
					}
				}
			}
		}

		return $keys;
	}
}}

使用:
$memcache = new Memcache_Plus;
$memcache->addServer('192.168.80.128', 11211);

$keys = $memcache->getKeys();

getKeys是返回单台服务器的key,getExtendedKeys是返回全部服务器的key。

2.扩展Memcached
到目前为止,Memcached::getStats不支持参数("items", "sizes", "slabs"...)

3.山寨socket版
写了个socket版,作为后备使用。用正则来匹配,主要是不想循环去解析每行。
function memcachedGetKeys($host, $port) {
	$keys = array();
	$fp = fsockopen($host, $port, $errno, $errstr, 30);

	if ($fp) {
		fwrite($fp, "stats items\r\n");

		$response = '';

		while (substr($response, -5) != "END\r\n" && substr($response, -5) != "ERR\r\n") {
			$response .= fread($fp, 1024);
		}

		preg_match_all("/STAT items:(\d+):/", $response, $matches);
		
		$slabIds = array_flip(array_flip($matches[1]));

		foreach ($slabIds as $slabId) {
			$response = '';

			fwrite($fp, "stats cachedump $slabId 0\r\n");

			while (substr($response, -5) != "END\r\n" && substr($response, -5) != "ERR\r\n") {
				$response .= fread($fp, 1024);
			}

			preg_match_all("/ITEM (.+) \[\d+ b; \d+ s\]/", $response, $matches);

			$keys = array_merge($keys, $matches[1]);
		}
	}
	
	return $keys;
}


缺点:
1.需要专门启动一个memcached来保存,遍历才不会有多余Key
2.memcached是保存在内存,数据丢失概率大。
3.memcached的LRU机制,内存不足的时候会导致数据被挤出

四.全量更新、增量更新以及Key的命名
1.Key的命名
因为value是用来保存点击数,我们可以用key来保存逻辑数据,这样我们可以从key来判断出属于哪篇文章,例如:前缀_文章id(article_1)、前缀_文章id_某天的日期(article_1_2010-05-01)

2.全量更新
如果只是想知道点击总数,那在统计和同步方面会比较简单,同步的时候直接全量更新就可以了。例如 UPDATE article SET view_count = ? WHERE article_id = ?

3.增量更新
有时候,我们的需求是细化到每天的点击数和总点击数,那总点击数的更新就不得不使用增量更新了,因为我们只记录了每天的点击数,没有一个总点击数,当然也可以同时递增2个key,那总点击数依然可以使用全量更新。

增量更新的话,我们只增量昨天和昨天之前的数据,因为今天的数据还在更新。同步完后可以把昨天和昨天之前的数据删除了。例如 UPDATE article SET view_count = view_count + ? WHERE article_id = ?

有时候,需要及时知道今天的数据,那今天的数据就不删除了,等到明天删除,如果是全量更新的话就很好办了。但是如果是增量更新的话,那只能在程序里加一下点击数,而不同步到MySQL里。

说了很多,需求不一致,或许不能直接解决问题,只希望提供一点思路。

参考资料:
如何对memcache的数据(key-value)进行遍历操作
2
1
分享到:
评论
9 楼 willko 2010-05-06  
nightsailer 写道
willko 写道

如果是讀取的話可以用nginx代替php讀取文件,效果會好點吧。


nginx的mogilefs module太弱,不支持etag,range,生产环境还是回避为好。
对于小文件也许问题不大,但是如果要serve 稍大的(比如》100Mb)文件就不行了。

对于小文件,我们的部署方案是nginx+proxy store+psgi backend. 效果很好。



谢谢你的分享
8 楼 nightsailer 2010-05-05  
willko 写道

如果是讀取的話可以用nginx代替php讀取文件,效果會好點吧。


nginx的mogilefs module太弱,不支持etag,range,生产环境还是回避为好。
对于小文件也许问题不大,但是如果要serve 稍大的(比如》100Mb)文件就不行了。

对于小文件,我们的部署方案是nginx+proxy store+psgi backend. 效果很好。


7 楼 willko 2010-05-05  
nightsailer 写道
GridFS最大的问题就是异步IO,尤其是PHP/Perl的driver不支持,无法streming,对于并发量很大的话,prefork模式有瓶颈。

不过node.js有相应的driver也可以解决,总体来说不太成熟。

我最近还在做这方面的尝试。

如果是讀取的話可以用nginx代替php讀取文件,效果會好點吧。
6 楼 nightsailer 2010-05-05  
GridFS最大的问题就是异步IO,尤其是PHP/Perl的driver不支持,无法streming,对于并发量很大的话,prefork模式有瓶颈。

不过node.js有相应的driver也可以解决,总体来说不太成熟。

我最近还在做这方面的尝试。
5 楼 willko 2010-05-05  
nightsailer 写道
我用tc做过一个和你类似的简单的统计。我用Perl做了一个FASTCGI,将点击数更新到tc里。tc的健就是你文章的id了,假设。然后另外用一个脚本,定时将所有的tc中的数据更新到mysql中。因为tc中永远只更新当日的数据,之后可以简单的计算后刷新总数就行了。 用2个脚本的好处是,读写两不误。很多时候我在维护mysql的同时,点击数仍然可以记录下来。

不过后来我用mongoDB替代了这个方式,更加快捷简便。

MongoDB確實是好東西,支持查詢,性能也可以,還支持sharding。
最近還在研究GirdFS的優缺點和應用場景。
4 楼 nightsailer 2010-05-05  
我用tc做过一个和你类似的简单的统计。我用Perl做了一个FASTCGI,将点击数更新到tc里。tc的健就是你文章的id了,假设。然后另外用一个脚本,定时将所有的tc中的数据更新到mysql中。因为tc中永远只更新当日的数据,之后可以简单的计算后刷新总数就行了。 用2个脚本的好处是,读写两不误。很多时候我在维护mysql的同时,点击数仍然可以记录下来。

不过后来我用mongoDB替代了这个方式,更加快捷简便。
3 楼 willko 2010-05-04  
nightsailer 写道
使用memcached不是一个好的方式。可以考虑Flare/TT。

如果仅仅是更新点击数的话完全可以用tc,然后刷新到mysql。

整体方案太繁琐了,似乎无需同步回mysq,仅仅是出于排序的目的?



这些方案是分开来的,可能是用一种就够了,看场合了。
比较像知道如果用tc的话,怎么同步回去?

之前问过MemcacheDB的作者,是用BDB工具导出一份,然后倒入MySQL。
2 楼 willko 2010-05-04  
nightsailer 写道
使用memcached不是一个好的方式。可以考虑Flare/TT。

如果仅仅是更新点击数的话完全可以用tc,然后刷新到mysql。

整体方案太繁琐了,似乎无需同步回mysq,仅仅是出于排序的目的?



只是一个例子,想讲的是一些可以考虑的方式。并不单指“点击数”
也就是从NoSQL同步到MySQL一些方式。
1 楼 nightsailer 2010-05-04  
使用memcached不是一个好的方式。可以考虑Flare/TT。

如果仅仅是更新点击数的话完全可以用tc,然后刷新到mysql。

整体方案太繁琐了,似乎无需同步回mysq,仅仅是出于排序的目的?


相关推荐

    canal 的 mysql 与 redis/memcached/mongodb 的 nosql 数据实时同步方案

    标题中的“canal”的MySQL与“redis/memcached/mongodb”的NoSQL数据实时同步方案,主要涉及了数据库间的数据迁移和实时同步技术。这个话题涵盖了多个关键知识点,包括: 1. **Canal**: Canal是阿里巴巴开源的一个...

    cpp-基于canal的mysql与redismemcachedmongodb的nosql数据实时同步方案案例canalclient

    标题中的“cpp-基于canal的mysql与redismemcachedmongodb的nosql数据实时同步方案案例canalclient”指的是一个使用C++实现的项目,它利用了阿里巴巴开源的Canal工具来实现实时同步MySQL数据库的数据到NoSQL数据库,...

    NoSQL数据处理方式.pdf

    CAP理念指导下的灵活数据管理,多样化的存储模式和高效的数据处理方式,使得NoSQL数据库在大数据时代成为不可或缺的一部分。对于开发者而言,选择合适的NoSQL数据库并根据CAP理论合理配置,可以最大化地提升应用性能...

    NoSQL数据管理技术

    NoSQL全称为Not Only SQL,意即不仅仅是SQL,这种数据库通常不使用传统的SQL语句作为查询语言,而是采用更加灵活的方式来存取数据。 NoSQL的数据模型主要包括键值存储(Key-Value)、文档存储(Document)、列存储...

    NoSQL技术在气象传感器数据处理中的应用.pdf

    NoSQL技术在气象传感器数据处理中的应用 一、NoSQL技术概述 NoSQL技术是指一种新的数据存储和处理技术,它不同于传统的关系数据库管理系统(RDBMS)。NoSQL技术的主要特点是其 schema-free 的设计、分布式存储、...

    nosql与大数据

    大数据是指那些规模巨大、增长迅速、种类繁多且处理复杂的数据集合,而NoSQL则是为了解决传统关系型数据库在处理大数据时面临的挑战而诞生的一种新型数据库管理系统。 一、大数据的特点 1. **大量性(Volume)**:...

    基于NoSQL的大数据处理的研究

    基于NoSQL的大数据处理的研究

    Python-SHDB一个专为Shell脚本提供数据存储支持的NoSql数据

    2. **非关系型**:作为NoSql数据库,SHDB支持键值对、文档型、列族或图形等多种数据模型,适合存储结构各异的数据。 3. **轻量级**:SHDB的体积小,对系统资源的需求低,适合在资源有限的环境中运行。 4. **可移植性...

    【Java分布式事务】封装对MySQL NoSQL数据访问、实现分布式事务.zip

    【Java分布式事务】封装对MySQL NoSQL数据访问、实现分布式事务.zip 【Java分布式事务】封装对MySQL NoSQL数据访问、实现分布式事务.zip 【Java分布式事务】封装对MySQL NoSQL数据访问、实现分布式事务.zip 【Java...

    Android-Iron-一个快速和易用的NoSQL数据存储框架包含RxJava支持

    6. **备份与恢复**:Iron提供数据备份和恢复的功能,方便用户在不同设备间同步数据或应对数据丢失情况。 **优化与性能** Iron框架优化了数据读写速度,通过缓存机制减少不必要的磁盘IO,提高性能。此外,它的数据...

    NoSQL数据笔谈

    列存储是NoSQL数据库中常见的一种数据存储方式,它按照列族而非行来组织数据,特别适合于大数据分析场景,如HBase就采用了这种方式。 #### 十五、软件篇 NoSQL数据库领域有多种不同的实现,包括但不限于: - **...

    nosql研发之路

    最后,结合业务场景进行深度定制和优化,如利用NoSQL数据库的复制协议进行数据同步、故障恢复等,充分发挥NoSQL数据库的优势,为应用提供强有力的支持。 总之,NoSQL数据库的发展历程和技术特点,使其在特定领域...

    当当网排行榜爬虫+nosql数据分析

    爬取当当网排行榜并连接本地nosql数据库进行多维度数据分析

    canal_mysql_nosql_sync:基于canal的mysql与redismemcachedmongodb的nosql数据实时同步方案案例demo canal client

    基于Canal的MySql RabbitMQ Redis / memcached / mongodb的nosql同步(多读,nosql延迟不严格需求) 1.mysql主从配置 2.对mysql binlog(row) parser 这一步交给canal 3.MQ对解析后binlog增量数据的推送 4.对MQ数据...

    山东大学 nosql期末复习笔记 nosql 期末复习

    数据类型包括string、list、set、zset和hash,支持主从复制和两种持久化方式(快照和AOF)。 - **Neo4j**:适合存储节点和关系,适用于社交网络分析,提供ACID支持和高速检索。 - **HBase**:列存储,适用于大数据...

    NoSQLBooster for MongoDB

    5. **备份与恢复**:NoSQLBooster支持一键式数据库备份和恢复功能,使得数据安全得到保障,尤其是在面临系统故障或数据丢失的情况下。 6. **脚本编辑器**:对于需要运行JavaScript脚本的场景,NoSQLBooster提供了一...

    Iron,支持RXJava的快速易用NoSQL数据存储.zip

    快速易用的nosql数据存储,支持rxjava和kotlin

    NoSQL数据库入门 高清PDF

    3. **灵活的数据模型**:NoSQL数据库允许存储复杂的数据类型,如嵌套对象、数组等,这使得数据模型更加灵活多变。 4. **弱一致性**:为了提高性能,NoSQL数据库通常牺牲了一致性,采用最终一致性的原则。 #### 三、...

Global site tag (gtag.js) - Google Analytics