redis 和 memcached 有什么区别

分类:编程技术 时间:2024-02-20 15:23 浏览:0 评论:0
0
本文将详细讲解redis和memcached的区别。文章内容质量较高,小编分享给大家,作为参考。希望您看完本文后对相关知识有一定的了解。

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

事实上,MySQL适合海量数据存储。 Memcached用于将热点数据加载到缓存中,以加快访问速度。 ,很多公司都采用了这样的结构,但是随着业务数据量不断增加,访问量不断增长,我们遇到了很多问题:

1、MySQL需要不断拆解并拆除。另外,Memcached还需要不断扩展,扩展和维护工作占用了大量的开发时间。

2、Memcached与MySQL数据库之间的数据一致性问题。

3、Memcached数据命中率低或t机器宕机,大量访问直接渗透到DB,MySQL无法支持。

4.跨机房缓存同步问题。

众多NoSQL产品百花齐放,如何选择?

近年来,业界涌现出许多形形色色的NoSQL产品,那么如何使用他们正确吗?用好这些产品,发挥它们的优势,是我们需要深入研究和思考的。归根结底,最重要的是要了解这些产品的定位,了解每个产品的利弊,从而在实际应用中扬长避短。一般来说,这些NoSQL主要用来解决以下问题

:1.数据存储量小,读写访问高速。此类产品将所有数据保留在内存中,保证高速访问,同时提供数据落地功能。事实上,这是Redis的主要应用场景。

2、海量数据存储,分布式系统支持,数据一致性保证,集群节点便捷增删。

3、这方面最有代表性的想法是dynamo和bigtable这两篇论文。前者是完全无心的设计。集群信息在节点之间通过gossip传递,数据保证最终一致性。后者是集中式的方案设计,通过分布式锁服务保证强一致性,数据写入先写入内存和重做日志,然后定期兼容合并到磁盘,将随机写优化为顺序写,提高写入性能。

4.Schema free、自动分片等。例如,目前一些常见的文档数据库都支持schema-free。存储json格式的数据,并支持自动分片等功能,比如mongodb。

面对这些不同类型的NoSQL产品,我们需要根据我们的业务场景选择最合适的产品。

Redis适用场景,如何正确使用

前面分析过,Redis最适合所有数据内存场景,虽然Redis也提供了持久化转换功能,但实际上更多的是磁盘支持的功能,与传统意义上的持久化有很大不同。那么你可能会有疑问。看起来Redis更像是Memcached的增强版。那么当使用Memcached时,什么时候使用Redis?

如果简单比较Redis和Memcached的区别,大多数人会得到以下观点:

1 Redis不仅支持简单的k/v类型数据,还提供list、set、zset、hash等数据结构的存储。

2 Redis支持数据备份,即master-中的数据备份从模式。

3 Redis支持数据持久化,可以将内存中的数据保存在磁盘上并且可以加载重新启动时再次使用。

除了这些,你还可以深入研究Redis的内部结构,观察更多本质的区别,了解Redis的设计。

在Redis中,并非所有数据都始终存储在内存中。这是与Memcached相比最大的区别。 Redis只会缓存所有关键信息。如果Redis发现内存使用量超过一定阈值,就会触发swap操作。 Redis 根据“swappability =age*log(size_in_memory)”交换到磁盘来计算哪些键对应于该值。然后这些key对应的值会被持久化到磁盘并在内存中被清除。该特性允许Redis维护超过其机器本身内存大小的数据。当然,机器本身的内存必须能够保存所有的key,毕竟这些数据不会被交换。同时,当Redis将内存中的数据交换到磁盘时,提供服务的主线程和各自的子线程形成swap操作会共享这部分内存,所以如果需要交换的数据有更新,Redis会阻塞该操作,直到子线程完成swap操作后才能进行修改。

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

VM关闭:300k键,4096字节值:1.3G使用VM开启: 300k 键,4096 字节值:73MusedVM off:100 万个键,256 字节值:430.12MusedVM on:100 万个键,256 字节值:160.09MusedVM on:100 万个键,值随心所欲, still: 160.09Mused

当从Redis读取数据时,如果读取的key对应的value不在内存中,那么Redis需要从交换文件中加载对应的数据然后返回给请求者。这里存在一个I/O线程池问题。默认情况下,Redis 会阻塞,即在加载所有交换文件之前不会响应。这个策略比较适合当客户端数量较少且批量操作时。但如果Redis应用在大型网站应用中,这显然不能满足大并发的情况。因此,在运行Redis时,我们设置I/O线程池的大小,并对需要从交换文件中加载相应数据的读请求进行并发操作,以减少阻塞时间。

如果想要在海量数据的环境下用好Redis,相信了解Redis的内存设计和阻塞情况是必不可少的。

补充知识点:

