导航:首页 > 源码编译 > 内存池slab算法

内存池slab算法

发布时间:2024-10-25 19:56:39

php面试题 memcache和redis的区别

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适用场景,如何正确的使用

前面已经分析过,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的设计。


Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。Redis只会缓存所有的
key的信息,如果Redis发现内存的使用量超过了某一个阀值,将触发swap的操作,Redis根据“swappability =
age*log(size_in_memory)”计
算出哪些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁盘中,同时在内存中清除。这种特性使得Redis可以

保持超过其机器本身内存大小的数据。当然,机器本身的内存必须要能够保持所有的key,毕竟这些数据是不会进行swap操作的。同时由于Redis将内存

中的数据swap到磁盘中的时候,提供服务的主线程和进行swap操作的子线程会共享这部分内存,所以如果更新需要swap的数据,Redis将阻塞这个
操作,直到子线程完成swap操作后才可以进行修改。

使用Redis特有内存模型前后的情况对比:
VM off: 300k keys, 4096 bytes values: 1.3G used
VM on: 300k keys, 4096 bytes values: 73M used
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 large as you want, still: 160.09M used



从Redis中读取数据的时候,如果读取的key对应的value不在内存中,那么Redis就需要从swap文件中加载相应数据,然后再返回给请求方。

这里就存在一个I/O线程池的问题。在默认的情况下,Redis会出现阻塞,即完成所有的swap文件加载后才会相应。这种策略在客户端的数量较小,进行

批量操作的时候比较合适。但是如果将Redis应用在一个大型的网站应用程序中,这显然是无法满足大并发的情况的。所以Redis运行我们设置I/O线程
池的大小,对需要从swap文件中加载相应数据的读取请求进行并发操作,减少阻塞的时间。

如果希望在海量数据的环境中使用好Redis,我相信理解Redis的内存设计和阻塞的情况是不可缺少的。

补充的知识点:

memcached和redis的比较

1 网络IO模型

Memcached是多线程,非阻塞IO复用的网络模型,分为监听主线程和worker子线程,监听线程监听网络连接,接受请求后,将连接描述
字pipe 传递给worker线程,进行读写IO, 网络层使用libevent封装的事件库,多线程模型可以发挥多核作用,但是引入了cache
coherency和锁的问题,比如,Memcached最常用的stats
命令,实际Memcached所有操作都要对这个全局变量加锁,进行计数等工作,带来了性能损耗。

(Memcached网络IO模型)

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

2.内存管理方面

Memcached使用预分配的内存池的方式,使用slab和大小不同的chunk来管理内存,Item根据大小选择合适的chunk存储,内
存池的方式可以省去申请/释放内存的开销,并且能减小内存碎片产生,但这种方式也会带来一定程度上的空间浪费,并且在内存仍然有很大空间时,新的数据也可
能会被剔除,原因可以参考Timyang的文章:http://timyang.net/data/Memcached-lru-evictions/

Redis使用现场申请内存的方式来存储数据,并且很少使用free-list等方式来优化内存分配,会在一定程度上存在内存碎片,Redis
跟据存储命令参数,会把带过期时间的数据单独存放在一起,并把它们称为临时数据,非临时数据是永远不会被剔除的,即便物理内存不够,导致swap也不会剔
除任何非临时数据(但会尝试剔除部分临时数据),这点上Redis更适合作为存储而不是cache。

3.数据一致性问题

Memcached提供了cas命令,可以保证多个并发访问操作同一份数据的一致性问题。 Redis没有提供cas 命令,并不能保证这点,不过Redis提供了事务的功能,可以保证一串 命令的原子性,中间不会被任何操作打断。

4.存储方式及其它方面

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

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

进行枚举操作,但不能在线上使用,如果需要枚举线上数据,Redis提供了工具可以直接扫描其mp文件,枚举出所有数据,Redis还同时提供了持久化和复制等功能。

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

在不同语言的客户端方面,Memcached和Redis都有丰富的第三方客户端可供选择,不过因为Memcached发展的时间更久一些,目
前看在客户端支持方面,Memcached的很多客户端更加成熟稳定,而Redis由于其协议本身就比Memcached复杂,加上作者不断增加新的功能
等,对应第三方客户端跟进速度可能会赶不上,有时可能需要自己在第三方客户端基础上做些修改才能更好的使用。

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

