一、问题:

    数据库表数据量极大(千万条),要求让服务器更加快速地响应用户的需求。

二、解决方案:

     1.通过高速服务器Cache缓存数据库数据

     2.内存数据库

  (这里仅从数据缓存方面考虑,当然,后期可以采用Hadoop+HBase+Hive等分布式存储分析平台)

三、主流数据库对比

redis实现mongo自增 redis mongodb memcache_数据

 

上述技术基本上代表了当今在数据存储方面的实现方案,其中主要涉及到了关系型数据库(Mysql/PostgreSql),NoSql数据库(MongoDB),内存数据库(redis),内存cache(Memcached)。如果需要对大数据表仍保持高效的查询速度,普通关系型数据库是无法满足的。而MongoDB其实只是一种非关系型数据库,其优势在于可以存储海量数据,具备强大的查询功能,因此不宜用于缓存数据的场景。

 

四、下面重点分析Memcached和Redis两种方案:

4.1 Memcached介绍  

Memcached是一个高效的分布式内存对象缓存系统,用于动态web应用以减轻数据库负载,它通过内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。现在已经被Facebook,Vox等公司所使用。

4.1.1 Memcached工作方式分析

   许多Web应用都将数据保存到 RDBMS中,应用服务器从中读取数据并在浏览器中显示。 但随着数据量的增大、访问的集中,就会出现RDBMS的负担加重、数据库响应恶化、 网站显示延迟等重大影响。Memcached是高性能的分布式内存缓存服务器,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web等应用的速度、 提高可扩展性。下图展示了memcache与数据库端协同工作情况:

redis实现mongo自增 redis mongodb memcache_数据_02

1

检查用户请求的数据缓存中是否存在,如果存在,则直接返回给用户,无需查询数据库

2

如果缓存中找不到,则需要去查询数据库,在把请求数据返回给用户的同时,也需要把数据库缓存到缓存中一份。

3

保持缓存的“新鲜性”,每当数据发生变化时,需要同步的更新缓存信息,确保用户不会从缓存中取到旧的数据。

 

 

  Memcached作为高速运行的分布式缓存服务器,具有以下的特点: 

o   协议简单 

o   基于libevent的事件处理 

o   内置内存存储方式

o   memcached不互相通信的分布式

4.1.2 如何实现分布式可拓展性

Memcached的分布式不是在服务器端实现的,而是在客户端应用中实现的,即通过内置算法制定目标数据的节点,如下图所示:

redis实现mongo自增 redis mongodb memcache_Redis_03

4.2 redis介绍

 Redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、 list(链表)、set(集合)和zset(有序集合)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步,当前 Redis的应用已经非常广泛,国内像新浪、淘宝,国外像 Flickr、Github等均在使用Redis的缓存服务。

4.2.1 Redis工作方式:

Redis作为一个高性能的key-value数据库具有与以下特征:

(1)   多样的数据类型;

(2)      支持持久化

(3)      主从同步吧

(4)      集群

Redis支持丰富的数据类型,最为常用的数据类型有5中:string,hash,list,set,sorted set。Redis通常将数据存储在内存中,但是其具有一个很重要的特征就是可以支持数据持久化,支持RDB和AOF两种方式。

4.2.2 Redis如何实现分布式可拓展性

相较于Memcached只能采用客户端实现分布式存储,Redis则在服务器端构建分布式存储。Redis Cluster是一个实现了分布式且允许单点故障的Redis高级版本,它没有中心节点,各个节点地位一致,具有线性可伸缩的功能。如图给出Redis Cluster的分布式存储架构,其中节点与节点之间通过二进制协议进行通信,节点与客户端之间通过ascii协议进行通信。在数据的放置策略上,Redis Cluster将整个 key的数值域分成16384个哈希槽,每个节点上可以存储一个或多个哈希槽,也就是说当前Redis Cluster支持的最大节点数就是16384。

4.2.3 Redis内存限制说明

可以设置redis可以使用的内存量。一旦到达内存使用上限,redis将会试图移除内部数据,移除规则可以通过maxmemory-policy来指定。

如果redis无法根据移除规则来移除内存中的数据,或者我们设置了“不允许移除”,那么redis则会针对那些需要申请内存的指令返回错误信息,比如SET、LPUSH等。但是对于无内存申请的指令,仍然会正常响应,比如GET等。