memcached和redis的比较

1 网络IO模型

Memcached是一种多线程、非阻塞IO复用网络模型。分为主监听线程和工作子线程。监听线程监视网络连接。接受请求后,将连接描述符管道传递给工作线程读写IO和网络。该层使用libevent封装的事件库。多线程模型可以起到多核的作用,但是它引入了缓存一致性和锁问题。比如Memcached最常用的stats命令,实际上Memcached的所有操作都必须锁定这个全局变量并对其进行计数。等待工作会带来性能损失。

(Memcached网络IO模型)

Redis采用单线程IO复用模型,封装了一个简单的AeEvent事件处理框架,主要实现没有epoll、kqueue和select,对于纯IO操作来说,单线程可以最大限度的发挥速度优势,但是Redis也提供了一些简单的计算功能,比如排序、聚合等,对于这些操作来说,单线程模型其实是会的严重影响整体吞吐量。 CPU计算过程中,整个IO调度是阻塞的。

2.记忆人Memcached使用预先分配的内存池,使用不同大小的slab和chunk来管理内存。根据大小选择合适的块存储和内存池方式,可以节省申请/释放内存的开销,减少内存碎片的产生。不过这种方法也会造成一定程度的空间浪费,内存中仍然存在大量的空间。当空间用完时,新数据也可能被消除。原因可以参考Timyang的文章:http://timyang.net/data/Memcached-lru-evictions/

Redis采用现场内存申请。存储数据,很少使用free-list等方法来优化内存分配。内存碎片在一定程度上会存在。根据存储命令参数,Redis会将带有过期时间的数据单独存储在一起,称为临时数据,非临时数据永远不会被删除。即使物理内存是n还不够,交换不会删除任何非临时数据(但会尝试删除一些临时数据)。从这一点来看,Redis更适合作为存储而不是缓存。 。

三、数据一致性问题

Memcached提供了cas命令来保证多个并发访问操作对同一数据的一致性。 Redis 不提供 cas 命令,因此无法保证这一点。不过,Redis提供了事务功能,可以保证一系列命令的原子性,不会被中间的任何操作打断。

4.存储方式等方面

Memcached基本上只支持简单的key-value存储,不支持枚举、持久化和复制。其他功能

除了key/value之外,Redis还支持list、set、sorted set、hash等多种数据结构,并提供KEYS

进行枚举操作,但不能在线 如果您需要枚举在线数据,Redis提供了工具可以直接扫描其转储文件并枚举所有数据。 Redis还提供持久化和复制功能。

5.关于不同语言的客户端支持

在不同语言的客户端方面,Memcached 和 Redis 都有丰富的第三方客户端选择。可以选择,但是由于Memcached发展的时间比较长,目前在客户端支持方面,很多Memcached客户端都比较成熟稳定,而Redis由于其协议本身的原因,比Memcached更加复杂,笔者继续添加新功能等,第三方客户端相应的后续速度可能会跟不上,有时可能需要在第三方客户端的基础上进行一些修改才能更好地使用。

根据上面的比较,不难看出,当我们不希望数据被踢出时,或者当我们需要更多的数据类型时除了key/value之外,或者我们需要落地功能的时候,使用Redis比使用Memcached效率更高。合适的。

关于Redis的一些外围功能

Redis除了作为存储之外,还提供了一些其他的功能,比如聚合计算、pubsub、脚本、对于此类功能,需要了解其实现原理,明确其局限性,才能正确使用。例如, pubsub 函数实际上没有任何持久性支持。消费者连接中断或重新连接。所有传入的消息都将丢失。聚合计算、脚本等功能受限于Redis单线程模型,无法实现高吞吐量。需要谨慎使用它们。

总的来说,Redis的作者是一位非常勤奋的开发者。你经常可以看到作者尝试各种新的想法和想法。我们需要深入了解这些功能。稍后再用。

总结:

1、使用Redis最好的方式就是内存。

2.Redis作为Memcached的替代品在更多场景中使用。

3、当需要支持除key/value之外的更多数据类型时,使用Redis更为合适。

4.当存储的数据无法删除时,使用Redis比较合适。

聊聊Memcached和Redis

1.Memcached简介