关于Redis的一些周边功能

Redis除了作为存储之外还提供了一些其它方面的功能,比如聚合计算、pubsub、scripting等,对于此类功能需要了解其实现原
理,清楚地了解到它的局限性后,才能正确的使用,比如pubsub功能,这个实际是没有任何持久化支持的,消费方连接闪断或重连之间过来的消息是会全部丢
失的,又比如聚合计算和scripting等功能受Redis单线程模型所限,是不可能达到很高的吞吐量的,需要谨慎使用。

总的来说Redis作者是一位非常勤奋的开发者,可以经常看到作者在尝试着各种不同的新鲜想法和思路,针对这些方面的功能就要求我们需要深入了解后再使用。

总结:

1.Redis使用最佳方式是全部数据in-memory。

2.Redis更多场景是作为Memcached的替代者来使用。

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

4.当存储的数据不能被剔除时,使用Redis更合适。

谈谈Memcached与Redis(一)

1. Memcached简介

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

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

1.1 Memcache配置

Memcached服务器在启动时需要对关键的参数进行配置,下面我们就看一看Memcached在启动时需要设定哪些关键参数以及这些参数的作用。

1)-p <num> Memcached的TCP监听端口,缺省配置为11211;

2)-U <num> Memcached的UDP监听端口,缺省配置为11211,为0时表示关闭UDP监听;

3)-s <file> Memcached监听的UNIX套接字路径;

4)-a <mask> 访问UNIX套接字的八进制掩码,缺省配置为0700;

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

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

7)-r 最大core文件大小;

8)-u <username> 运行Memcached的用户,如果当前为root的话需要使用此参数指定用户;

9)-m <num> 分配给Memcached使用的内存数量,单位是MB;

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

11)-c <num> 最大并发连数,缺省配置为1024;

12)-v –vv –vvv 设定服务器端打印的消息的详细程度,其中-v仅打印错误和警告信息,-vv在-v的基础上还会打印客户端的命令和相应,-vvv在-vv的基础上还会打印内存状态转换信息;

13)-f <factor> 用于设置chunk大小的递增因子;

14)-n <bytes> 最小的chunk大小,缺省配置为48个字节;

15)-t <num> Memcached服务器使用的线程数,缺省配置为4个;

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

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

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

2. Redis简介

Redis是一个开源的key-value存储系统。与Memcached类似,Redis将大部分数据存储在内存中,支持的数据类型包括:字
符串、哈希表、链表、集合、有序集合以及基于这些数据类型的相关操作。Redis使用C语言开发,在大多数像Linux、BSD和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的源码目录下,文件名为redis.conf。

② 鍐呭瓨绠$悊锛氢竴鏂囱绘哕Linux鍐呭瓨缁勭粐缁撴瀯鍙婇〉闱㈠竷灞

1銆佸唴瀛樻槸浠涔堬纻

1) 鍐呭瓨鍙堢О涓诲瓨锛屾槸 CPU 鑳界洿鎺ュ诲潃镄勫瓨鍌ㄧ┖闂达纴鐢卞崐瀵间綋鍣ㄤ欢鍒舵垚锛

2) 鍐呭瓨镄勭壒镣规槸瀛桦彇阃熺巼蹇锛屾柇鐢典竴鑸涓崭缭瀛樻暟鎹锛岄潪鎸佷箙鍖栬惧囷绂

2銆佸唴瀛樼殑浣灭敤

1) 𨱌傛椂瀛樻斁 cpu 镄勮繍绠楁暟鎹

2) 纭鐩樼瓑澶栭儴瀛桦偍鍣ㄤ氦鎹㈢殑鏁版嵁

3) 淇濋㱩 cpu 璁$畻链虹殑绋冲畾镐у拰楂樻ц兘

1銆乴inux 鍐呭瓨鍦板潃绌洪棿 Linux 鍐呭瓨绠$悊鍏ㄨ矊

2銆佸唴瀛桦湴鍧钬斺旂敤鎴锋&鍐呮牳镐

