日常开发中,总会接触到一些好玩的东西,比如这篇的redis,一说到redis,可能就有人跟memcache做比较了,是呀,
memcache只能说是简单的kv内存数据结构,而redis支持的数据类型就丰富多了,当然最能让人看上眼的就是SortedSet。
有了它,我们就可以玩一些“贪心”的问题,比如适合“贪心”的优先队列,说到优先队列,我们以前实现了仅仅是内存形式的,
哎,内存毕竟是内存,当有海量数据的时候,最好能有一个序列化到硬盘的操作。。。恰恰这个场景redis就可以办到。。。
一:快速搭建
好了,我们知道redis比较适合做的事情了,现在我们可以进行快速搭建。
第一步:下载redis-2.0.2.zip (32 bit)。然后改名为redis放在D盘中。
最重要的也就是下面两个:
redis-server.exe: 这个就是redis的服务端程序。
redis-cli.exe: 服务端开启后,我们的客户端就可以输入各种命令测试了。
从图中我们可以看到两点:
①:没有指定config file。
原来redis建议我们做一个配置文件,那我就搞段配置。
daemonize: 是否以“守护进程”的方式开启,当是守护进程的时候就不受控制台的影响了。
logfile: log文件位置。
database: 开启数据库的个数。
dbfilename: 数据快照文件名。
save * *: 保存快照的频率,第一个为时间,第二个为写操作。
将这些配置好后,我们再看看:
②:我们看到redis默认的开放端口为6379。
二:安装驱动
好了,redis已经搭建完毕了,现在我们就要用C#去操作redis,这也是我最渴望的功能,优先队列~,先下载C#驱动,
就可以看到如下3个dll。
最后我们做下小测试:
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 var client = new RedisClient("127.0.0.1", 6379);
6
7 //最后一个参数为我们排序的依据
8 var s = client.AddItemToSortedSet("12", "百度", 400);
9
10 client.AddItemToSortedSet("12", "谷歌", 300);
11 client.AddItemToSortedSet("12", "阿里", 200);
12 client.AddItemToSortedSet("12", "新浪", 100);
13 client.AddItemToSortedSet("12", "人人", 500);
14
15 //升序获取最一个值:"新浪"
16 var list = client.GetRangeFromSortedSet("12", 0, 0);
17
18 foreach (var item in list)
19 {
20 Console.WriteLine(item);
21 }
22
23 //降序获取最一个值:"人人"
24 list = client.GetRangeFromSortedSetDesc("12", 0, 0);
25
26 foreach (var item in list)
27 {
28 Console.WriteLine(item);
29 }
30
31 Console.Read();
32 }
33 }
AddItemToSortedSet: 第三个参数也就是我们要排序的依据,这也非常适合我们做topK的问题,非常爽~
本文链接
db.getCollection("mobiles").ensureIndex({
"params.name": 1,
"params.value": 1
});
db.getCollection("mobiles").insert({
"_id": 1, www.jokedu.com
"name": "ME525",
"brand": "摩托罗拉",
"params": [
{"name": "待机时间", "value": 200},
{"name": "外观设计", "value": "直板"}
]
});
db.getCollection("mobiles").insert({
"_id": 2,
"name": "E7",
"brand": "诺基亚",
"params": [ www.yzjxsp.com
{"name": "待机时间", "value": 500},
{"name": "外观设计", "value": "滑盖"}
]
});
如果想查询待机时间大于100小时,并且外观设计是直板的手机,需要按照如下方式查询:
db.getCollection("mobiles").find({
"params": {
$all: [
{$elemMatch: {"name": "待机时间", "value": {$gt: 100}}},
{$elemMatch: {"name": "外观设计", "value": "直板"}}
]
}
});
注:查询中用到的$all,$elemMatch等高级用法的详细介绍请参考官方文档中相关说明。
本文链接
随着用户内容的增长,所生成、处理、分析和归档的数据的规模快速增大,类型也快速增多。此外,一些新数据源也在生成大量数据,比如传感器、全球定位系统(GPS)、自动追踪器和监控系统。这些大数据集通常被称为大数据。数据不仅仅快速增长,而且半结构化和稀疏的趋势也很明显。这样一来,预定义好schema和利用关系型引用的传统数据管理技术就受到了挑战。
在探索海量数据和半结构化数据相关问题的过程中,诞生了一系列新型数据库产品,其中包括列族数据库(column-oriented data store)、键/值数据库和文档数据库,这些数据库统称NoSQL。
今天NoSQL泛指这样一类数据库和数据存储,它们不遵循经典RDBMS原理,且常与Web规模的大型数据集有关。换句话说,NoSQL并不单指一个产品或一种技术,它代表一族产品,以及一系列不同的、有时相互关联的、有关数据存储及处理的概念。
RDBMS假定数据的结构已明确定义,数据是致密的,并且很大程度上是一致的。RDBMS构建在这样的先决条件上,即数据的属性可以预先定义好,它们之间的相互关系非常稳固且被系统地引用(systematically referenced)。它还假定定义在数据上的索引能保持一致性,能统一应用以提高查询的速度。RDBMS可以容忍一定程度的不规律和结构缺乏,但在松散结构的海量稀疏数据面前,传统存储机制和访问方法捉襟见肘。
NoSQL缓解了RDBMS引发的问题并降低了处理海量稀疏数据的难度,但是反过来也被夺去了事务完整性的力量和灵活的索引及查询能力。
总之,NoSQL数据库是非常高效、强大的海量数据存储与处理工具。大部分NoSQL数据库都能很好地适应数据增长,并且能灵活适应半结构化数据和稀疏数据集。
背景和历史
Google建造了大规模可扩展的基础设施,用于支撑Google的搜索引擎和其他应用。其策略是在应用程序栈的每个层面上分别解决问题,旨在建立一套可伸缩的基础设施来并行处理海量数据。为此Google创建了一整套完备的机制,包括分布式文件系统、面向列族的数据存储、分布式协调系统和基于MapReduce的并行算法执行环境。
Google公开发布了一系列论文来解释其基础设施中一些关键的组成部分:
Sanjay Ghemawat、Howard Gobioff和Shun-Tak Leung,“The Google File System”; pub.19th ACM Symposium on Operating Systems Principles, Lake George, NY, October 2003
Jeffrey Dean和Sanjay Ghemawat,“MapReduce: Simplified Data Processing on Large Clusters”; pub. OSDI’04: Sixth Symposium on Operating System Design and Implementation, San Francisco, CA, December 2004。
Fay Chang、Jeffrey Dean、Sanjay Ghemawat、Wilson C. Hsieh、Deborah A. Wallach、Mike Burrows、Tushar Chandra、Andrew Fikes和Robert E. Gruber,“Bigtable: A Distributed Storage System for Structured Data”; pub. OSDI’06: Seventh Symposium on Operating System Design and Implementation, Seattle, WA, November 2006。
Mike Burrows,“The Chubby Lock Service for Loosely-Coupled Distributed Systems”; pub.OSDI’06: Seventh Symposium on Operating System Design and Implementation, Seattle, WA, November 2006。
Google 云端三大天王分別是: The Google File System, MapReduce, Bigtable
下面是中文翻译版
GFS: http://blog.csdn.net/xuleicsu/archive/2005/11/10/526386.aspx
MapReduce: http://blog.csdn.net/active1001/archive/2007/07/02/1675920.aspx
BigTale: http://blog.csdn.net/accesine960/archive/2006/02/09/595628.aspx
Google公布设计理念引起了开源开发者的广泛关注和浓厚兴趣。很快,第一个模仿Google基础设施部分特性的开源软件就开发出来了,它的创建者正是开源搜索引擎Lucene的发明人。紧接着,Lucene的核心开发者们加入了Yahoo!,在那里,依靠众多开源贡献者的支持,参照Google的分布式计算架构,开发者们创建出了一个能够替代Google基础设施所有部分的开源产品,这就是Hadoop及其子项目和相关项目。
Google的论文激发了人们对并行大规模处理和分布式非关系型数据存储的兴趣,一年后,Amazon分享了他们的成功经验。2007年Amazon对外展示了它的分布式高可用、最终一致性数据存储,其名曰Dynamo。
有关Amazon Dynamo的内容可以参考如下论文:
Giuseppe DeCandia, Deniz Hastorun, Madan Jampani, Gunavardhan Kakulapati, Avinash Lakshman, Alex Pilchin, Swami Sivasubramanian, Peter Vosshall, and Werner Vogels,“Dynamo: Amazon’s Highly Available Key/value Store,”in the Proceedings of the 21st ACM Symposium on Operating Systems Principles, Stevenson, WA, October 2007。(中文版:点击下载)
此外,Amazon的CTO Werner Vogels在一篇博文中解释了Amazon Dynamo背后的关键思想,博文地址为:http://www.allthingsdistributed.com/2007/10/amazons_dynamo.html
大数据
就现在而言,任何超过几个TB大小的数据集都可以归为大数据。这是数据集大到开始跨越多个存储单元的典型尺寸,也是传统RDBMS技术开始表现出吃力的尺寸。
随着数据规模的增长和数据创建来源的日趋多元化,以下挑战将日益严峻。
·高效存储和访问大量数据很难。额外要求的容错和备份使事情变得更加复杂。
·操作大数据集涉及大量并行进程。运行过程中要从任何故障中平稳恢复过来,同时还要在合理的时间范围内返回结果,这非常复杂。
·各种不同数据源生成的半结构化和无结构数据的schema和元数据持续不断变化,对它们的管理是一个令人头疼的问题。
可扩展性
可扩展性是一种能力,有了它系统能通过增加资源提高吞吐量进而解决增加的负荷。可扩展性可以通过两种方式实现,一是配置一个大而强的资源来满足额外的需求,二是依靠由普通机器组成的集群。使用大而强的机器通常属于垂直可扩展性。典型的垂直扩展方案是使用配有大量CPU内核且直接挂载大量存储的超级计算机。这类超级计算机通常极其昂贵,属于专有设备。替代垂直扩展的是水平扩展。水平扩展使用商业系统集群,集群随负载的增加而扩展。水平扩展通常需要添加额外的节点来应付额外的负载。大数据以及大规模并行处理数据的需要促使水平扩展得到了广泛的采纳。在Google、Amazon、Facebook、eBay和Yahoo!,水平扩展的基础设施包含数量巨大的服务器,其中一些包含几千甚至几十万台服务器。
对水平扩展集群上分布的数据进行处理是非常复杂的事情。在水平集群上处理大规模数据的方法里,MapReduce模型可能要算是最好的。
MapReduce
MapReduce这种并行编程模型支持在水平集群上对大规模数据集进行分布式处理。MapReduce框架是Google的专利,但其核心思想可以自由分享,一些开源实现已经采纳了这些思想。
MapReduce的创意和灵感来源于函数式编程。map和reduce是函数式编程中两个常用函数。在函数式编程中,map函数对列表的每个元素执行操作或函数。例如,在列表[1, 2, 3, 4]上执行multiple-by-two函数会产生另一个列表[2, 4, 6, 8]。执行这些函数时,原有列表不会被修改。函数式编程认为应当保持数据不可变,避免在多个进程或线程间共享数据。这意味着刚演示过的map函数虽然很简单,却可以通过两个或更多线程在同一个列表上同时执行,线程之间互不影响,因为列表本身没有改变。
与map函数类似,函数式编程中还有一个reduce函数的概念。实际上,reduce在函数式编程中更广为人知的名字是fold函数。reduce或fold函数又称accumulate、compress或者inject函数。reduce或fold函数对数据结构(例如列表)中的所有元素执行一个函数,最终返回单个结果或输出。因此在map函数输出列表[2, 4, 6, 8]上执行reduce求和,会得到单个输出值20。
map和reduce函数可以结合起来处理列表数据,先对列表的每个成员执行一个函数,再对转换生成的列表执行另一个聚合函数。
map和reduce这种简洁的思路可以用在大数据集上,只需稍事修改以适应由元组(tuple)或键/值对组成的集合即可。map函数对集合中的每组键/值对执行函数并产生一个新集合,接着reduce函数对新生成的集合执行聚合以计算最终结果。