Memcached是LiveJurnal子公司Danga Interactive的Bard Fitzpatric开发的高性能分布式内存缓存服务器。它本质上是一个内存键值数据库,但它不支持数据持久化。服务器关闭后所有数据都会丢失。 Memcached是用C语言开发的,只要安装了libevent就可以在Linux、BSD、Solaris等大多数POSIX系统上使用。在Windows下,它还有一个非官方版本可用(http://code.jellycan.com/memcached/)。 Memcached 的客户端软件实现有很多,包括 C/C++、PHP、Java、Python、Ruby、Perl、Erlang、Lua 等。目前 Memcached 应用广泛,包括 LiveJournal、Wikipedia、Flickr、Twitter、Youtube 和 WordPress。

在Windows系统中,Memcached的安装非常方便。只需从上面给出的地址下载可执行软件并运行memcached.exe –d install即可完成安装。在Linux等系统中,我们首先需要安装libevent,然后通过make && make install获取源码。默认情况下,Memcached服务器启动程序安装在/usr/local/bin目录下。在启动Memcached时,我们可以为其配置不同的启动参数。

1.1 Memcache配置

Memcached服务器启动时需要配置关键参数。我们来看看Memcached启动时需要设置哪些关键参数以及这些参数的详细信息。影响。

1) -p Memcached TCP监听端口,默认配置为11211;

2) -U Memcached的UDP监听端口,默认配置为11211,为0时表示关闭UDP监听;

3) -s Memcached监控的UNIX套接字路径;

4) -a 访问UNIX套接字的八进制掩码,默认配置为0700;

p >

5) -l <​​addr> 监控服务器IP地址,默认为所有网卡;

6) -d 启动Memcached服务器的守护进程;

7) -r 最大核心文件大小;

8) -u <用户名> 运行 Memcached 的用户。如果当前是root,则需要使用该参数来指定用户;

9) -m 分配给Memcached的内存量,单位MB;

10) -M 指示Memcached在内存用完时返回错误,而不是使用LRU算法删除数据记录;

11) -c 最大并发连接数,默认配置为1024;

12) -v –vv –vvv 设置服务器打印消息的详细级别,其中-v只打印Error和警告信息,-vv还会根据-v打印客户端命令和响应, -vvv还会在-vv的基础上打印内存状态转换信息;

13) -f 用于设置chunk大小的增量因子;

14) -n 最小chunk大小,默认配置为48字节;

15) -t Memcached服务器使用的线程数,默认配置为4;

16) -L 尝试使用大内存页;

17) -R 每个事件的最大请求数,默认配置为20;

18) -C 禁用CAS,CAS模式会带来8字节的冗余;

2. Redis简介

Redis是一个开源的键值存储系统。与 Memcached 类似,Redis 将大部分数据存储在内存中。支持的数据类型包括:字符串、哈希表、链表、集合、有序集合和 r基于这些数据类型的相关操作。 Redis 使用 C 语言开发,可在大多数 Linux 和 BSD 系统上使用。它可以在 Solaris、Solaris 等 POSIX 系统上使用,无需任何外部依赖。 Redis支持的客户端语言也非常丰富。常用的计算机语言如C、C#、C++、Object-C、PHP、Python、Java、Perl、Lua、Erlang等都有可用的客户端来访问Redis服务器。目前Redis已经得到了广泛的应用。国内的新浪、淘宝等公司,国外的Flickr、Github等公司都在使用Redis的缓存服务。

Redis的安装非常方便。只需从http://redis.io/download获取源代码,然后make && make install即可。默认情况下,Redis服务器启动程序和客户端程序安装在/usr/local/bin目录下。当启动Redis服务器时,我们需要为其指定一个配置文件。默认情况下,配置文件位于Redis中,所以urce代码目录,文件名为redis.conf。

2.1 Redis配置文件

为了能够直观的了解Redis的系统实现,我们首先看一下Redis配置文件中定义的主要参数以及功能这些参数。 。

1) daemonize no 默认情况下,redis 不在后台运行。如果需要后台运行,则将此项的值改为yes;

2)pidfile /var/run/redis.pid 当Redis在后台运行时,Redis会将pid文件放入默认情况下在 / 中。 var/run/redis.pid,可以配置为其他地址。运行多个redis服务时,需要指定不同的pid文件和​​端口;

3)port 6379指定redis运行的端口,默认为6379;

4) 绑定 127.0.0.0 0.1 指定redis只接收来自该IP地址的请求。如果未设置,则将处理所有请求。生产环境中最好设置此项;

5)loglevel debug指定日志记录级别,其中Redis一共支持四个级别:debug、verbose、notice、warning,默认为verbose。调试意味着记录大量信息以供开发和测试使用。 verbose 意味着记录有用的信息,但不如 debug 记录的那么多。 notification 表示常见的详细信息,常用于生产环境。
warning表示只有非常重要或者严重的信息才会记录在日志中;

6) logfile /var/log/redis/redis.log 配置日志文件地址,默认值是标准输出。如果后台模式会输出到/dev/null;

7)databases 16 可用数据库数量,默认值为16,默认数据库为0,数据库范围在0-之间(database-1);

8) save 900 1 将数据保存到磁盘,格式为save <秒> <变化>,表示在很长一段时间内有多少次更新操作,然后将数据同步到data 文件 rdb.相当于抓快照的条件触发器,可以匹配多个条件。 save 900 1 表示如果在900秒内至少改变1个key,则将数据保存到磁盘;

