1.Redis和Memcached的区别
2.redisåmemcachedçåºå«
3.Java教程:dubbo源码解析-网络通信
Redis和Memcached的区别
Redis和Memcached是两种基于内存的高性能数据存储系统,它们在多个方面具有不同特点。以下将从网络IO模型、数据支持类型、内存管理机制、数据存储及持久化、伏魔决源码数据一致性问题以及集群管理等角度,详细比较两者的主要区别。
网络IO模型方面,Memcached采用多线程模型进行非阻塞IO复用,通过libevent封装的事件库实现。虽然这种模型可以充分利用多核资源,但也引入了cache coherency和锁问题,比如在执行stats命令时需要对全局变量加锁,影响性能。相比之下,武侠宗师源码Redis使用单线程IO复用模型,利用封装的AeEvent事件处理框架,优化了IO调度,对单存操作有速度优势,但当涉及计算操作时,单线程模型可能会限制整体吞吐量。
数据支持类型上,Memcached仅支持简单的key-value形式存储,而Redis在提供key-value支持的同时,还具备更丰富数据结构,如list、set、zset和hash等,这使得Redis在处理复杂数据逻辑时更灵活。
在内存管理机制上,asus 源码编译Memcached采用Slab Allocation机制管理内存,将内存分割成特定长度的块以存储相应长度的key-value数据记录,有效地解决了内存碎片问题。Redis则采用源码封装的内存管理机制,通过记录分配情况的数组和内存头部存储大小信息,实现内存块管理,相对简单高效。两者在内存使用效率上有不同侧重点,Memcached在不造成内存碎片的同时可能带来空间浪费,而Redis的内存管理虽简单但可能产生内存碎片。
数据存储及持久化方面,Memcached不支持数据持久化,所有数据均保存在内存中。Redis则支持持久化操作,通过快照(snapshotting)或只追加文件(AOF)两种方法将数据存储到硬盘,YB支付源码提供了数据恢复的可能。
数据一致性问题上,Memcached通过cas命令保证多并发访问同一数据时的一致性,而Redis未提供cas命令,但可通过事务功能实现命令原子性,避免被其他操作打断。
集群管理方面,Memcached依赖客户端通过分布式算法实现集群存储,客户端查询数据同样需计算目标节点。Redis则倾向于在服务器端构建分布式存储,最新版本的Redis支持分布式存储功能,采用Redis Cluster实现线性可伸缩的分布式架构,节点间通过二进制协议通信,支持自动故障转移,保证数据可用性。方框绘制源码
综上所述,Redis相较于Memcached在数据结构、持久化能力、集群管理等方面有更多优势,但两者根据具体应用场景和需求选择,各有其适用场景。
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æ§è½æ´é«ãèå¨k以ä¸çæ°æ®ä¸ï¼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å é¨æ¯ææ°å¼åç±»åå¨å表示è¿ä¸ªå符串çï¼å½ç¶åææ¯è¿ä¸ªå符串æ¬èº«å¯ä»¥ç¨æ°å¼è¡¨ç¤ºï¼æ¯å¦:ââ³ ââè¿æ ·çå符串ãåªææå¼äºRedisçèæå ååè½ï¼vmå段å段æä¼çæ£çåé å åï¼è¯¥åè½é»è®¤æ¯å ³éç¶æçã
1ï¼String
常ç¨å½ä»¤ï¼set/get/decr/incr/mgetçï¼
åºç¨åºæ¯ï¼Stringæ¯æ常ç¨çä¸ç§æ°æ®ç±»åï¼æ®éçkey/valueåå¨é½å¯ä»¥å½ä¸ºæ¤ç±»ï¼
å®ç°æ¹å¼ï¼Stringå¨rediså é¨åå¨é»è®¤å°±æ¯ä¸ä¸ªå符串ï¼è¢«redisObjectæå¼ç¨ï¼å½éå°incrãdecrçæä½æ¶ä¼è½¬ææ°å¼åè¿è¡è®¡ç®ï¼æ¤æ¶redisObjectçencodingå段为intã
2ï¼Hash
常ç¨å½ä»¤ï¼hget/hset/hgetallç
åºç¨åºæ¯ï¼æ们è¦åå¨ä¸ä¸ªç¨æ·ä¿¡æ¯å¯¹è±¡æ°æ®ï¼å ¶ä¸å æ¬ç¨æ·IDãç¨æ·å§åãå¹´é¾åçæ¥ï¼éè¿ç¨æ·IDæ们å¸æè·å该ç¨æ·çå§åæè å¹´é¾æè çæ¥ï¼
å®ç°æ¹å¼ï¼RedisçHashå®é æ¯å é¨åå¨çValue为ä¸ä¸ªHashMapï¼å¹¶æä¾äºç´æ¥ååè¿ä¸ªMapæåçæ¥å£ãå¦å¾æ示ï¼Keyæ¯ç¨æ·ID, valueæ¯ä¸ä¸ªMapãè¿ä¸ªMapçkeyæ¯æåçå±æ§åï¼valueæ¯å±æ§å¼ãè¿æ ·å¯¹æ°æ®çä¿®æ¹åååé½å¯ä»¥ç´æ¥éè¿å ¶å é¨MapçKey(Redisé称å é¨Mapçkey为field), ä¹å°±æ¯éè¿ key(ç¨æ·ID) + field(å±æ§æ ç¾) å°±å¯ä»¥æä½å¯¹åºå±æ§æ°æ®ãå½åHashMapçå®ç°æ两ç§æ¹å¼ï¼å½HashMapçæåæ¯è¾å°æ¶Redis为äºèçå åä¼éç¨ç±»ä¼¼ä¸ç»´æ°ç»çæ¹å¼æ¥ç´§ååå¨ï¼èä¸ä¼éç¨çæ£çHashMapç»æï¼è¿æ¶å¯¹åºçvalueçredisObjectçencoding为zipmapï¼å½æåæ°éå¢å¤§æ¶ä¼èªå¨è½¬æçæ£çHashMap,æ¤æ¶encoding为htã
3ï¼List
常ç¨å½ä»¤ï¼lpush/rpush/lpop/rpop/lrangeçï¼
åºç¨åºæ¯ï¼Redis listçåºç¨åºæ¯é常å¤ï¼ä¹æ¯Redisæéè¦çæ°æ®ç»æä¹ä¸ï¼æ¯å¦twitterçå ³æ³¨å表ï¼ç²ä¸å表çé½å¯ä»¥ç¨Redisçlistç»ææ¥å®ç°ï¼
å®ç°æ¹å¼ï¼Redis listçå®ç°ä¸ºä¸ä¸ªååé¾è¡¨ï¼å³å¯ä»¥æ¯æååæ¥æ¾åéåï¼æ´æ¹ä¾¿æä½ï¼ä¸è¿å¸¦æ¥äºé¨åé¢å¤çå åå¼éï¼Rediså é¨çå¾å¤å®ç°ï¼å æ¬åéç¼å²éåçä¹é½æ¯ç¨çè¿ä¸ªæ°æ®ç»æã
4ï¼Set
常ç¨å½ä»¤ï¼sadd/spop/smembers/sunionçï¼
åºç¨åºæ¯ï¼Redis set对å¤æä¾çåè½ä¸list类似æ¯ä¸ä¸ªå表çåè½ï¼ç¹æ®ä¹å¤å¨äºsetæ¯å¯ä»¥èªå¨æéçï¼å½ä½ éè¦åå¨ä¸ä¸ªå表æ°æ®ï¼åä¸å¸æåºç°éå¤æ°æ®æ¶ï¼setæ¯ä¸ä¸ªå¾å¥½çéæ©ï¼å¹¶ä¸setæä¾äºå¤ææ个æåæ¯å¦å¨ä¸ä¸ªsetéåå çéè¦æ¥å£ï¼è¿ä¸ªä¹æ¯listæä¸è½æä¾çï¼
å®ç°æ¹å¼ï¼set çå é¨å®ç°æ¯ä¸ä¸ª valueæ°¸è¿ä¸ºnullçHashMapï¼å®é å°±æ¯éè¿è®¡ç®hashçæ¹å¼æ¥å¿«éæéçï¼è¿ä¹æ¯setè½æä¾å¤æä¸ä¸ªæåæ¯å¦å¨éåå çåå ã
5ï¼Sorted Set
常ç¨å½ä»¤ï¼zadd/zrange/zrem/zcardçï¼
åºç¨åºæ¯ï¼Redis sorted setç使ç¨åºæ¯ä¸set类似ï¼åºå«æ¯setä¸æ¯èªå¨æåºçï¼èsorted setå¯ä»¥éè¿ç¨æ·é¢å¤æä¾ä¸ä¸ªä¼å 级(score)çåæ°æ¥ä¸ºæåæåºï¼å¹¶ä¸æ¯æå ¥æåºçï¼å³èªå¨æåºãå½ä½ éè¦ä¸ä¸ªæåºç并ä¸ä¸éå¤çéåå表ï¼é£ä¹å¯ä»¥éæ©sorted setæ°æ®ç»æï¼æ¯å¦twitter çpublic timelineå¯ä»¥ä»¥å表æ¶é´ä½ä¸ºscoreæ¥åå¨ï¼è¿æ ·è·åæ¶å°±æ¯èªå¨ææ¶é´æ好åºçã
å®ç°æ¹å¼ï¼Redis sorted setçå é¨ä½¿ç¨HashMapåè·³è·è¡¨(SkipList)æ¥ä¿è¯æ°æ®çåå¨åæåºï¼HashMapéæ¾çæ¯æåå°scoreçæ å°ï¼èè·³è·è¡¨éåæ¾çæ¯ææçæåï¼æåºä¾æ®æ¯HashMapéåçscore,使ç¨è·³è·è¡¨çç»æå¯ä»¥è·å¾æ¯è¾é«çæ¥æ¾æçï¼å¹¶ä¸å¨å®ç°ä¸æ¯è¾ç®åã
2ãå å管çæºå¶ä¸å
å¨Redisä¸ï¼å¹¶ä¸æ¯ææçæ°æ®é½ä¸ç´åå¨å¨å åä¸çãè¿æ¯åMemcachedç¸æ¯ä¸ä¸ªæ大çåºå«ãå½ç©çå åç¨å®æ¶ï¼Rediså¯ä»¥å°ä¸äºå¾ä¹ 没ç¨å°çvalue交æ¢å°ç£çã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ä¸è¯»åæ°æ®çæ¶åï¼å¦æ读åçkey对åºçvalueä¸å¨å åä¸ï¼é£ä¹Rediså°±éè¦ä»swapæ件ä¸å è½½ç¸åºæ°æ®ï¼ç¶ååè¿åç»è¯·æ±æ¹ã è¿éå°±åå¨ä¸ä¸ªI/O线ç¨æ± çé®é¢ãå¨é»è®¤çæ åµä¸ï¼Redisä¼åºç°é»å¡ï¼å³å®æææçswapæ件å è½½åæä¼ç¸åºãè¿ç§çç¥å¨å®¢æ·ç«¯çæ°éè¾å°ï¼è¿è¡æ¹éæä½çæ¶åæ¯è¾åéãä½æ¯å¦æå°Redisåºç¨å¨ä¸ä¸ªå¤§åçç½ç«åºç¨ç¨åºä¸ï¼è¿æ¾ç¶æ¯æ æ³æ»¡è¶³å¤§å¹¶åçæ åµçãæ以Redisè¿è¡æ们设置I/O线ç¨æ± ç大å°ï¼å¯¹éè¦ä»swapæ件ä¸å è½½ç¸åºæ°æ®ç读å请æ±è¿è¡å¹¶åæä½ï¼åå°é»å¡çæ¶é´ã
对äºåRedisåMemcachedè¿ç§åºäºå åçæ°æ®åºç³»ç»æ¥è¯´ï¼å å管ççæçé«ä½æ¯å½±åç³»ç»æ§è½çå ³é®å ç´ ãä¼ ç»Cè¯è¨ä¸çmalloc/freeå½æ°æ¯æ常ç¨çåé åéæ¾å åçæ¹æ³ï¼ä½æ¯è¿ç§æ¹æ³åå¨çå¾å¤§ç缺é·ï¼é¦å ï¼å¯¹äºå¼å人åæ¥è¯´ä¸å¹é çmallocåfree容æé æå åæ³é²ï¼å ¶æ¬¡é¢ç¹è°ç¨ä¼é æ大éå åç¢çæ æ³åæ¶éæ°å©ç¨ï¼éä½å åå©ç¨çï¼æåä½ä¸ºç³»ç»è°ç¨ï¼å ¶ç³»ç»å¼éè¿è¿å¤§äºä¸è¬å½æ°è°ç¨ãæ以ï¼ä¸ºäºæé«å åç管çæçï¼é«æçå å管çæ¹æ¡é½ä¸ä¼ç´æ¥ä½¿ç¨malloc/freeè°ç¨ãRedisåMemcachedå使ç¨äºèªèº«è®¾è®¡çå å管çæºå¶ï¼ä½æ¯å®ç°æ¹æ³åå¨å¾å¤§çå·®å¼ï¼ä¸é¢å°ä¼å¯¹ä¸¤è çå å管çæºå¶åå«è¿è¡ä»ç»ã
Memcachedé»è®¤ä½¿ç¨Slab Allocationæºå¶ç®¡çå åï¼å ¶ä¸»è¦ææ³æ¯æç §é¢å è§å®ç大å°ï¼å°åé çå ååå²æç¹å®é¿åº¦çå以åå¨ç¸åºé¿åº¦çkey-valueæ°æ®è®°å½ï¼ä»¥å®å ¨è§£å³å åç¢çé®é¢ãSlab Allocationæºå¶åªä¸ºåå¨å¤é¨æ°æ®è设计ï¼ä¹å°±æ¯è¯´ææçkey-valueæ°æ®é½åå¨å¨Slab Allocationç³»ç»éï¼èMemcachedçå ¶å®å å请æ±åéè¿æ®éçmalloc/freeæ¥ç³è¯·ï¼å 为è¿äºè¯·æ±çæ°éåé¢çå³å®äºå®ä»¬ä¸ä¼å¯¹æ´ä¸ªç³»ç»çæ§è½é æå½±åSlab Allocationçåçç¸å½ç®åã å¦å¾æ示ï¼å®é¦å ä»æä½ç³»ç»ç³è¯·ä¸å¤§åå åï¼å¹¶å°å ¶åå²æåç§å°ºå¯¸çåChunkï¼å¹¶æ尺寸ç¸åçååæç»Slab Classãå ¶ä¸ï¼Chunkå°±æ¯ç¨æ¥åå¨key-valueæ°æ®çæå°åä½ãæ¯ä¸ªSlab Classç大å°ï¼å¯ä»¥å¨Memcachedå¯å¨çæ¶åéè¿å¶å®Growth Factoræ¥æ§å¶ãåå®å¾ä¸Growth Factorçåå¼ä¸º1.ï¼å¦æ第ä¸ç»Chunkç大å°ä¸ºä¸ªåèï¼ç¬¬äºç»Chunkç大å°å°±ä¸ºä¸ªåèï¼ä¾æ¤ç±»æ¨ã
å½Memcachedæ¥æ¶å°å®¢æ·ç«¯åéè¿æ¥çæ°æ®æ¶é¦å ä¼æ ¹æ®æ¶å°æ°æ®ç大å°éæ©ä¸ä¸ªæåéçSlab Classï¼ç¶åéè¿æ¥è¯¢Memcachedä¿åçç该Slab Classå 空é²Chunkçå表就å¯ä»¥æ¾å°ä¸ä¸ªå¯ç¨äºåå¨æ°æ®çChunkãå½ä¸æ¡æ°æ®åºè¿ææè 丢å¼æ¶ï¼è¯¥è®°å½æå ç¨çChunkå°±å¯ä»¥åæ¶ï¼éæ°æ·»å å°ç©ºé²å表ä¸ãä»ä»¥ä¸è¿ç¨æ们å¯ä»¥çåºMemcachedçå å管çå¶æçé«ï¼èä¸ä¸ä¼é æå åç¢çï¼ä½æ¯å®æ大ç缺ç¹å°±æ¯ä¼å¯¼è´ç©ºé´æµªè´¹ãå 为æ¯ä¸ªChunké½åé äºç¹å®é¿åº¦çå å空é´ï¼æ以åé¿æ°æ®æ æ³å åå©ç¨è¿äºç©ºé´ãå¦å¾ æ示ï¼å°ä¸ªåèçæ°æ®ç¼åå°ä¸ªåèçChunkä¸ï¼å©ä½ç个åè就浪费æäºã
Redisçå å管ç主è¦éè¿æºç ä¸zmalloc.håzmalloc.c两个æ件æ¥å®ç°çãRedis为äºæ¹ä¾¿å åç管çï¼å¨åé ä¸åå åä¹åï¼ä¼å°è¿åå åç大å°åå ¥å ååç头é¨ãå¦å¾æ示ï¼real_ptræ¯redisè°ç¨mallocåè¿åçæéãrediså°å ååç大å°sizeåå ¥å¤´é¨ï¼sizeæå æ®çå å大å°æ¯å·²ç¥çï¼ä¸ºsize_tç±»åçé¿åº¦ï¼ç¶åè¿året_ptrãå½éè¦éæ¾å åçæ¶åï¼ret_ptrè¢«ä¼ ç»å å管çç¨åºãéè¿ret_ptrï¼ç¨åºå¯ä»¥å¾å®¹æçç®åºreal_ptrçå¼ï¼ç¶åå°real_pträ¼ ç»freeéæ¾å åã
Rediséè¿å®ä¹ä¸ä¸ªæ°ç»æ¥è®°å½ææçå ååé æ åµï¼è¿ä¸ªæ°ç»çé¿åº¦ä¸ºZMALLOC_MAX_ALLOC_STATãæ°ç»çæ¯ä¸ä¸ªå ç´ ä»£è¡¨å½åç¨åºæåé çå ååç个æ°ï¼ä¸å ååç大å°ä¸ºè¯¥å ç´ çä¸æ ãå¨æºç ä¸ï¼è¿ä¸ªæ°ç»ä¸ºzmalloc_allocationsãzmalloc_allocations[]代表已ç»åé çé¿åº¦ä¸ºbytesçå ååç个æ°ãzmalloc.cä¸æä¸ä¸ªéæåéused_memoryç¨æ¥è®°å½å½ååé çå åæ»å¤§å°ãæ以ï¼æ»çæ¥çï¼Rediséç¨çæ¯å è£ çmallc/freeï¼ç¸è¾äºMemcachedçå å管çæ¹æ³æ¥è¯´ï¼è¦ç®åå¾å¤ã
3ãæ°æ®æä¹ åæ¯æ
Redisè½ç¶æ¯åºäºå åçåå¨ç³»ç»ï¼ä½æ¯å®æ¬èº«æ¯æ¯æå åæ°æ®çæä¹ åçï¼èä¸æä¾ä¸¤ç§ä¸»è¦çæä¹ åçç¥ï¼RDBå¿«ç §åAOFæ¥å¿ãèmemcachedæ¯ä¸æ¯ææ°æ®æä¹ åæä½çã
1ï¼RDBå¿«ç §
Redisæ¯æå°å½åæ°æ®çå¿«ç §åæä¸ä¸ªæ°æ®æ件çæä¹ åæºå¶ï¼å³RDBå¿«ç §ãä½æ¯ä¸ä¸ªæç»åå ¥çæ°æ®åºå¦ä½çæå¿«ç §å¢ï¼Redisåå©äºforkå½ä»¤çcopy on writeæºå¶ãå¨çæå¿«ç §æ¶ï¼å°å½åè¿ç¨forkåºä¸ä¸ªåè¿ç¨ï¼ç¶åå¨åè¿ç¨ä¸å¾ªç¯ææçæ°æ®ï¼å°æ°æ®åæ为RDBæ件ãæ们å¯ä»¥éè¿Redisçsaveæ令æ¥é ç½®RDBå¿«ç §çæçæ¶æºï¼æ¯å¦é ç½®åéå°±çæå¿«ç §ï¼ä¹å¯ä»¥é ç½®æ次åå ¥å°±çæå¿«ç §ï¼ä¹å¯ä»¥å¤ä¸ªè§åä¸èµ·å®æ½ãè¿äºè§åçå®ä¹å°±å¨Redisçé ç½®æ件ä¸ï¼ä½ ä¹å¯ä»¥éè¿RedisçCONFIG SETå½ä»¤å¨Redisè¿è¡æ¶è®¾ç½®è§åï¼ä¸éè¦éå¯Redisã
RedisçRDBæ件ä¸ä¼åæï¼å ä¸ºå ¶åæä½æ¯å¨ä¸ä¸ªæ°è¿ç¨ä¸è¿è¡çï¼å½çæä¸ä¸ªæ°çRDBæ件æ¶ï¼Redisçæçåè¿ç¨ä¼å å°æ°æ®åå°ä¸ä¸ªä¸´æ¶æ件ä¸ï¼ç¶åéè¿ååæ§renameç³»ç»è°ç¨å°ä¸´æ¶æ件éå½å为RDBæ件ï¼è¿æ ·å¨ä»»ä½æ¶ååºç°æ éï¼RedisçRDBæ件é½æ»æ¯å¯ç¨çãåæ¶ï¼RedisçRDBæ件ä¹æ¯Redis主ä»åæ¥å é¨å®ç°ä¸çä¸ç¯ãRDBæä»çä¸è¶³ï¼å°±æ¯ä¸æ¦æ°æ®åºåºç°é®é¢ï¼é£ä¹æ们çRDBæ件ä¸ä¿åçæ°æ®å¹¶ä¸æ¯å ¨æ°çï¼ä»ä¸æ¬¡RDBæ件çæå°Redisåæºè¿æ®µæ¶é´çæ°æ®å ¨é¨ä¸¢æäºãå¨æäºä¸å¡ä¸ï¼è¿æ¯å¯ä»¥å¿åçã
2ï¼AOFæ¥å¿
AOFæ¥å¿çå ¨ç§°æ¯append only fileï¼å®æ¯ä¸ä¸ªè¿½å åå ¥çæ¥å¿æ件ãä¸ä¸è¬æ°æ®åºçbinlogä¸åçæ¯ï¼AOFæ件æ¯å¯è¯å«ç纯ææ¬ï¼å®çå 容就æ¯ä¸ä¸ªä¸ªçRedisæ åå½ä»¤ãåªæé£äºä¼å¯¼è´æ°æ®åçä¿®æ¹çå½ä»¤æä¼è¿½å å°AOFæ件ãæ¯ä¸æ¡ä¿®æ¹æ°æ®çå½ä»¤é½çæä¸æ¡æ¥å¿ï¼AOFæ件ä¼è¶æ¥è¶å¤§ï¼æ以Redisåæä¾äºä¸ä¸ªåè½ï¼å«åAOF rewriteãå ¶åè½å°±æ¯éæ°çæä¸ä»½AOFæ件ï¼æ°çAOFæ件ä¸ä¸æ¡è®°å½çæä½åªä¼æä¸æ¬¡ï¼èä¸åä¸ä»½èæ件é£æ ·ï¼å¯è½è®°å½äºå¯¹åä¸ä¸ªå¼çå¤æ¬¡æä½ãå ¶çæè¿ç¨åRDB类似ï¼ä¹æ¯forkä¸ä¸ªè¿ç¨ï¼ç´æ¥éåæ°æ®ï¼åå ¥æ°çAOF临æ¶æ件ãå¨åå ¥æ°æ件çè¿ç¨ä¸ï¼ææçåæä½æ¥å¿è¿æ¯ä¼åå°åæ¥èçAOFæ件ä¸ï¼åæ¶è¿ä¼è®°å½å¨å åç¼å²åºä¸ãå½éå®æä½å®æåï¼ä¼å°ææç¼å²åºä¸çæ¥å¿ä¸æ¬¡æ§åå ¥å°ä¸´æ¶æ件ä¸ãç¶åè°ç¨ååæ§çrenameå½ä»¤ç¨æ°çAOFæ件å代èçAOFæ件ã
AOFæ¯ä¸ä¸ªåæ件æä½ï¼å ¶ç®çæ¯å°æä½æ¥å¿åå°ç£çä¸ï¼æ以å®ä¹åæ ·ä¼éå°æ们ä¸é¢è¯´çåæä½çæµç¨ãå¨Redisä¸å¯¹AOFè°ç¨writeåå ¥åï¼éè¿appendfsyncé项æ¥æ§å¶è°ç¨fsyncå°å ¶åå°ç£çä¸çæ¶é´ï¼ä¸é¢appendfsyncçä¸ä¸ªè®¾ç½®é¡¹ï¼å®å ¨å¼ºåº¦éæ¸å强ã
appendfsync no å½è®¾ç½®appendfsync为noçæ¶åï¼Redisä¸ä¼ä¸»å¨è°ç¨fsyncå»å°AOFæ¥å¿å 容åæ¥å°ç£çï¼æ以è¿ä¸åå°±å®å ¨ä¾èµäºæä½ç³»ç»çè°è¯äºã对大å¤æ°Linuxæä½ç³»ç»ï¼æ¯æ¯ç§è¿è¡ä¸æ¬¡fsyncï¼å°ç¼å²åºä¸çæ°æ®åå°ç£çä¸ã
appendfsync everysec å½è®¾ç½®appendfsync为everysecçæ¶åï¼Redisä¼é»è®¤æ¯éä¸ç§è¿è¡ä¸æ¬¡fsyncè°ç¨ï¼å°ç¼å²åºä¸çæ°æ®åå°ç£çãä½æ¯å½è¿ä¸æ¬¡çfsyncè°ç¨æ¶é¿è¶ è¿1ç§æ¶ãRedisä¼éå延è¿fsyncççç¥ï¼åçä¸ç§éãä¹å°±æ¯å¨ä¸¤ç§ååè¿è¡fsyncï¼è¿ä¸æ¬¡çfsyncå°±ä¸ç®¡ä¼æ§è¡å¤é¿æ¶é´é½ä¼è¿è¡ãè¿æ¶åç±äºå¨fsyncæ¶æ件æ述符ä¼è¢«é»å¡ï¼æ以å½åçåæä½å°±ä¼é»å¡ãæ以ç»è®ºå°±æ¯ï¼å¨ç»å¤§å¤æ°æ åµä¸ï¼Redisä¼æ¯éä¸ç§è¿è¡ä¸æ¬¡fsyncãå¨æåçæ åµä¸ï¼ä¸¤ç§éä¼è¿è¡ä¸æ¬¡fsyncæä½ãè¿ä¸æä½å¨å¤§å¤æ°æ°æ®åºç³»ç»ä¸è¢«ç§°ä¸ºgroup commitï¼å°±æ¯ç»åå¤æ¬¡åæä½çæ°æ®ï¼ä¸æ¬¡æ§å°æ¥å¿åå°ç£çã
appednfsync always å½è®¾ç½®appendfsync为alwaysæ¶ï¼æ¯ä¸æ¬¡åæä½é½ä¼è°ç¨ä¸æ¬¡fsyncï¼è¿æ¶æ°æ®æ¯æå®å ¨çï¼å½ç¶ï¼ç±äºæ¯æ¬¡é½ä¼æ§è¡fsyncï¼æä»¥å ¶æ§è½ä¹ä¼åå°å½±åã
对äºä¸è¬æ§çä¸å¡éæ±ï¼å»ºè®®ä½¿ç¨RDBçæ¹å¼è¿è¡æä¹ åï¼åå æ¯RDBçå¼é并ç¸æ¯AOFæ¥å¿è¦ä½å¾å¤ï¼å¯¹äºé£äºæ æ³å¿æ°æ®ä¸¢å¤±çåºç¨ï¼å»ºè®®ä½¿ç¨AOFæ¥å¿ã
4ãé群管ççä¸å
Memcachedæ¯å ¨å åçæ°æ®ç¼å²ç³»ç»ï¼Redisè½ç¶æ¯ææ°æ®çæä¹ åï¼ä½æ¯å ¨å åæ¯ç«ææ¯å ¶é«æ§è½çæ¬è´¨ãä½ä¸ºåºäºå åçåå¨ç³»ç»æ¥è¯´ï¼æºå¨ç©çå åç大å°å°±æ¯ç³»ç»è½å¤å®¹çº³çæ大æ°æ®éãå¦æéè¦å¤ççæ°æ®éè¶ è¿äºåå°æºå¨çç©çå å大å°ï¼å°±éè¦æ建åå¸å¼é群æ¥æ©å±åå¨è½åã
Memcachedæ¬èº«å¹¶ä¸æ¯æåå¸å¼ï¼å æ¤åªè½å¨å®¢æ·ç«¯éè¿åä¸è´æ§åå¸è¿æ ·çåå¸å¼ç®æ³æ¥å®ç°Memcachedçåå¸å¼åå¨ãä¸å¾ç»åºäºMemcachedçåå¸å¼åå¨å®ç°æ¶æãå½å®¢æ·ç«¯åMemcachedé群åéæ°æ®ä¹åï¼é¦å ä¼éè¿å ç½®çåå¸å¼ç®æ³è®¡ç®åºè¯¥æ¡æ°æ®çç®æ èç¹ï¼ç¶åæ°æ®ä¼ç´æ¥åéå°è¯¥èç¹ä¸åå¨ãä½å®¢æ·ç«¯æ¥è¯¢æ°æ®æ¶ï¼åæ ·è¦è®¡ç®åºæ¥è¯¢æ°æ®æå¨çèç¹ï¼ç¶åç´æ¥å该èç¹åéæ¥è¯¢è¯·æ±ä»¥è·åæ°æ®ã
ç¸è¾äºMemcachedåªè½éç¨å®¢æ·ç«¯å®ç°åå¸å¼åå¨ï¼Redisæ´ååäºå¨æå¡å¨ç«¯æ建åå¸å¼åå¨ãææ°çæ¬çRediså·²ç»æ¯æäºåå¸å¼åå¨åè½ãRedis Clusteræ¯ä¸ä¸ªå®ç°äºåå¸å¼ä¸å 许åç¹æ éçRedisé«çº§çæ¬ï¼å®æ²¡æä¸å¿èç¹ï¼å ·æ线æ§å¯ä¼¸ç¼©çåè½ãä¸å¾ç»åºRedis Clusterçåå¸å¼åå¨æ¶æï¼å ¶ä¸èç¹ä¸èç¹ä¹é´éè¿äºè¿å¶åè®®è¿è¡éä¿¡ï¼èç¹ä¸å®¢æ·ç«¯ä¹é´éè¿asciiåè®®è¿è¡éä¿¡ãå¨æ°æ®çæ¾ç½®çç¥ä¸ï¼Redis Clusterå°æ´ä¸ªkeyçæ°å¼ååæ个åå¸æ§½ï¼æ¯ä¸ªèç¹ä¸å¯ä»¥åå¨ä¸ä¸ªæå¤ä¸ªåå¸æ§½ï¼ä¹å°±æ¯è¯´å½åRedis Clusteræ¯æçæ大èç¹æ°å°±æ¯ãRedis Cluster使ç¨çåå¸å¼ç®æ³ä¹å¾ç®åï¼crc( key ) % HASH_SLOTS_NUMBERã
为äºä¿è¯åç¹æ éä¸çæ°æ®å¯ç¨æ§ï¼Redis Clusterå¼å ¥äºMasterèç¹åSlaveèç¹ãå¨Redis Clusterä¸ï¼æ¯ä¸ªMasterèç¹é½ä¼æ对åºç两个ç¨äºåä½çSlaveèç¹ãè¿æ ·å¨æ´ä¸ªé群ä¸ï¼ä»»æ两个èç¹çå®æºé½ä¸ä¼å¯¼è´æ°æ®çä¸å¯ç¨ãå½Masterèç¹éåºåï¼é群ä¼èªå¨éæ©ä¸ä¸ªSlaveèç¹æ为æ°çMasterèç¹ã
Java教程:dubbo源码解析-网络通信
在之前的内容中,我们探讨了消费者端服务发现与提供者端服务暴露的相关内容,同时了解到消费者端通过内置的负载均衡算法获取合适的调用invoker进行远程调用。接下来,我们聚焦于远程调用过程,即网络通信的细节。
网络通信位于Remoting模块中,支持多种通信协议,包括但不限于:dubbo协议、rmi协议、hessian协议、ty进行网络通讯,NettyClient.doOpen()方法中可以看到Netty的相关类。序列化接口包括但不限于:Serialization接口、Hessian2Serialization接口、Kryo接口、FST接口等。
序列化方式如Kryo和FST,性能往往优于hessian2,能够显著提高序列化性能。这些高效Java序列化方式的引入,可以优化Dubbo的序列化过程。
在配置Dubbo RPC时,引入Kryo和FST非常简单,只需在RPC的XML配置中添加相应的属性即可。
关于服务消费方发送请求,Dubbo框架定义了私有的RPC协议,消息头和消息体分别用于存储元信息和具体调用消息。消息头包括魔数、数据包类型、消息体长度等。消息体包含调用消息,如方法名称、参数列表等。请求编码和解码过程涉及编解码器的使用,编码过程包括消息头的写入、序列化数据的存储以及长度的写入。解码过程则涉及消息头的读取、序列化数据的解析以及调用方法名、参数等信息的提取。
提供方接收请求后,服务调用过程包含请求解码、调用服务以及返回结果。解码过程在NettyHandler中完成,通过ChannelEventRunnable和DecodeHandler进一步处理请求。服务调用完成后,通过Invoker的invoke方法调用服务逻辑。响应数据的编码与请求数据编码过程类似,涉及数据包的构造与发送。
服务消费方接收调用结果后,首先进行响应数据解码,获得Response对象,并传递给下一个处理器NettyHandler。处理后,响应数据被派发到线程池中,此过程与服务提供方接收请求的过程类似。
在异步通信场景中,Dubbo在通信层面为异步操作,通信线程不会等待结果返回。默认情况下,RPC调用被视为同步操作。Dubbo通过CompletableFuture实现了异步转同步操作,通过设置异步返回结果并使用CompletableFuture的get()方法等待完成。
对于异步多线程数据一致性问题,Dubbo使用编号将响应对象与Future对象关联,确保每个响应对象被正确传递到相应的Future对象。通过在创建Future时传入Request对象,可以获取调用编号并建立映射关系。线程池中的线程根据Response对象中的调用编号找到对应的Future对象,将响应结果设置到Future对象中,供用户线程获取。
为了检测Client端与Server端的连通性,Dubbo采用双向心跳机制。HeaderExchangeClient初始化时,开启两个定时任务:发送心跳请求和处理重连与断连。心跳检测定时任务HeartbeatTimerTask确保连接空闲时向对端发送心跳包,而ReconnectTimerTask则负责检测连接状态,当判定为超时后,客户端选择重连,服务端采取断开连接的措施。