3銆佸唴瀛桦湴鍧钬斺拟MU 鍦板潃杞鎹

4銆佸唴瀛桦湴鍧钬斺斿垎娈垫満鍒

1) 娈甸夋嫨绗

镟村歀inux鍐呮牳瑙嗛戞暀绋嬫枃妗h祫鏂椤厤璐归嗗彇钖庡彴绉佷俊銆 鍐呮牳 銆戣嚜琛岃幏鍙栥

鍐呮牳瀛︿範缃戠珯锛

Linux鍐呮牳婧愮爜/鍐呭瓨璋冧紭/鏂囦欢绯荤粺/杩涚▼绠$悊/璁惧囬┍锷/缃戠粶鍗忚镙-瀛︿範瑙嗛戞暀绋-鑵捐璇惧爞

2) 鍒嗘靛疄鐜

5銆佸唴瀛桦湴鍧钬斺斿垎椤垫満鍒讹纸32 浣嶏级

6銆佺敤鎴锋佸湴鍧绌洪棿

7銆佸唴镙告佸湴鍧绌洪棿

8銆佽繘绋嫔唴瀛樼┖闂

鍐呭瓨绠$悊绠楁硶 钬斺斿硅ㄥ帉镊宸辩$悊鍐呭瓨镄勪汉𨱒ヨ存槸澶╄祼镄勭ぜ鐗

1銆佸唴瀛樼庣墖

1) 锘烘湰铡熺悊

2) 濡备綍阆垮厤鍐呭瓨纰庣墖

2銆佷紮浼寸郴缁熺畻娉曗斺旂粍缁囩粨鏋

1) 姒傚康

2) 澶栭儴纰庣墖

3銆佷紮浼寸郴缁熺畻娉曗斺旂敌璇峰拰锲炴敹

1) 鐢宠风畻娉

2) 锲炴敹绠楁硶

3) 𨱒′欢

4銆佸备綍鍒嗛厤 4M 浠ヤ笂鍐呭瓨锛

1) 涓轰綍闄愬埗澶у潡鍐呭瓨鍒嗛厤

2) 鍐呮牳涓銮峰彇 4M 浠ヤ笂澶у唴瀛樼殑鏂规硶

5銆佷紮浼寸郴缁颎斺斿弽纰庣墖链哄埗

1) 涓嶅彲绉诲姩椤

2) 鍙锲炴敹椤

6銆乻lab 绠楁硶钬斺斿熀链铡熺悊

1) 锘烘湰姒傚康

2) 鍐呴儴纰庣墖

7銆乻lab 鍒嗛厤鍣ㄧ殑缁撴瀯

璇︾粏鍙傝冿细

缁忓吀|锲捐ВLinux鍐呭瓨镐ц兘浼桦寲镙稿绩镐濇兂

8銆乻lab 楂橀熺紦瀛

1) 鏅阃氶珮阃熺紦瀛

2) 涓撶敤楂橀熺紦瀛

9銆佸唴镙告佸唴瀛樻睁

1) 锘烘湰铡熺悊

2) 鍐呮牳 API

10銆佺敤鎴锋佸唴瀛樻睁

1) C++ 瀹炰緥

11銆丏MA 鍐呭瓨

1) 浠涔堟槸 DMA

2) DMA 淇″彿

out of memory 镄勬椂浠h繃铡讳简钖楋纻no锛屽唴瀛桦啀鍏呰冻涔熶笉鍙浠绘т娇鐢ㄣ

1銆佸唴瀛樼殑浣跨敤鍦烘櫙

2銆佺敤鎴锋佸唴瀛桦垎閰嶅嚱鏁

a) 濡傛灉褰揿墠杩炵画鍐呭瓨鍧楄冻澶 realloc 镄勮瘽锛屽彧鏄灏 p 镓鎸囧悜镄勭┖闂存墿澶э纴骞惰繑锲 p 镄勬寚阍埚湴鍧銆傝繖涓镞跺 q 鍜 p 鎸囧悜镄勫湴鍧鏄涓镙风殑