9) rdbcompression yes 数据存储到本地数据库时是否压缩(持久化到rdb文件),默认为yes;

10) dbfilename dump.rdb 本地持久数据库文件名,默认值为dump.rdb;

11) dir ./工作目录,数据库镜像备份路径的文件放置。这里的路径和文件名需要单独配置,因为redis在进行备份时,会先将当前数据库的状态写入到一个临时文件中,等备份完成后,再将临时文件替换为上面指定的文件。这里的临时文件和上面配置的备份文件都会放在这个指定的路径下,AOF文件也会存放在这个目录下。注意这里必须指定目录而不是文件;

12)slaveof 主从复制,将数据库设置为其他数据库的从库。当本机为从服务时,设置主服务的IP地址和端口。 Redis启动时,会自动从master同步数据;

13) masterauth 当master服务有密码保护时(密码由requirepass指定),slave服务连接的密码到master;

14)slave-serve-stale-data yes 当从库与主机失去连接或者复制正在进行时,从库有两种运行模式:如果slave-serve-stale -data 设置为yes(默认设置),从库将继续相应客户端的请求。如果slave-serve-stale-data引用no,则排除INFO和SLAVOF命令以外的任何请求,将返回错误“SYNC with master in Progress”;

15) repl-ping-slave-period 10 从库会每隔一个时间间隔向主库发送PING,可以通过repl-ping-slave-period设置这个时间间隔,默认是10秒;

16) repl-timeout 60 设置主库批量数据传输时间或者ping回复时间间隔,默认值为60秒,一定要保证repl-timeout大于repl-ping-slave -period;

17) requirepass foobared 设置客户端连接后在任何其他规范之前所需的密码。因为redis速度相当快,在相对好的服务器下,外部用户每秒可以进行150K次密码尝试,这意味着你需要指定一个非常强的密码来防止暴力破解;

18)rename- command CONFIG ""命令重命名,比较危险的命令可以在共享环境中重命名,比如将CONFIG重命名为不易猜到的字符:#rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52。如果你想删除命令,只需将其重命名为空字符“”:rename-command CONFIG“”;

19) maxclients 128 设置同时最大客户端连接数,默认无限制。 Redis可以同时打开的客户端连接数就是Redis进程可以打开的最大文件描述符数。如果maxclients设置为0,则表示没有限制。当客户端连接数达到限制时,Redis会关闭新的连接,并向客户端返回max number of client
reached错误信息;

20) maxmemory 指定最大值Redis的内存限制。 Redis启动时会将数据加载到内存中。达到最大内存后,Redis 会首先尝试清除过期或过期的键。 Redis 还将删除空列表对象。当执行此方法并且仍然达到最大内存设置时,将不再可以进行写入操作,但仍然可以进行读取操作。注:Redis’新的vm机制将Key存储在内存中,Value存储在交换区中;

21) maxmemory-policy volatile-lru 当内存达到最大值时,Redis会选择删除哪些数据?有五种方法可供选择: volatile-lru 表示使用 LRU 算法删除过期时间的密钥(LRU:最近最少使用),allkeys-lru 表示使用 LRU 算法删除任何密钥, volatile-random 表示移入除了设置一个带有过期时间的随机密钥外,allkeys_random 表示删除一个随机密钥, volatile-ttl 表示删除即将过期的密钥(次要 TTL),noeviction 表示不删除任何密钥,只返回写入错误。
注意:对于上述策略,如果没有合适的key需要remove,Redis在写入时会返回错误;

22)appendonly no 默认情况下,redis会在后台异步返回将数据库映像备份到磁盘,但是这种备份非常耗时,而且备份不能很频繁。如果情况当发生断电或者拔插等情况时,会出现比较大范围的数据丢失,所以redis提供了另一种更高效的数据库备份和容灾方法。开启append only模式后,redis会将收到的每一个写操作请求追加到appendonly.aof文件中。当redis重启时,会从这个文件恢复之前的状态,但这会导致appendonly.aof文件太大,所以redis还支持BGREWRITEAOF命令来重新组织appendonly.aof。
可以同时打开异步转储和AOF;

23)appendfilenameappendonly.aof AOF文件名,默认为“appendonly.aof”;

24)appendfsync everysec Redis支持三种同步AOF文件的策略:no表示不同步,系统会进行操作,always表示每次有写操作都同步,everysec表示累计写操作,每秒同步一次,默认为“everysec”,whch 是速度和安全性之间的最佳折衷方案。 OK