maxmemory <bytes>

需要注意的一点是,如果你的redis是主redis(说明你的redis有从redis),那么在设置内存使用上限时,需要在系统中留出一些内存空间给同步队列缓存,只有在你设置的是“不移除”的情况下,才不用考虑这个因素。

对于内存移除规则来说,redis提供了多达6种的移除规则。他们是:

1.volatile-lru:使用LRU算法移除过期集合中的key
2.allkeys-lru:使用LRU算法移除key
3.volatile-random:在过期集合中移除随机的key
4.allkeys-random:移除随机的key
5.volatile-ttl:移除那些TTL值最小的key,即那些最近才过期的key。
6.noeviction:不进行移除。针对写操作,只是返回错误信息。

 

五、对比分析

性能

性能上都很出色,具体到细节,由于Redis只使用单核,而Memcached可以使用多核,所以平均每一个核上Redis在存储小数据时比

Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis最近也在存储大数据的性能上进行优化,但是比起 Memcached,还是稍有逊色。

内存空间数据流大小限制

MemCached可以修改最大内存,采用LRU算法。Redis增加了VM的特性,突破了物理内存的限制。

可靠性上

 MemCached不支持数据持久化,断电或重启后数据消失,但其稳定性是有保证的。Redis支持数据持久化和数据恢复,允许单点故障,但是同时也会付出性能的代价

应用场景

  Memcached:动态系统中减轻数据库负载,提升性能;做缓存,适合多读少写,大数据量的情况(如人人网大量查询用户信息、好友信息、文章信息等)。

     Redis:适用于对读写效率要求都很高,数据处理业务复杂和对安全性要求较高的系统(如新浪微博的计数和微博发布部分系统,对数据安全性、读写要求都很高)。

 

5.1 传统MySQL+Memcached架构遇到的问题

实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样的架构,但随着业务数据量的不断增加,和访问量的持续增长,我们遇到了很多问题:

MySQL需要不断进行拆库拆表,Memcached也需不断跟着扩容,扩容和维护工作占据大量开发时间。

Memcached与MySQL数据库数据一致性问题。

Memcached数据命中率低或down机,大量访问直接穿透到DB,MySQL无法支撑。

最近几年,业界不断涌现出很多各种各样的NoSQL产品,那么如何才能正确地使用好这些产品,最大化地发挥其长处,是我们需要深入研究和思考的问题,实际归根结底最重要的是了解这些产品的定位,在实际应用中做到扬长避短,总体上这些NoSQL主要用于解决以下几种问题:

(1)少量数据存储,高速读写访问。此类产品通过数据全部in-momery 的方式来保证高速访问,同时提供数据落地的功能,实际这正是Redis最主要的适用场景

(2)海量数据存储,分布式系统支持,数据一致性保证,方便的集群节点添加/删除。

5.2 Redis特性说明

前面已经分析过,Redis最适合所有数据in-momory的场景,虽然Redis也提供持久化功能,但实际更多的是一个disk-backed的功能,跟传统意义上的持久化有比较大的差别,那么可能大家就会有疑问,似乎Redis更像一个加强版的Memcached,那么何时使用Memcached,何时使用Redis呢:

如果简单地比较Redis与Memcached的区别,大多数都会得到以下观点:
1  Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
2  Redis支持数据的备份,即master-slave模式的数据备份。

3  Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。


在Redis中,并不是所有的数据都一直存储在内存中,这是与Memcached相比一个最大的区别,Redis只会缓存所有的key信息,如果redis发现内存使用超过了某个阈值,则会触发swap操作,Rdis根据swappbalilty=age*log(size_in_memory)计算出那些key对应的value需要swap到磁盘上。然后再将这些key对应的value值持久化到磁盘中,同时在内存中清除。这种特性可以使Redis可以保存超过机器内存大小的数据,但是机器内存大小必须要能够保持所有的key,这些key数据是不会进行swap的。



使用Redis特有内存模型前后的情况对比:

VM off: 300k keys,4096 bytes values: 1.3G used VM on:  300k keys, 4096 bytes values: 73Mused VM off: 1 million keys, 256 bytes values: 430.12M used VM on:  1 million keys, 256 bytes values:160.09M used VM on:  1 million keys, values as largeas you want, still: 160.09M used