b) 濡傛灉褰揿墠杩炵画鍐呭瓨鍧椾笉澶熼暱搴︼纴鍐嶆垒涓涓瓒冲熼暱镄勫湴鏂癸纴鍒嗛厤涓鍧楁柊镄勫唴瀛桡纴q锛屽苟灏 p 鎸囧悜镄勫唴瀹 鍒 q锛岃繑锲 q銆傚苟灏 p 镓鎸囧悜镄勫唴瀛樼┖闂村垹闄

3銆佸唴镙告佸唴瀛桦垎閰嶅嚱鏁

4銆乵alloc 鐢宠峰唴瀛

5銆佺己椤靛纾甯

6銆佺敤鎴疯繘绋嬭块梾鍐呭瓨鍒嗘瀽

7銆佸叡浜鍐呭瓨

1) 铡熺悊

2) shm 鎺ュ彛

1銆丆 鍐呭瓨娉勯湶

2銆丆 閲庢寚阍

3銆丆 璧勬簮璁块梾鍐茬獊

4銆丼TL 杩浠e櫒澶辨晥

阌栾绀轰緥锛氩垹闄ゅ綋鍓嶈凯浠e櫒锛岃凯浠e櫒浼氩け鏁

姝g‘绀轰緥锛氲凯浠e櫒 erase 镞讹纴闇淇濆瓨涓嬩竴涓杩浠e櫒

5銆丆++ 11 鏅鸿兘鎸囬拡

锛1锛夊师鐞嗗垎鏋愶细

锛2锛夋暟鎹缁撴瀯锛

锛3锛変娇鐢ㄦ柟娉曪细

6銆丆++ 11 镟村皬镟村揩镟村畨鍏

鍏銆 濡备綍镆ョ湅鍐呭瓨

鍙浠ラ氲繃 cat /proc/slabinfo 锻戒护镆ョ湅

鍙浠ラ氲繃 /proc/sys/vm/drop_caches𨱒ラ喷鏀

③ Redis和Memcached的区别

Redis的作者Salvatore Sanfilippo曾经对这两种基于内存的数据存储系统进行过比较:


1、Redis支持服务器端的数据操作:Redis相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,通常在Memcached里,你需要将数据拿到客户端来进行类似的修改再set回去。这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的GET/SET一样高效。所以,如果需要缓存能够支持更复杂的结构和操作,那么Redis会是不错的选择。


2、内存使用效率对比:使用简单的key-value存储的话,Memcached的内存利用率更高,而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。


3、性能对比:由于Redis只使用单核,而Memcached可以使用多核,所以平均每一个核上Redis在存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis最近也在存储大数据的性能上进行优化,但是比起Memcached,还是稍有逊色。


具体为什么会出现上面的结论,以下为收集到的资料:


1、数据类型支持不同


与Memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多。最为常用的数据类型主要由五种:String、Hash、List、Set和Sorted Set。Redis内部使用一个redisObject对象来表示所有的key和value。redisObject最主要的信息如图所示:




type代表一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部的存储方式,比如:type=string代表value存储的是一个普通字符串,那么对应的encoding可以是raw或者是int,如果是int则代表实际redis内部是按数值型类存储和表示这个字符串的,当然前提是这个字符串本身可以用数值表示,比如:”123″ “456”这样的字符串。只有打开了Redis的虚拟内存功能,vm字段字段才会真正的分配内存,该功能默认是关闭状态的。


1)String


阅读全文

与内存池slab算法相关的资料

热点内容
phpjson解析错误 浏览:487
算法加速工程师 浏览:494
内网不能访问公网服务器地址 浏览:640
程序员在厦门做什么工作 浏览:682
linuxmatlab卸载 浏览:983
bat女程序员数量 浏览:517
安卓怎么拍手机里照片 浏览:386
如何连接无尽之剑服务器 浏览:574
业务型it程序员和技术员程序员 浏览:811
windows下命令 浏览:714
程序员努力进阿里 浏览:226
武器压缩技术 浏览:815
pythonindexpackage 浏览:626
php网页运行原理 浏览:283
老人存的定期存款可以加密码吗 浏览:233
tde透明加密性能 浏览:328
蛮力字符串匹配算法 浏览:220
网络广告是什么app 浏览:566
win11如何解压文件 浏览:871
猫眼是干什么的app 浏览:945