25)slowlog-log-slower-than 10000 记录超过特定执行时间的命令。执行时间不包括I/O计算,如连接客户端、返回结果等,只是命令执行时间。慢日志可以通过两个参数来设置:一个是参数slowlog-log-slower-than(微秒),它告诉Redis执行需要多长时间,另一个是慢日志的长度。当记录新命令时,最旧的命令将从队列中删除。以下时间以微秒为单位,因此 1000000 代表一分钟。请注意,指定负数将关闭慢速日志记录,将其设置为 0 将强制记录每个命令;

26) hash-max-zipmap-entries 512 && hash-max-zipmap-value 64 当散列包含超过指定数量的元素且最大元素不超过临界值时,散列w将以特殊的编码方法存储(这大大减少了内存使用)。这两个临界值可以在这里设置。 Value对应的Redis Hash实际上是一个HashMap,这里实际上有两种不同的实现。当这个Hash的成员比较少的时候,Redis为了节省内存,会采用类似一维数组的方式来紧凑的存储,而不是使用真正的HashMap结构。对应值redisObject的编码是zipmap。当成员数量增加时,会自动转换为真正的HashMap,此时编码为ht;

27) list-max-ziplist-entries 512 列表数据类型将使用低于节点数的无指针紧凑存储。格式;

28) list-max-ziplist-value 64 数据类型节点值大小小于字节数时会使用紧凑存储格式;

29) set-max-intset-entries 512 如果set数据类型的内部数据全是numeric,且包含的节点数量不超过,则会以紧凑格式存储;

30) zset-max-ziplist-entries 128 如果zsort数据类型不超过数量节点,它将使用指针。压缩存储格式;

31) zset-max-ziplist-value 64 如果zsort数据类型节点值大小小于字节数,将使用压缩存储格式。

32) activerehashing yes Redis会每100毫秒使用1毫秒的CPU时间对redis哈希表进行rehash,这样可以减少内存的使用。当你的使用场景对实时性要求非常严格,无法接受Redis时不时的请求2毫秒延迟时,配置为no。如果没有那么严格的实时性要求,可以设置为yes,以尽快释放内存;

Redis常见数据类型

与Memcached只支持简单的key-value结构数据记录不同,Redis支持更丰富的数据一个类型。有五种最常用的数据类型:String、Hash、List、Set 和 Sorted Set。在详细描述这些数据类型之前,我们先用一张图来了解一下这些不同的数据类型在Redis的内部内存管理中是如何描述的。

图1 Redis对象

Redis内部使用一个redisObject对象来表示所有的键和值。 redisObject的主要信息如图1所示:type表示值对象的具体数据类型,encoding是不同数据类型在redis内部的存储方式。例如:type=string 表示该值存储为普通字符串。那么对应的编码可以是raw或者int。如果是int的话,说明实际redis内部是按照数值类来存储和表示字符串的。当然,前提是字符串本身可以用数值来表示,比如:“123”“456”这样的字符串。这里需要特别注意一下vm场地。只有开启了Redis的虚拟内存功能,该字段才能真正分配内存。该功能默认关闭。从图1中我们可以发现,Redis使用redisObject来表示所有的key/value数据,这样很浪费内存。当然,这些内存管理成本主要是为了给Redis的不同数据类型提供统一的管理接口。实际作者还提供了很多这样的方法来帮助我们尽可能的节省内存的使用。我们先来一一分析一下这五种数据类型的使用和内部实现。

1)String

常用命令:set/get/decr/incr/mget等;

应用场景:String是最常用的数据type ,普通的key/value存储都可以归为此类;

实现方法:String默认在redis内部存储为字符串,由redisObject引用。当遇到 incr、decr 等运算时,会转换为 numeric typee 进行计算。此时redisObject的encoding字段为int。

2)Hash

常用命令:hget/hset/hgetall等

应用场景:我们要存储一个用户信息对象数据,包括用户 ID、用户名、年龄和生日。通过用户ID我们希望获取用户的姓名、年龄或者生日。 ;

实现方法:Redis的Hash实际上在内部将值存储为一个HashMap,并提供了直接访问这个Map的成员的接口。如图2所示,Key是用户ID,Value是Map。这个Map的key是成员的属性名,value是属性值。这样就可以直接通过其内部Map的key来修改和访问数据(内部Map的key在Redis中称为field),即通过key(用户ID)+field来操作对应的属性数据(属性标签)。目前HashMap有两种实现方式: 当存在比较多的情况时对于 HashMap 的成员,Redis 会使用类似一维数组的方式来紧凑地存储,以节省内存,而不是使用真正的 HashMap 结构。此时对应值的redisObject的编码为zipmap,当成员数量增加时,会自动转换为真正的HashMap,编码为ht。

图2 Redis Hash数据类型

3)List

常用命令:lpush/rpush/lpop/rpop/lrange等.;

应用场景:Redis列表的应用场景非常多,也是Redis最重要的数据结构之一。例如twitter的关注列表、粉丝列表等都可以使用Redis的列表结构来实现;

