neversoft 发表于 2018-11-2 13:13:11

Redis 和 Memcached 各有什么优缺点,主要的应用场景是什么样的?

  MySql+Memcached架构的问题  实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样的架构,但随着业务数据量的不断增加,和访问量的持续增长,我们遇到了很多问题:  1.MySQL需要不断进行拆库拆表,Memcached也需不断跟着扩容,扩容和维护工作占据大量开发时间。  
  2.Memcached与MySQL数据库数据一致性问题。  
  3.Memcached数据命中率低或down机,大量访问直接穿透到DB,MySQL无法支撑。  
  4.跨机房cache同步问题。  
  众多NoSQL百花齐放,如何选择最近几年,业界不断涌现出很多各种各样的NoSQL产品,那么如何才能正确地使用好这些产品,最大化地发挥其长处,是我们需要深入研究和思考的问题,实际归根结底最重要的是了解这些产品的定位,并且了解到每款产品的tradeoffs,在实际应用中做到扬长避短,总体上这些NoSQL主要用于解决以下几种问题 
  1.少量数据存储,高速读写访问。此类产品通过数据全部in-momery 的方式来保证高速访问,同时提供数据落地的功能,实际这正是Redis最主要的适用场景。
  2.海量数据存储,分布式系统支持,数据一致性保证,方便的集群节点添加/删除。  
  3.这方面最具代表性的是dynamo和bigtable 2篇论文所阐述的思路。前者是一个完全无中心的设计,节点之间通过gossip方式传递集群信息,数据保证最终一致性,后者是一个中心化的方案设计,通过类似一个分布式锁服务来保证强一致性,数据写入先写内存和redo log,然后定期compat归并到磁盘上,将随机写优化为顺序写,提高写入性能。  
  4.Schema free,auto-sharding等。比如目前常见的一些文档数据库都是支持schema-free的,直接存储json格式数据,并且支持auto-sharding等功能,比如mongodb。面对这些不同类型的NoSQL产品,我们需要根据我们的业务场景选择最合适的产品。       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常用数据类型Redis最为常用的数据类型主要有以下:  

  String
  Hash
  List
  Set
  Sorted set
  pub/sub
  Transactions

  在具体描述这几种数据类型之前,我们先通过一张图了解下Redis内部内存管理中是如何描述这些不同数据类型的:  id_list = redis.lrange("latest.comments",start,start+num_items - 1)

  IF>  id_list = SQL_DB("SELECT ... ORDER BY time LIMIT ...")
  END

  RETURN>  END
  这里我们做的很简单。在Redis中我们的最新ID使用了常驻缓存,这是一直更新的。但是我们做了限制不能超过5000个ID,因此我们的获取ID函数会一直询问Redis。只有在start/count参数超出了这个范围的时候,才需要去访问数据库。      我们的系统不会像传统方式那样“刷新”缓存,Redis实例中的信息永远是一致的。SQL数据库(或是硬盘上的其他类型数据库)只是在用户需要获取“很远”的数据时才会被触发,而主页或第一个评论页是不会麻烦到硬盘上的数据库了。2、删除与过滤      我们可以使用LREM来删除评论。如果删除操作非常少,另一个选择是直接跳过评论条目的入口,报告说该评论已经不存在。       有些时候你想要给不同的列表附加上不同的过滤器。如果过滤器的数量受到限制,你可以简单的为每个不同的过滤器使用不同的Redis列表。毕竟每个列表只有5000条项目,但Redis却能够使用非常少的内存来处理几百万条项目。3、排行榜相关      另一个很普遍的需求是各种数据库的数据并非存储在内存中,因此在按得分排序以及实时更新这些几乎每秒钟都需要更新的功能上数据库的性能不够理想。      典型的比如那些在线游戏的排行榜,比如一个Facebook的游戏,根据得分你通常想要:         - 列出前100名高分选手         - 列出某用户当前的全球排名      这些操作对于Redis来说小菜一碟,即使你有几百万个用户,每分钟都会有几百万个新的得分。      模式是这样的,每次获得新得分时,我们用这样的代码:      ZADD leaderboard          你可能用userID来取代username,这取决于你是怎么设计的。      得到前100名高分用户很简单:ZREVRANGE leaderboard 0 99。      用户的全球排名也相似,只需要:ZRANK leaderboard 。4、按照用户投票和时间排序      排行榜的一种常见变体模式就像Reddit或Hacker News用的那样,新闻按照类似下面的公式根据得分来排序:       score = points / time^alpha       因此用户的投票会相应的把新闻挖出来,但时间会按照一定的指数将新闻埋下去。下面是我们的模式,当然算法由你决定。      模式是这样的,开始时先观察那些可能是最新的项目,例如首页上的1000条新闻都是候选者,因此我们先忽视掉其他的,这实现起来很简单。      每次新的新闻贴上来后,我们将ID添加到列表中,使用LPUSH + LTRIM,确保只取出最新的1000条项目。      有一项后台任务获取这个列表,并且持续的计算这1000条新闻中每条新闻的最终得分。计算结果由ZADD命令按照新的顺序填充生成列表,老新闻则被清除。这里的关键思路是排序工作是由后台任务来完成的。5、处理过期项目      另一种常用的项目排序是按照时间排序。我们使用unix时间作为得分即可。      模式如下:       - 每次有新项目添加到我们的非Redis数据库时,我们把它加入到排序集合中。这时我们用的是时间属性,current_time和time_to_live。       - 另一项后台任务使用ZRANGE…SCORES查询排序集合,取出最新的10个项目。如果发现unix时间已经过期,则在数据库中删除条目。6、计数       Redis是一个很好的计数器,这要感谢INCRBY和其他相似命令。       我相信你曾许多次想要给数据库加上新的计数器,用来获取统计或显示新信息,但是最后却由于写入敏感而不得不放弃它们。       好了,现在使用Redis就不需要再担心了。有了原子递增(atomic increment),你可以放心的加上各种计数,用GETSET重置,或者是让它们过期。       例如这样操作:         INCR user: EXPIRE          user: 60      你可以计算出最近用户在页面间停顿不超过60秒的页面浏览量,当计数达到比如20时,就可以显示出某些条幅提示,或是其它你想显示的东西。7、特定时间内的特定项目      另一项对于其他数据库很难,但Redis做起来却轻而易举的事就是统计在某段特点时间里有多少特定用户访问了某个特定资源。比如我想要知道某些特定的注册用户或IP地址,他们到底有多少访问了某篇文章。      每次我获得一次新的页面浏览时我只需要这样做:       SADD page:day1:      当然你可能想用unix时间替换day1,比如time()-(time()%3600*24)等等。      想知道特定用户的数量吗?只需要使用SCARD page:day1:。       需要测试某个特定用户是否访问了这个页面?SISMEMBER page:day1:。8、实时分析正在发生的情况,用于数据统计与防止垃圾邮件等      我们只做了几个例子,但如果你研究Redis的命令集,并且组合一下,就能获得大量的实时分析方法,有效而且非常省力。使用Redis原语命令,更容易实施垃圾邮件过滤系统或其他实时跟踪系统。9、Pub/Sub       Redis的Pub/Sub非常非常简单,运行稳定并且快速。支持模式匹配,能够实时订阅与取消频道。10、队列      你应该已经注意到像list push和list pop这样的Redis命令能够很方便的执行队列操作了,但能做的可不止这些:比如Redis还有list pop的变体命令,能够在列表为空时阻塞队列。       现代的互联网应用大量地使用了消息队列(Messaging)。消息队列不仅被用于系统内部组件之间的通信,同时也被用于系统跟其它服务之间的交互。消息队列的使用可以增加系统的可扩展性、灵活性和用户体验。非基于消息队列的系统,其运行速度取决于系统中最慢的组件的速度(注:短板效应)。而基于消息队列可以将系统中各组件解除耦合,这样系统就不再受最慢组件的束缚,各组件可以异步运行从而得以更快的速度完成各自的工作。    此外,当服务器处在高并发操作的时候,比如频繁地写入日志文件。可以利用消息队列实现异步处理。从而实现高性能的并发操作。11、缓存      Redis的缓存部分值得写一篇新文章,我这里只是简单的说一下。Redis能够替代memcached,让你的缓存从只能存储数据变得能够更新数据,因此你不再需要每次都重新生成数据了。



页: [1]
查看完整版本: Redis 和 Memcached 各有什么优缺点,主要的应用场景是什么样的?