memcachedæ´»ç¨ã¯ãæ ¼ç´ãªãã¸ã§ã¯ãã®âç²åº¦âããã¢
æè¿ããmemcachedãæ´»ç¨ãã¦ãã¼ã¿ãã¼ã¹(RDB)ã®è² è·ãä¸ããã£ã¦è©±ãããããã ãããèããã¦ããããã©ãmemcachedã®æ´»ç¨ã¯ãæ ¼ç´ãªãã¸ã§ã¯ãã®âç²åº¦âï¼granularityï¼ããã¢ã ã¨æã£ã¦ã¾ãã
memcachedã¯ãKeyã¨Dataããã¢ã§æ ¼ç´ãã¦ãKeyãä¸ããããã¨ãé¢é£ä»ããããDataãè¿ãã ãã®ã·ã³ãã«ãªã·ã¹ãã ãPerlãPHPã®é£æ³é åã¨åãããã®memcachedãRDBã®ãã£ãã·ã¥ã¨ãã¦æ´»ç¨ãã¦ããå ´åãmemcachedã«æ ¼ç´ãããã£ãã·ã¥ãã¼ã¿ã®åä½ãâç²åº¦âãã©ãè¨è¨ããããéè¦ã«ãªã£ã¦ããã
RDBã®å ´åãæ ¼ç´ããããã¼ã¿ã¯Row(ã¬ã³ã¼ã)åä½ãããããã£ãã·ã¥ãRowåä½ã§ä½ã£ã¦ããã°ããã®ãã¨ããã°ãããã§ã¯ãã¾ããããªãã±ã¼ã¹ããããããããRDBã§ã¯å°ç¨ã®åãåããè¨èªã§ããSQLã使ã£ã¦ã
SELECT * FROM hoge WHERE ãã
ã¨ããããã«ãWHEREç¯ã®æ¡ä»¶ã«ãããããã¬ã³ã¼ããæ ¹ãããå¼ã£å¼µã£ã¦ãããã¨ãã§ããããã©ã¤ããªãã¼ä»¥å¤ã«ãæ§ã ãªãã£ã¼ã«ãå¤ã§è©²å½ãã¼ã¿ãçµãè¾¼ããã®ãRDBMSã®å¼·ã¿ãªããã§ãWebã¢ããªã±ã¼ã·ã§ã³ã§RDBã使ãå ´åããããã£ãã¯ã¨ãªãçºè¡ãããã¨ãå®ã«å¤ããããããmemcachedãåç §ã§ããã®ã¯ããã¾ã§Keyã«å¯¾å¿ããDataã ãã ãããä¸è¨ã®ããã«WHEREã§ãããããæ¡ä»¶ãæå®ãããããªã¯ã¨ãªã¯ç¸æ§ãæªããããRowåä½ã§ãã£ãã·ã¥ãmemcachedã«æ ¼ç´ãã¦ãã¾ã£ãå ´åããããã£ãã¯ã¨ãªãmemcachedã ãã§å®çµããããã¨ããã¨ãå ¨ãã£ãã·ã¥ãã¼ã¿ãã¢ããªå´ã§ãã«ã¹ãã£ã³ããå¿ è¦ãåºã¦ãã¾ãã ãããããå¹çãã¨ã¦ãæªããRDBã§ããã¼ãã«ã«ãã©ã¤ããªã¤ã³ããã¯ã¹ããå¼µããªããããªã¤ã¡ã¼ã¸ããªã
ãããã©ãããã°ããã®ããæ®éããããå ´åã§ã¯ãä¸è¨ã¯ã¨ãªã®çµæãã®ãã®ãä¸å¡ã®ãã¼ã¿ã¨ãã¦ãã£ãã·ã¥ã«æ ¼ç´ããã±ã¼ã¹ãå¤ãã¨æããä¸è¨ã¯ã¨ãªã®çµæãã¨ãã°è¤æ°ã¬ã³ã¼ãããããããã¨ããã¨ãDBé¢æ°ããå¤æ¬¡å é åãè¿ããã¦ããã ãããããããããã®ã¾ã¾ã·ãªã¢ã©ã¤ãºãã¦memcachedã«æ ¼ç´ãã¦ãããã¤ã¾ããã£ãã·ã¥ãã¼ã¿ã®ç²åº¦ã大ããããã
ãã®å ´åã®åé¡ç¹ã¯ããããã¦ä½ã£ããã£ãã·ã¥ãã¼ã¿ããã¤ç ´æ£ããªããã°ãããªãã®ããç¹å®ããã®ãé£ãããã¨ã ãâSELECT * FROM hoge WHERE ããâã®ãããªã¯ã¨ãªã¯ãã¯ã¨ãªçµæã«ã©ããªã¬ã³ã¼ããã©ãã ãå«ã¾ãã¦ããã®ããå®è¡ãã¦ã¿ãã¾ã§åãããªããã ãããã®ã¯ã¨ãªçµæããã£ãã·ã¥ããã¨ãããã¨ã¯ãèªåãã©ããªãã¼ã¿ããã£ãã·ã¥ãã¦ããã®ããããã°ã©ã èªä½ãï¼ãã®ã¾ã¾ã§ã¯ï¼ææ¡ã§ããªããã¨ã«ãªãã
ããã¦ãã®Webãµã¼ãã¹ã§ã¯ã¦ã¼ã¶ã常ã«ãã¼ã¿ãæ´æ°ã»è¿½å ãç¶ãããããå¤ããªã£ããã£ãã·ã¥ãç ´æ£ããªãã¨ããã¤ã¾ã§ãã£ã¦ãå¤ãæ
å ±ã表示ããã£ã±ãªãã«ãªã£ã¦ãã¾ããã¦ã¼ã¶ããããã¼ã¿ãæ´æ°ããã¨ãã¦ãæ´æ°åã®å¤ããã¼ã¿ãå«ããã£ãã·ã¥ã¯ã©ãã«ããã®ãããç¹å®ã§ããªããã°ããã£ãã·ã¥ãç ´æ£ãããã¨ã¯ã§ããªãããããã£ãã·ã¥ãã¼ã¿ããã¼ã¿ãã¼ã¹ã®Rowåä½ã§æ ¼ç´ããã¦ããå ´åã¯ããã®Rowã®ãã£ãã·ã¥ãç ´æ£ããã ãã§ããã®ã§ããããã£ãåé¡ã¯çããªãããããé«æ¬¡ã®ã¯ã¨ãªçµæããã£ãã·ã¥ãã¦ããå ´åãå½è©²Rowãå«ããã£ãã·ã¥ãã¼ã¿ãææ¡ãããã¨ã¯ãªããªãé£ããã
ãã®åé¡ã®æã£åãæ©ã解決çã¯ããã£ãã·ã¥ã«âæå¹æéâãè¨å®ãããã¨ã ãä¸è¨ã®ãããªã¯ã¨ãªã®æå¹æéãããã£ãã·ã¥æ ¼ç´å¾ããä¾ãã°10åã«éå®ãã¦ãããããã¨10åéã¯å¸¸ã«ãã®ãã£ãã·ã¥ã表示ããç¶ãããã¨ã«ãªãããã©ãã10åçµéå¾ã«ãã®ãã£ãã·ã¥ã¯èªåã§ç ´æ£ãããã®ã§ããã以éã®ãªã¯ã¨ã¹ãã«å¯¾ãã¦ã¯ãã¾ãæ°ãã«ãã¼ã¿ãã¼ã¹ãåç §ãã¦ãã£ãã·ã¥ãã¼ã¿ãä½ãç´ããã¨ãã§ããããããããã®ãã£ãã·ã¥ãã¼ã¿ã®å 訳ãææ¡ãããã¨ã¯é£ããã®ã§ãä¸å¾ã«æå¹æéãè¨ãã¦ãæéåãã¯æ¨ã¦ã¦ãã¾ããã¨ãããã®ã¢ã¤ãã£ã¢ããã¡ãªããã¨ãã¦ã¯ãæå¹æééã«ãã¼ã¿æ´æ°ãè¡ããã¦ãããã表示ãã¼ã¿ã«åæ ããããã¨ãã§ããªãããã£ãã«æ´æ°ãããªããã¼ã¿ã®ãã£ãã·ã¥ãä¸å¾ã«ç ´æ£ããã¦ãã¾ãã®ã§ããã£ãã·ã¥å¹çãä½ä¸ãããçããã®è¾ºã®èãæ¹ã¯äººã«ãã£ã¦åãããããããªãããªããã¼ã¿ãæ´æ°ãããã«ãããããããæå¹æéãåããã¾ã§å¤ããã¼ã¿ã表示ããç¶ããã¨ããã®ã¯ãå人çã«ã¯ã¡ãã£ã¨è¨±å®¹ã§ããªãããã©ã
ä¸è¬ã«æ¬¡ã®ãããªãã¬ã¼ããªããããã¨èãã¦ããã¨æããã¤ã¾ãã
- ããã£ãã·ã¥ãã¼ã¿ã®ç²åº¦ãã大ããããã°ããã»ã©ããã£ãã·ã¥åç §æã®å®è¡å¹çã¯é«ã¾ããããã¼ã¿æ´æ°æã®ä¾åé¢ä¿ã®è§£æ±ºãé£ãããªãã
表示ã®é
延ã許容ã§ããªãå ´åããã¼ã¿æ´æ°æã«ãã£ãã·ã¥ã«åã¶å½±é¿ãç¹å®ããã¢ã¼ããã¯ãã£ãé å¼µã£ã¦æ§ç¯ããªãããããªãããã®è¾ºã®ã¢ã¼ããã¯ãã£ã¯ããµã¼ãã¹ã®ç¨®é¡ã«å¿ãã¦æ§ã
ãªæ¹æ³ãããã¨æãã®ã§ä¸æ¦ã«ä¾ç¤ºã¯ã§ããªãã¨æãããã SNSã¨ãmicroblogçãã¡ã¸ã£ã¼ãªWebã¢ããªã±ã¼ã·ã§ã³ã«ã¤ãã¦ã¯ãä¸ã®ä¸ã«åä¾ã確ç«ããã¤ã¤ããæãããï¼åèï¼Twitterがスケールに苦しむ理由ï¼ã
Webãµã¼ãã¹ã®ã¹ã±ã¼ã©ããªãã£ã«ã¤ãã¦ã®æ å ±ãéã¾ã£ã¦ãããµã¤ã「High Scalability」ã«ãä¸çæ大ã®åçå ±æãµã¤ãFotologã«ã¤ãã¦ã®memcachedæ´»ç¨äºä¾ãç´¹ä»ããã¦ãããããã®ä¸ã§ã®memcachedæ´»ç¨ã¢ããã¤ã¹ããããªãããã«ãªãã以ä¸ä¸é¨å¼ç¨ã
A Bunch of Great Strategies for Using Memcached and MySQL Better Together
Miscellaneous
There were a few suggestions on using memcached that didn't fit in any other section, so they're gathered here for posterity:
- Have a lot of nodes to handle loss. Losing a node with a few nodes will cause a spike on the database as everything reloads. Having more servers means less database load on failure.
- Use a warm standby that takes over IP of a memcached server that fails. This means you clients will not have to update their cache lists.
- Memcached can operate with UDP and TCP. Persistence connections are better because there's less overhead. Cache designed to use 1000s of connections.
- Use separate memcached servers to reduce contention with applications.
- Check that your slab sizes match the size of the data you are allocating or you could be wasting a lot of memory.
Here are some additional strategies from Memcached and MySQL tutorial:
- Don't think row-level (database) caching, think complex objects.
- Don't run memcached on your database server, give your database all the memory it can get.
- Don't obsess about TCP latency - localhost TCP/IP is optimized down to an in-memory copy.
- Think multi-get - run things in parallel whenever you can.
- Not all memcached client libraries are made equal, do some research on yours.
- Instead of invalidating your data, expire it whenever you can - memcached will do all the work
- Generate smart keys - ex. on update, increment a version number, which will become part of the key
- For bonus points, store the version number in memcached - call it generation
- The latter will be added to Memcached soon - as soon as Brian gets around to it
(訳)
- memcachedã®ã¤ã³ã¹ã¿ã³ã¹ã¯ããããèµ°ãããã»ãããããå°æ°ã®ã¤ã³ã¹ã¿ã³ã¹ã«ä¾åãã¦ããå ´åããã®ã¤ã³ã¹ã¿ã³ã¹ã失ãããã¨ãã«åæ§ç¯ããªããã°ãããªããã£ãã·ã¥ãã¼ã¿ã大éã«çãããã¼ã¿ãã¼ã¹ãéè² è·ã«é¥ãã
- VIPã使ã£ã¦memcachedãåé·åããã»ãããããé害çºçæã«åä¸IPã§å¼ãç¶ããã£ãã·ã¥ãæä¾ã§ããã°ãé害çºçæã«ã¯ã©ã¤ã¢ã³ãï¼Webãµã¼ãï¼ã®ãã£ãã·ã¥ãµã¼ããªã¹ããæ´æ°ããå¿ è¦ãç¡ããªãã
- ã¡ã¢ãªã®æµªè²»ãé¿ãããããã¹ã©ããµã¤ãºããèªåã®ãã£ãã·ã¥ãã¼ã¿ã¨ããããã¦ãããã確èªããã»ããããã
- ãã¼ã¿ãã¼ã¹ã®rowåä½ã§ãã£ãã·ã¥ãçæãããªãããè¤éãªãªãã¸ã§ã¯ãããã£ãã·ã¥ããã»ãããããï¼ç²åº¦ã大ããããï¼
- ãã¼ã¿ãã¼ã¹ãµã¼ãä¸ã§memcachedãèµ°ããããªããã¼ã¿ãã¼ã¹ã«ã¯ã¡ã¢ãªãå¯è½ãªéãä¸ããã»ããããã
- memcachedã使ç¨ããã¨ãã¯TCPã®ã¬ã¤ãã³ã·ãå¿é ãããªãlocalhostä¸ã§ã®TCP/IPéä¿¡ã¯ãã¡ã¢ãªéã³ãã¼ãæ´»ç¨ãããã¨ã§æé©åããã¦ããã
- memcachedã¸ã®ã¢ã¯ã»ã¹ã並åå¦çã§ããå ´åã¯æ´»ç¨ããã
- memcachedã¯ã©ã¤ã¢ã³ãã©ã¤ãã©ãªã®æåã¯ã¢ãã«ãã£ã¦ç°ãªããããããã調ã¹ã¦ãããã»ããããã
- ãã£ãã·ã¥ãã¼ã¿ãç¡å¹åããã®ã§ã¯ãªããæå¹æéãè¨ãããã¨ãèããã»ããããã
- memcachedã®ãã¼ã«ã¤ãã¦ã¡ããã¨èãã¦ãããã»ãããããããã°ã©ã ã®ãã¼ã¸ã§ã³çªå·ããã¼ã«å«ããã¨ãï¼ä¸æ´åãåé¿ããããï¼ã
- ããã°ã©ã ã®ãã¼ã¸ã§ã³çªå·ã¨ããmemchachedã®ãã¼ã¿ã¨ãã¦æ ¼ç´ããã»ããããã
ããã¦ãè¨äºæå¾ã®çè èå¯ã
Final Thoughts
Fotolog has obviously put a great deal of thought and effort into creating sophisticated scaling strategies using memcached and MySQL. What I'm struck with is the enormous amount of effort that goes into syncing rows and objects back and forth between the cache and the database. Shouldn't it be easier? What role is the database playing when the application makes such constant use of the object cache? Wouldn't more memory make the disk based storage unnecessary?
Fotologã¯è©¦è¡é¯èª¤ã®æ«ã«ãmemcachedã¨MySQLãç¨ãããæ´ç·´ãããã¹ã±ã¼ã«æ¦ç¥ãçã¿åºãããå人çã«é©ããã®ã¯ãFotologã§ã¯ãã£ãã·ã¥ã¨ãã¼ã¿ãã¼ã¹éã®æ´åæ§ãä¿ã¤ããããã£ãã·ã¥ãªãã¸ã§ã¯ãã¨ãã¼ã¿ãã¼ã¹ã®ã¬ã³ã¼ããåæãããããã«ãã ãªãã¬è¦å´ãæã£ã¦ãããã¨ã ããããããããæ¹æ³ã¯ãªããã ãããï¼ãã¢ããªã±ã¼ã·ã§ã³ã§ããã»ã©ã¾ã§ã«ãã£ãã·ã¥ãå¤æ§ãããããã«ãªãã¨ããã¼ã¿ãã¼ã¹ã®å½¹å²ã¯ã©ããªããã ããããã£ã¨ãã£ã¨ã¡ã¢ãªãå¢ããã¦ããã°ããã®ãã¡ãã£ã¹ã¯ã¿ã¤ãã®ã¹ãã¬ã¼ã¸ã¯å¿ è¦ãªããªãããããªãã ãããã
é«åº¦ã«ã¹ã±ã¼ã«ãããã¨ãæ±ããããç¾ä»£ã®ãã³ã¢ã¹ãµã¤ãã§ã¯ãRDBMSã®éè¦åº¦ãä½ä¸ãã¤ã¤ãããå mixiã®ãã¿ã©ãããã¤ã³ã¿ãã¥ã¼ã§同じようなことを言っていたã