实现方法:Redis链表的实现是双向链表,可以支持反向查找和遍历,操作起来比较方便,但是带来了一些额外的内存开销。 Redis 内部的许多实现,包括ng send buffer Queues等也使用这种数据结构。

4)Set

常用命令:sadd/spop/smembers/sunion等;

应用场景:Redis set提供了类似list的外部功能。 list函数的特点是set可以自动消除重复项。当需要存储列表数据并且不希望出现重复数据时,set是一个不错的选择,set提供了判断某个成员是否在set集合中的重要接口,这也是set所不提供的list;

实现方法:set的内部实现是一个HashMap,其值始终为null。其实就是通过计算hash来快速剔除重复项。是的,这就是为什么set可以提供一种判断某个成员是否在集合中的方法。

5)排序集

常用命令:zadd/zrange/zrem/zcard等;

应用场景:Redis排序集的使用场景有类似于设置。区别在于集合不会自动排序,但排序集合可以通过用户提供额外的优先级(分数)参数对成员进行排序,并且是插入排序的,即自动排序。当需要有序且不重复的集合列表时,可以选择有序集合数据结构。例如,Twitter的公开时间线可以将发布时间作为分数进行存储,这样在获取时会自动按时间排序。的。

实现方法:Redis排序集内部使用HashMap和跳跃列表(SkipList)来保证数据的存储和排序。 HashMap存储了从成员到分数的映射,而跳表存储了所有成员根据HashMap中存储的分数进行排序。采用跳表结构可以实现较高的查找效率,且实现比较简单。

2.3 Redis持久化

虽然Redis是一个基于内存的存储系统,但它本身就支持内存数据的持久化,并提供两种主要的持久化策略:RDB快照和AOF日志。下面我们将分别介绍这两种不同的持久化策略。

2.3.1 Redis AOF日志

Redis支持一种持久化机制,将当前数据的快照保存到数据文件中,即RDB快照。这种方法很容易理解,但是连续写入的数据库是如何生成快照的呢? Redis使用fork命令的写时复制机制。生成快照时,将当前进程fork出一个子进程,然后循环子进程中的所有数据,并将数据写入RDB文件中。

我们可以通过Redis的save命令来配置RDB快照生成的时机。例如,您可以配置10分钟内有100次写入时生成快照,也可以配置1小时内有1000次写入时生成快照。输入时生成快照,也可以同时实施多个规则。定义这些规则位于 Redis 配置文件中。您还可以在Redis运行时通过Redis CONFIG SET命令设置规则,而无需重新启动Redis。

Redis的RDB文件不会被损坏,因为它的写操作是在新的进程中进行的。当生成新的RDB文件时,Redis生成的子进程会首先将数据写入临时文件,然后通过原子重命名系统调用将临时文件重命名为RDB文件,这样如果任何时候发生故障, Redis RDB 文件始终可用。同时Redis的RDB文件也是Redis主从同步内部实现的一部分。

但是,我们可以清楚地看到RDB有它的缺点,那就是一旦数据库出现问题,我们的RDB文件中保存的数据就不是全新的了。 Redis 关闭期间所有数据都会丢失。在某些企业中,这是可以忍受的。我们还建议这些企业使用 RDB坚持下去,因为开RDB的成本并不高。但对于其他对数据安全性要求极高、不能容忍数据丢失的应用,RDB就无能为力了,因此Redis引入了另一种重要的持久化机制:AOF日志。

Redis的AOF日志

AOF日志的全称是append only file。从名字就可以看出,这是一个追加写入的文件。日志文件。与一般数据库的binlog不同,AOF文件是可识别的纯文本,其内容是一一的Redis标准命令。当然,并不是所有发送到Redis的命令都必须记录在AOF日志中。只有那些会导致数据修改的命令才会被追加到 AOF 文件中。然后每个修改数据的命令都会生成一个日志。 AOF文件会很大吗?答案是肯定的,AOF文件会越来越大,所以Redis提供了另一个功能,叫做AOF重写。它的作用是重新生成一个AOF文件。只会有一个o对新 AOF 文件中的记录进行操作,与旧文件不同,旧文件可能会记录对同一值的多个操作。生成过程与RDB类似。它还fork一个进程,直接遍历数据,写入新的AOF临时文件。在写入新文件的过程中,所有写操作日志仍然会写入原来的旧AOF文件中,同时也会记录在内存缓冲区中。当重做操作完成时,缓冲区中的所有日志将被一次性写入临时文件。然后调用原子重命名命令将旧的 AOF 文件替换为新的 AOF 文件。

