ãªã¢ã«ã¿ã¤ã å ±åç·¨éã®ã¢ã«ã´ãªãºã (Operational Transformation; OT) ãç解ãã試ã¿
Google Docsã®ããã«ææ¸ãè¤æ°äººã§ãªã¢ã«ã¿ã¤ã ã«å ±åç·¨éã§ããã¢ããªã±ã¼ã·ã§ã³ãããã¾ãããã®ãããªæ©è½ã¯ãå¤ããå°ãªãããOperational Transformation (OT; æä½å¤æ) ã¨ããèãæ¹ã使ã£ã¦å®ç¾ããã¦ããããã§ããèå³ããã£ãã®ã§ããã®OTã«ã¤ãã¦èª¿ã¹ã¦ã¿ã¾ããã
(追è¨: ãããã㯠OT ã§ãªã CRDT ã ã¨ãã話 â I was wrong. CRDTs are the future)
ãªãGoogle Docsã§ã¯ããããããªããããã¹ãããå ±åç·¨éã§ãã¾ãããããã§ã¯è©±ãç°¡åã«ããããã«ããã¬ã¼ã³ããã¹ãããå ±åç·¨éãããã¨ãæ³å®ãã¾ãã
ãªã¢ã«ã¿ã¤ã å ±åç·¨éã®æµã
å ±åç·¨éã·ã¹ãã ã®ç»å ´äººç©ã¯æ¬¡ã®éãã§ãï¼
- ãµã¼ã x 1ï¼åã¯ã©ã¤ã¢ã³ãããå±ãç·¨éæä½ããã¨ã«ãææ°ã®ææ¸ãä¿æãã¾ãï¼
- ã¯ã©ã¤ã¢ã³ã x Nï¼ææ¸ãç·¨éããå´ã§ãï¼
ããã¦ããªã¢ã«ã¿ã¤ã å ±åç·¨éã§ã¯ä»¥ä¸ã®ãããªå¦çãç¹°ãè¿ããã¾ãï¼
- åã¯ã©ã¤ã¢ã³ãã¯ãæå ã§ææ¸ãç·¨éããããããã®ç·¨éæä½ã®å 容ããµã¼ãã«éä¿¡ãã¾ãã
- ãµã¼ãã¯ãåã¯ã©ã¤ã¢ã³ãããéããã¦ããç·¨éæä½ããå°çããé ã«ãµã¼ãä¸ã®ææ¸ã«é©ç¨ãã¾ãï¼â»ããã§OTã使ãã¾ããå¾è¿°ï¼ã
- 次ã«ãµã¼ãã¯ãä»ã®å ¨ã¦ã®ã¯ã©ã¤ã¢ã³ãã«ç·¨éæä½ã®å 容ãéä¿¡ãã¾ãã
- åã¯ã©ã¤ã¢ã³ãã¯ããµã¼ãããéããã¦ããï¼ä»ã®ã¯ã©ã¤ã¢ã³ãã«ããï¼ç·¨éæä½ããæå ã®ææ¸ã«åæ ãã¾ãï¼â»ããã§ãOTã使ãã¾ããå¾è¿°ï¼ã
ã¡ãªã¿ã«ãã¬ã¼ã³ããã¹ãã«ããã¦ã¯ããç·¨éæä½ãã¨ããã®ã¯æååã®åãªãæ¿å ¥ã¨åé¤ã®ãã¨ã§ããä¾ãã°ã39æåç®ã«æåå “hello” ã追å ãã¨ãã74æåç®ãã8æåãåé¤ãã¨ãã£ããã®ã§ãã
ãµã¼ãã¯ãåã¯ã©ã¤ã¢ã³ãããå±ãç·¨éæä½ããå°çé ã«ãµã¼ãä¸ã®ææ¸ã«åæ ããã¦ããã¾ããããã«ãã£ã¦ãµã¼ãä¸ã®ææ¸ã¯æ¬¡ã ã¨æ´æ°ããã¦ãããææ¸ã®ãªãã¸ã§ã³çªå· (rev) 㯠0 â 1 â 2 â 3 â 4 â ⦠ã¨ç´ç·çã«é²ãã§ããã¾ãããµã¼ãã¯ãããã¯ã©ã¤ã¢ã³ãããå±ããç·¨éã®å 容ããä»ã®ã¯ã©ã¤ã¢ã³ãå ¨å¡ã«ãéä¿¡ãããã¨ã§ãçãåãææ¸ã®ç¶æ ãå ±æãã¾ãã
â¦ã¨ããã®ãåºæ¬ã§ãããç¾å®ã¯ããç°¡åã§ã¯ããã¾ããã
é 延ã«ããé£ãã
ãªã¢ã«ã¿ã¤ã å ±åç·¨éãé£ããã®ã¯ãããã¯ã¼ã¯çã«ããé 延ãããããã§ããé 延ãããããããã¹ã¦ã®ã¯ã©ã¤ã¢ã³ãã常ã«ææ°ã®ãªãã¸ã§ã³ãè¦ã¦ããã¨ã¯éãã¾ãããããã¯ã©ã¤ã¢ã³ãã¯ãå¤ããªãã¸ã§ã³ã®å 容ã«åºã¥ãã¦ç·¨éãè¡ããããããµã¼ãã«éä¿¡ããããããã¾ãããã¾ããåããªãã¸ã§ã³ã«å¯¾ãã¦è¤æ°ã®ã¯ã©ã¤ã¢ã³ããåæã«ç·¨éããã¨ãã競åãèµ·ããã§ããããå ·ä½ä¾ã¨ãã¦ã¯ä»¥ä¸ã®ãããªãã¨ãçºçãã¾ãï¼
- ã·ããªãª (1) ããµã¼ãå´ã®ææ¸ã¯ãªãã¸ã§ã³ rev:53 ãªã®ã«ãã¯ã©ã¤ã¢ã³ãBã«ã¯ã¾ã rev:51 ã¾ã§ããåæããã¦ããªãã£ãããã®ã¯ã©ã¤ã¢ã³ãBãææ¸ãç·¨éããrev:51 ã«å¯¾ããç·¨éæä½ããµã¼ãã«éã£ããããããµã¼ãå´ã¯æ¢ã« rev:53 ã§ãããã©ããã£ã¦è¾»è¤ãåãããã°ããã®ãï¼ã
- ã·ããªãª (2) ãã¯ã©ã¤ã¢ã³ãC㯠rev:74 ã«å¯¾ãã¦æååã®è¿½å ãè¡ãªã£ãããã®æä½ããµã¼ãã«éããã¨ããæä¸ã«ããµã¼ãããï¼ä»ã®ã¯ã©ã¤ã¢ã³ãã«ããç·¨éã§çããï¼rev:74â75 ã®ç·¨éæä½ãéããã¦ããããã®ã¨ããã¯ã©ã¤ã¢ã³ãCãæå 㧠rev:74 ãç·¨éãããã¨ã®ç¶æ ã¨ããµã¼ãããéããã¦ãã rev:74â75 ã®æä½ã¯ãã©ããã£ã¦è¾»è¤ãåãããã°ããã®ãï¼ã
ãã®åé¡ã解決ããææ³ãOTã§ãã
ãªãã¸ã§ã³ãåå²ãã¦ã¯ãªããªã
åæç·¨éã®ç®æ¨ã¯ãé 延ãããã¤ã¤ãçµæçã«ã¯çãåãææ¸ãå ±æãããã¨ãããã¨ã§ããã¤ã¾ããªãã¸ã§ã³ã¯åå²ãã¦ã¯ãªããããã 1ã¤ã®æ£çµ±ãªæ¬æµã ããåå¨ãã¹ãã ã¨ãããã¨ã§ãã
ãã®è¦³ç¹ã§è¦ãã¨ãå è¿°ããã·ããªãªã§ã¯ããæ¬æµã®ãªãã¸ã§ã³ããã®æåããã®çºçãã«ãã£ã¦åé¡ãçãã¦ãããã¨ãåããã¾ãã
解決æ¹æ³:ã競åãã2ã¤ã®æä½ããé ä¸åãªç´åæä½ã«å¤æããæ¹æ³ãå®ç¾©ããã
éã«ããã°ãä¸æçã«ç·¨éçµæãæåãããã¦ãããããããã«æ¬æµã®ç¶æ ã¸ã¨è»éä¿®æ£ã§ããã°ããã 1ã¤ã®æ¬æµãçã§å ±æãããã¨ãã§ãã¾ãã
ãã®ããã®è¦ä»¶ã¨ãã¦ãã¾ããå°ãªãã¨ããåå²ãçããå ´åã«ãããç´åã«ç´ããªããã°ãªãã¾ããã
(å³ã¯ã¾ã )
ãåããªãã¸ã§ã³ã«å¯¾ããï¼ã¤ã¾ã競åããï¼opAã¨opBããããopAããããã¨ã§ãopBã«ç¸å½ããop B’ ããããã«å¤æã§ããªããã°ãªããªãã®ã§ãã
ã¾ããããããã®ç«å ´ã«ãã£ã¦ opA, opB ã®çºçé åºãéãã®ã§ããopAããããã¨ã§ãopBã«ç¸å½ããopB’ ããããã¨ãopBããããã¨ã§ãopAã«ç¸å½ããopA’ ããããã¨ãåä¸ã®çµæã«ãªãã¨ããæ§è³ªãå¿ è¦ã§ãã
(å³ã¯ã¾ã )
ãã¬ã¼ã³ããã¹ãã§ã®å ·ä½ä¾ã示ãã¾ããããåããªãã¸ã§ã³ã«å¯¾ãã¦ãopA: 4æåç®ãã10æåãåé¤ããããopB: 8æåç®ã« “hello” ã追å ãããã¨ãã競åããæä½ãçããå ´åããããã¯2éãã®ç´åãªæä½ã«å¤æã§ãã¾ãï¼
- opAâopB’ã®é ã®å ´å ãopA: 4æåç®ãã10æåãåé¤ãããâ opB’: 4æåç®ã« “hello” ã追å ããã
- opBâopA’ã®é ã®å ´åãopB: 8æåç®ã« “hello” ã追å ãããâ opA’: 4æåç®ãã4æåãåé¤ãã13æåç®ãã6æåãåé¤ããã
ã¨ããç´åãªæä½ã«å¤æãããã¨ãã§ãã¾ããããããåãçµæãå¾ããã¾ãã
ããããæä½å¤æ (OT)ãã§ãããã®ãããªæä½å¤æãå®ç¾©ã§ããã°ãåå²ã®çºçãä¿®æ£ãã¦å¸¸ã«æ¬æµã®ãªãã¸ã§ã³ã ããåå¨ããããã«ã§ãã¾ãã
ãã¬ã¼ã³ããã¹ãã«ãããæä½ã¨æä½å¤æã®ä¾
ããã§ä¸æ¦ããã¬ã¼ã³ããã¹ãã«å¯¾ããæä½ãè¦ã¦ããã¾ãããããã¬ã¼ã³ããã¹ãã«å¯¾ããæä½ (operation) ã¯ã以ä¸ã®3ã¤ã®åºæ¬æä½ã®åã¨ãã¦è¨è¿°ãããã¨ãå¤ãããã§ãã
insert(s)
— æååsãæ¿å ¥ããdelete(n)
— næåãåé¤ããretain(n)
— æ¢åã®næåãç¶æãã
ä¾ãã°ã20æåã®ææ¸ã«ããã¦ãopAã4æåç®ãã10æåãåé¤ãããã¨ãopBã8æåç®ã« “hello” ã追å ãããããæä½ã¯ä»¥ä¸ã®ããã«è¨è¿°ã§ãã¾ãã
opA = [retain(4), delete(10), retain(6)]
opB = [retain(8), insert(âhelloâ), retain(12)]
ããã¦ããããæä½å¤æ transform(opA, opB) -> (opA', opB')
ããã¨ä»¥ä¸ãå¾ããã¾ãã
opB' = [retain(4), insert(âhelloâ), retain(6)]
ï¼opAâopB’ ã®é ã«é©ç¨ããå ´åã«opBã«ç¸å½ããæä½ï¼opA' = [retain(4), delete(4), retain(5), delete(6), retain(6)]
ï¼opBâopA’ ã®é ã«é©ç¨ããå ´åã«opAã«ç¸å½ããæä½ï¼
ãã¬ã¼ã³ããã¹ãã®æä½ã«ã¤ãã¦ã®æä½å¤æ transform(opA, opB) -> (opAâ, opBâ)
ã®å
·ä½çãªå®è£
ã«ã¤ãã¦ã¯ããã§ã¯å²æãã¾ããããã¬ã¼ã³ããã¹ãã«é¢ãã¦ã¯ãããã»ã©é£ããå¦çã§ã¯ããã¾ããã
ã¾ããä¸è¨ã® transform ã®ã»ãã«ã2ã¤ã®ç´åãªopãåæãã compose(op1, op2) -> op
ãå®ç¾©ãã¦ããã¾ããããã詳細ã¯çç¥ã
ãµã¼ãå´ã§ã®å¦ç
ãµã¼ãã¯ä»¥ä¸ã®ç¶æ ããã£ã¦ãã¾ãï¼
- ææ°ã®ææ¸ï¼éä¸ããåå ããã¯ã©ã¤ã¢ã³ãã«é å¸ããï¼
- ç¾å¨ã®ãªãã¸ã§ã³çªå·
- éå»ã«é©ç¨ãã¦ããopsã®å±¥æ´ï¼å ¨ã¦ã§ã¯ãªãç´è¿ã®ãã®ã ãä¿æããã°OKãä¿æããéãå¢ããã»ã©é 延ã«èããããããã«ãªãï¼ãé©ç¨æã®ãªãã¸ã§ã³çªå·ã¨ç´ä»ãã¦ä¿æãã¾ãã
ãµã¼ãã¯ãã¯ã©ã¤ã¢ã³ãããç·¨éæä½ãéããã¦ãããã³ã«ã次ã®å¦çãè¡ãã¾ããï¼ãªãã¯ã©ã¤ã¢ã³ãããéããã¦ããã¡ãã»ã¼ã¸ã«ã¯ãç·¨éæä½ã®ã»ãã«ãã¯ã©ã¤ã¢ã³ãå´ã®ãªãã¸ã§ã³çªå·ãå«ã¾ãã¦ãã¾ããï¼
- ã¯ã©ã¤ã¢ã³ãå´ã¨ãµã¼ãå´ã¨ã§ãªãã¸ã§ã³çªå·ãç°ãªãå ´åã¯ãã¯ã©ã¤ã¢ã³ãå´ããéããã¦ãã op ã«æä½å¤æãé©ç¨ãã¦ããµã¼ãä¸ã®ææ°ã®ãªãã¸ã§ã³ã«é©ç¨ã§ãã op’ ã«å¤æãã¾ããå ·ä½çã«ã¯ããµã¼ãä¸ã«ããopsã®å±¥æ´ãç¨ãã¦æä½å¤æãå¿ è¦ãªã ãç¹°ãè¿ãã¾ããä¾ãã°ã¯ã©ã¤ã¢ã³ãå´ã rev:30 ã§ãµã¼ãå´ã rev:33 ã®å ´åã¯ããµã¼ãã«è¨é²ããã¦ãã rev:31 ãã rev:33 ã¾ã§ã®3ã¤ã®opsãç¸æã«ãã¦ã opã3åtransformãã¾ããããã op’ ã¨ãã¾ãã
- ã¯ã©ã¤ã¢ã³ãå´ã¨ãµã¼ãå´ã§ãªãã¸ã§ã³çªå·ãåä¸ã®å ´åã¯ä¸è¨ã®å¤æã¯ä¸è¦ã§ãã
- ç·¨éæä½ op’ ããµã¼ãã®ææ¸ã«é©ç¨ãããªãã¸ã§ã³çªå·ãã¤ã³ã¯ãªã¡ã³ããã¾ããã¾ããop’ ããµã¼ãä¸ã®å±¥æ´ã«è¿½å ãã¾ãã
- ç·¨éæä½ãéã£ã¦ããã¯ã©ã¤ã¢ã³ãã«ACKãè¿ãã¾ãããã®ACKã«ã¯ããµã¼ãä¸ã§ç¢ºå®ãããªãã¸ã§ã³çªå·ãå«ãã¾ãã
- ãã®ä»ã®å ¨ã¯ã©ã¤ã¢ã³ãã«ç·¨éæä½ãåæ ããããããop’ ã¨ææ°ã®ãªãã¸ã§ã³çªå·ãéä¿¡ãã¾ãã
ã¯ã©ã¤ã¢ã³ãå´ã§ã®å¦ç
ã¯ã©ã¤ã¢ã³ãå´ã¯ä»¥ä¸ã®ç¶æ ããã£ã¦ãã¾ãï¼
- ç¾å¨ã®ææ¸
- ãªãã¸ã§ã³çªå·ï¼ç¾æç¹ã§ã©ã®ãªãã¸ã§ã³ã¾ã§åæãã¦ãããã表ãã¾ãï¼
- outstanding opï¼æå ã§ã®ç·¨éã«ãã£ã¦ä¸æçã«åå²ããæä½ã®ãã¡ããµã¼ãã«éä¿¡æ¸ã¿ã ãã¾ã ACKãè¿ã£ã¦ãã¦ããªããã®ï¼
- buffered opï¼æå ã§ã®ç·¨éã«ãã£ã¦ä¸æçã«åå²ããæä½ã®ãã¡ãéä¿¡å¾ æ©ä¸ã®ãã®ï¼
ã¯ã©ã¤ã¢ã³ãã§ã¯ãåã¤ãã³ãã«ããã¦ä»¥ä¸ã®å¦çãè¡ãã¾ãã
ææ¸ãç·¨éãããã¨ã
- outstanding op ããªãå ´å㯠(=ACKå¾ ã¡ä¸ã§ãªãå ´åã¯)ãç·¨éæä½ op ã outstanding op ã«ã»ãããã¤ã¤ããµã¼ãã«éä¿¡ãã¾ãã
- outstanding op ãããå ´å㯠(=ACKå¾ ã¡ä¸ã®å ´åã¯)ãbuffered op ã« op ãã»ãããã¦éä¿¡å¾ ã¡ã«ãã¾ããbuffered op ãæ¢ã«åå¨ããå ´åã¯ããã® buffered op ã« op ãåæãã¾ãã
ACKãè¿ã£ã¦ããã¨ã
- ACKã«å«ã¾ãã revisionçªå·ã§æå ã®ãªãã¸ã§ã³çªå·ãæ´æ°ãã¾ãã
- outstanding op ã空ã«ãã¾ãã
- buffered op ãããå ´åã¯ãããã outstanding op ã«ç§»ãã¤ã¤ããµã¼ãã«éä¿¡ãã¾ãã
opãåä¿¡ããã¨ã
- outstanding op ãããå ´åã¯ã
(outstanding_op, op') := transform(outstanding_op, op)
ã¨ããæ´æ°ããã¾ãã - ããã« buffered op ãããå ´åã¯ã
(buffered_op, op') := transform(buffered_op, op')
ã¨ããæ´æ°ããã¾ãã - outstanding opãbuffered opããªãå ´åã¯ãopããã®ã¾ã¾ä½¿ãã¾ãï¼ã¤ã¾ã
op' := op
ã¨ãã¾ãï¼ã - ã¯ã©ã¤ã¢ã³ãå´ã®ææ¸ã«æä½ op’ ãé©ç¨ãã¾ãã
ãããã«
å®ç¨çãªããã¹ãã¨ãã£ã¿ãä½ãå ´åã¯ä»¥ä¸ã®ãããªãããã¯ãæ¤è¨ããªããã°ãããªãæ°ããã¾ãã
- ã«ã¼ã½ã«ã®åããOTã®å¯¾è±¡ã«ãã
- operation ããã¼ã¹ã«ããUndo/Redoã®å®è£
- ãµã¼ãå´ã§ã©ã®ããã«ã¹ã±ã¼ã©ããªãã£ãå¾ãã
- HTML5 ã® contenteditable ã¨æ¥æ¬èªIMEã«ãã£ã¦çºçããããªå°çã¨ã®æ¦ã