• Redis、Memcached和Tair,同为分布式缓存Redis为何更胜一筹?


    如今,市面上的缓存解决方案已经逐步成熟了,选取其中一些代表性的方案包括Redis、Memcached和Tair进行对比,帮助大家在生产实践中更好地进行技术选型。

    一、常用的分布式缓存的对比

    常用的分布式缓存包括Redis、Memcached和阿里巴巴的Tair(见下表),因为Redis提供的数据结构比较丰富且简单易用,所以Redis的使用广泛。

    下面我们从9个大方面来对比最常用的Redis和Memcached。

    1.数据类型

    Redis一共支持5种数据类型,每种数据类型对应不同的数据结构,有简单的String类型、压缩串、字典、跳跃表等。跳跃表是比较新型的数据结构,常用于高性能的查找,可以达到log2N的查询速度,而且跳跃表相对于红黑树,在更新时变更的节点较少,更易于实现并发操作。

    Memcache只支持对键值对的存储,并不支持其它数据结构。

    2.线程模型

    Redis使用单线程实现,Memcache等使用多线程实现,因此我们不推荐在Redis中存储太大的内容,否则会阻塞其它请求。

    因为缓存操作都是内存操作,只有很少的计算操作,所以在单线程下性能很好。Redis实现的单线程的非阻塞网络I/O模型,适合快速地操作逻辑,有复杂的长逻辑时会影响性能。对于长逻辑应该配置多个实例来提高多核CPU的利用率,也就是说,可以使用单机器多端口来配置多个实例,官方的推荐是一台机器使用8个实例。

    它实现的非阻塞I/O模型基于Libevent库中关于Epoll的两个文件加上自己简单实现的事件通知模型,简单小巧,作者的思想就是保持实现简单、减少依赖。由于在服务器中只有一个线程,因此提供了管道来合并请求和批量执行,缩短了通信消耗的时间。

    Memcache也使用了非阻塞I/O模型,但是使用了多线程,可以应用于多种场景,请求的逻辑可大可小、可长可短,不会出现一个逻辑复杂的请求阻塞对其它请求的响应的场景。它直接依赖Libevent库实现,依赖比较复杂,损失了在一些特定环境下的高性能。

    3.持久机制

    Redis提供了两种持久机制,包括RDB和AOF,前者是定时的持久机制,但在出现宕机时可能会出现数据丢失,后者是基于操作日志的持久机制。

    Memcahe并不提供持久机制,因为Memache的设计理念就是设计一个单纯的缓存,缓存的数据都是临时的,不应该是持久的,也不应该是一个大数据的数据库,缓存未命中时回源查询数据库是天经地义的,但可以通过第三方库MemcacheDB来支持它的持久性。

    4.客户端

    常见的Redis Java客户端Jedis使用阻塞I/O,但可以配置连接池,并提供了一致性哈希分片的逻辑,也可以使用开源的客户端分片框架Redic。

    Memecache的客户端包括Memcache Java Client、Spy Client、XMemcache等,Memcache Java Client使用阻塞I/O,而Spy Client/XMemcache使用非阻塞I/O。

    我们知道,阻塞I/O不需要额外的线程,非阻塞I/O会开启额外的请求线程(在Boss线程池里)监听端口,一个请求在处理后就释放工作者线程(在Worker线程池中),请求线程在监听到有返回结果时,一旦有I/O返回结果就被唤醒,然后开始处理响应数据并写回网络Socket连接,所以从理论上来讲,非阻塞I/O的吞吐量和响应能力会更高。

    5.高可用

    Redis支持主从节点复制配置,从节点可使用RDB和缓存的AOF命令进行同步和恢复。Redis还支持Sentinel和Cluster(从3.0版本开始)等高可用集群方案。

    Memecache不支持高可用模型,可使用第三方Megagent代理,当一个实例宕机时,可以连接另外一个实例来实现。

    6.对队列的支持

    Redis本身支持lpush/brpop、publish/subscribe/psubscribe等队列和订阅模式。

    Memcache不支持队列,可通过第三方MemcachQ来实现。

    7.事务

    Redis提供了一些在一定程度上支持线程安全和事务的命令,例如:multi/exec、watch、inc等。由于Redis服务器是单线程的,任何单一请求的服务器操作命令都是原子的,但跨客户端的操作并不保证原子性,所以对于同一个连接的多个操作序列也不保证事务。

    Memcached的单个命令也是线程安全的,单个连接的多个命令序列不是线程安全的,它也提供了inc等线程安全的自加命令,并提供了gets/cas保证线程安全。

    8.数据淘汰策略

    Redis提供了丰富的淘汰策略,包括maxmemory、maxmemory-policy、volatile-lru、allkeys-lru、volatile-random、allkeys-random、volatile-ttl、noeviction(return error)等。

    Memecache在容量达到指定值后,就基于LRU(Least Recently Used)算法自动删除不使用的缓存。在某些情况下LRU机制反倒会带来麻烦,会将不期待的数据从内存中清除,在这种情况下启动Memcache时,可以通过“M”参数禁止LRU算法。

    9.内存分配

    Redis为了屏蔽不同平台之间的差异及统计内存占用量等,对内存分配函数进行了一层封装,在程序中统一使用zmalloc、zfree系列函数,这些函数位于zmalloc.h/zmalloc.c文件中。封装就是为了屏蔽底层平台的差异,同时方便自己实现相关的统计函数。具体的实现方式如下:

    若系统中存在Google的TC_MALLOC库,则使用tc_malloc一族的函数代替原本的malloc一族的函数。

    若当前系统是Mac系统,则使用系统的内存分配函数。

    对于其它情况,在每一段分配好的空间前面同时多分配一个定长的字段,用来记录分配的空间大小,通过这种方式来实现简单有效的内存分配。

    Memcache采用slab table的方式分配内存,首先把可得的内存按照不同的大小来分类,在使用时根据需求找到最接近于需求大小的块分配,来减少内存碎片,但是这需要进行合理配置才能达到效果。

    从上面的对比可以看到,Redis在实现和使用上更简单,但是功能更强大,效率更高,应用也更广泛。下面将对Redis进行初步介绍,给初学者一个初体验式的学习引导。

    Redis支持语言:

  • 相关阅读:
    JMeter学习-027-JMeter参数文件(脚本分发)路径问题:jmeter.threads.JMeterThread: Test failed! java.lang.IllegalArgumentException: File distributed.csv must exist and be readable解决方法
    JMeter学习-026-JMeter 分布式(远程)参数化测试实例
    JMeter学习-025-JMeter 命令行(非GUI)模式详解(三)-测试图形化 HTML 报表(dashboard)生成
    JMeter学习-024-JMeter 命令行(非GUI)模式详解(二)-执行代理设置
    JMeter学习-023-JMeter 命令行(非GUI)模式详解(一)-执行、输出结果及日志、简单分布执行脚本
    JMeter学习-022-JMeter 分布式测试(性能测试大并发、远程启动解决方案)
    JMeter学习-021-JMeter 定时器(Synchronizing Timer)之集合点应用
    JMeter学习-020-JMeter 监听器之【聚合报告】错误率、吞吐量、传输速率实例计算
    Selenium2学习-038-firefox、webdriver版本不对称问题解决:org.openqa.selenium.firefox.NotConnectedException: Unable to connect to host 127.0.0.1 on port 7055
    JMeter学习-019-JMeter 监听器之【聚合报告】界面字段解析及计算方法概要说明
  • 原文地址:https://www.cnblogs.com/zhaosq/p/12655814.html
Copyright © 2020-2023  润新知