AOF是文件写入操作。它的目的是将操作日志写入磁盘,因此它也会遇到我们上面提到的写操作的五个过程。那么写AOF的操作有多安全呢?其实这个是可以设置的。在Redis中对AOF调用write(2)后,何时调用fsync将其写入磁盘由appendfsync选项控制。阿彭贝洛wdfsync的三个设置的安全强度逐渐变强。

1)appendfsync no

当appendfsync设置为no时,Redis不会主动调用fsync将AOF日志内容同步到磁盘,所以这一切完全取决于操作系统。已调试。对于大多数Linux操作系统,每30秒执行一次fsync,将缓冲区中的数据写入磁盘。

2)appendfsync everysec

当appendfsync设置为everysec时,Redis会默认每秒进行一次fsync调用,将缓冲区中的数据写入磁盘。但是当这个fsync调用持续时间超过1秒时。 Redis会采取延迟fsync的策略,再等待一秒。也就是说,fsync会在两秒后执行。这次不管执行多久都会执行fsync。此时,因为fsync时文件描述符会被阻塞,所以当前的写操作会被阻塞。所以结论是,在大多数情况下ses中,Redis会每秒执行一次fsync。最坏的情况下,每两秒发生一次 fsync 操作。这个操作在大多数数据库系统中称为组提交。它将多次写操作的数据组合起来,一次性将日志写入磁盘。

3)appednfsyncalways

当appendfsync设置为always时,每次写操作都会调用一次fsync。这个时候,数据是最安全的。当然,由于每次都会执行fsync,所以它的性能也会受到影响。

3. Memcached与Redis关键技术对比

作为内存数据缓冲系统,Memcached和Redis都具有高性能,但在关键实现技术上却有很大不同。 ,这种差异决定了两者具有不同的特点和不同的适用条件。下面我们将对两者的关键技术进行一些比较,以揭示两者之间的差异。
内存管理比较Memcached和Redis之间的管理机制

对于Redis和Memcached这样基于内存的数据库系统来说,内存管理的效率是影响系统性能的关键因素。传统C语言中的malloc/free函数是最常用的分配和释放内存的方法,但这种方法存在重大缺陷:第一,对于开发人员来说,malloc和free不匹配很容易导致内存泄漏;其次,频繁的调用会造成大量的内存碎片无法回收复用,降低内存利用率;最后,作为系统调用,其系统开销比普通函数调用要大得多。因此,为了提高内存管理效率,高效的内存管理方案不会直接使用malloc/free调用。 Redis和Memcached都使用自己的内存管理机制,但实现方法却有很大不同。两者的内存管理机制将分别介绍以下。

Memcached的内存管理机制

Memcached默认使用Slab Allocation机制来管理内存。其主要思想是按照预定的大小来划分分配的内存。分成特定长度的块来存储相应长度的键值数据记录,彻底解决内存碎片问题。 Slab Allocation机制只是为了存储外部数据而设计的,这意味着所有的键值数据都存储在Slab Allocation系统中,而Memcached的其他内存请求都是通过普通的malloc/free来申请的,因为这些请求的数量和频率决定了它们不会影响整个系统的性能

Slab Allocation的原理很简单。如图3所示,它首先向操作系统申请一大块内存,将其划分为各种大小的chunk,并将相同大小的chunk分为slab类组。其中,Chunk是用于存储key-value数据的最小单位。每个Slab Class的大小可以通过Memcached启动时指定Growth Factor来控制。假设图1中Growth Factor的值为1.25,那么如果第一组Chunk的大小为88字节,则第二组Chunk的大小为112字节,以此类推。

图3 Memcached内存管理架构

Memcached接收到客户端发送的数据时,首先会根据大小选择最合适的收到的数据。 Slab Class,然后通过查询Memcached保存的Slab Class中的空闲chunk列表,就可以找到可以用来存储数据的Chunk。当数据库记录过期或被丢弃时,该记录占用的Chunk可以被回收并重新添加到空闲列表中。从上面的过程我们可以看出,Memcached的内存管理系统效率很高,不会造成内存碎片,但是它最大的缺点优点是它会导致空间的浪费。由于每个Chunk都分配了特定长度的内存空间,因此变长数据无法充分利用该空间。如图4所示,128字节的Chunk中缓存了100字节的数据,剩下的28字节就被浪费了。

图4 Memcached存储空间浪费

Redis内存管理机制

Redis的内存管理主要通过两个文件来实现源代码中的zmalloc.h和zmalloc.c。为了方便内存管理,Redis在分配一块内存后,会将这块内存的大小存储在内存块的头部。如图5所示,real_ptr是redis调用malloc后返回的指针。 Redis 将内存块大小的大小存储在 header 中。 size占用的内存大小已知,是size_t类型的长度,然后返回ret_ptr。当需要释放内存时,ret_ptr为passed 到内存管理器。通过ret_ptr,程序可以方便的计算出real_ptr的值,然后将real_ptr传递给free来释放内存。

图5 Redis块分配

Redis通过定义一个数组来记录所有的内存分配情况。该数组的长度为 ZMALLOC_MAX_ALLOC_STAT。数组的每个元素代表当前程序分配的内存块的数量,内存块的大小是该元素的下标。在源代码中,这个数组是zmalloc_allocations。 zmalloc_allocations[16]表示分配的内存块数量,长度为16字节。 zmalloc.c中有一个静态变量used_memory,用于记录当前分配的内存总大小。因此,一般情况下,Redis采用封装的malc/free,比Memcached的内存管理方式简单很多。

Redis与Memcached集群实现机制对比

Memcached是一个full-mem理论数据缓冲系统。 Redis虽然支持数据持久化,但满内存并不是其高性能的本质。作为基于内存的存储系统,机器物理内存的大小就是系统能够容纳的最大数据量。如果需要处理的数据量超过单机物理内存大小,就需要构建分布式集群来扩展存储能力。

Memcached的分布式存储

Memcached本身不支持分布式,所以只能通过一致性哈希的方式分布在客户端。实现Memcached分布式存储的算法。 Memcached的分布式存储实现架构如图6所示。客户端向Memcached集群发送数据之前,首先会通过内置的分布式算法计算出数据的目标节点,然后将数据直接发送到该节点进行存储。但当客户查询数据时,还必须计算出查询数据所在的节点,然后直接向该节点发送查询请求来获取数据。

图6 Memcached客户端分布式存储实现

Redis分布式存储

与Memcached相比,只能使用客户端来实现分布式存储,Redis更喜欢在服务器端构建分布式存储。虽然目前发布的Redis稳定版还没有添加分布式存储功能,但是Redis开发版已经具备了Redis Cluster的基本功能。预计在2.6版本之后,Redis将在2012年底之前发布完全支持分布式分发的稳定版本。下面我们将基于开发版本中的实现来简单介绍一下Redis Cluster的核心思想。

Redis Cluster是Redis的高级版本,实现分布式,允许单点的失败。它没有中心节点,具有线性可扩展性。图7展示了Redis Cluster的分布式存储架构,其中节点之间通过二进制协议进行通信,节点与客户端之间通过ascii协议进行通信。在数据放置策略上,Redis Cluster将整个键值域划分为4096个哈希槽,每个节点可以存储一个或多个哈希槽。也就是说,Redis Cluster目前支持的最大节点数是4096个。Redis Cluster使用的分布式算法也很简单:crc16(key) % HASH_SLOTS_NUMBER。

图7 Redis分布式架构

为了保证单点故障下的数据可用性,Redis Cluster引入了Master节点和Slave节点。如图4所示,在Redis Cluster中,每个Master节点都有两个对应的Slave节点,以实现冗余。这样在整个集群中,任意两个节点宕机都不会导致数据不可用能力。当Master节点退出时,集群会自动选出一个Slave节点成为新的Master节点。

图8 Redis集群中Master节点和Slave节点

Redis与Memcached整体对比

Redis的作者Salvatore Sanfilippo曾经比较过这两种基于内存的数据存储系统。总体来说还是比较客观的。总结如下:

1)性能对比:由于Redis只使用单核,而Memcached可以使用多核,因此平均而言,在每个核上存储小数据时,Redis比Memcached具有更高的性能。对于超过100k的数据,Memcached的性能高于Redis。虽然Redis最近针对存储大数据的性能进行了优化,但与Memcached相比还是稍逊一筹。

2)内存使用效率对比:如果采用简单的key-value存储,Memcached的内存利用率更高。如果Redis使用哈希结构作为key-值存储,由于其结合压缩,其内存利用率会高于Memcached。

3)Redis支持服务器端数据操作:与Memcached相比,Redis拥有更多的数据结构,支持更丰富的数据操作。通常在Memcached中,需要将数据获取到客户端。使用它进行类似的修改,然后将其恢复。这大大增加了网络IO数量和数据量。在 Redis 中,这些复杂的操作通常与常规 GET/SET 一样高效。因此,如果你需要缓存支持更复杂的结构和操作,那么Redis将是一个不错的选择。

我在这里分享一下redis和memcached的区别。希望以上内容能够对大家有所帮助,可以学到更多的知识。如果您觉得文章不错,可以分享出去,让更多的人看到。

1. 本站所有资源来源于用户上传或网络,仅作为参考研究使用,如有侵权请邮件联系站长!
2. 本站积分货币获取途径以及用途的解读,想在本站混的好,请务必认真阅读!
3. 本站强烈打击盗版/破解等有损他人权益和违法作为,请各位会员支持正版!
4. 编程技术 > redis 和 memcached 有什么区别

用户评论