Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 796 lines (689 sloc) 21.351 kb
6f0f4da @yinhm presentations of redis
authored
1 <!DOCTYPE html>
2 <!--
3 Copyright 2010 Google Inc.
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 Original slides: Marcin Wichary (mwichary@google.com)
18 Modifications: Ernest Delgado (ernestd@google.com)
19 Alex Russell (slightlyoff@chromium.org)
20 -->
21 <html manifest="/html5/src/slides_manifest.php">
22 <head>
23 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
24 <meta http-equiv="X-UA-Compatible" content="chrome=1">
25
26 <title>HTML5 presentation</title>
27
28 <style>
29 .notes { display: none; }
30 .stroke {
31 -webkit-text-stroke-color: red;
32 -webkit-text-stroke-width: 1px;
33 -moz-text-stroke-color: red;
34 -moz-text-stroke-width: 1px;
35 }
36
37 body {
38 font: 14px "Lucida Grande", "Trebuchet MS", Verdana, sans-serif;
39 background: #778;
40 padding: 0;
41 margin: 0;
42 overflow: hidden;
43 }
44
45 div.presentation {
46 position: absolute;
47 width: 100%;
48 display: table-cell;
49 vertical-align: middle;
50 height: 100%;
51 background: inherit;
52 }
53
54 div.slides {
55 width: 100%;
56 height: 100%;
57 overflow: hidden;
58 left: 0;
59 top: 0;
60 position: absolute;
61 display: block;
62 -webkit-transition: -webkit-transform 1s ease-in-out;
63 -moz-transition: -moz-transform 1s ease-in-out;
64 }
65
66 div.slide {
67 display: none;
68 position: absolute;
69 overflow: hidden;
70 width: 900px;
71 height: 700px;
72 left: 50%;
73 top: 50%;
74 margin-top: -350px;
75 background: -webkit-gradient(linear, left bottom, left top, from(#bbd), to(#fff));
76 -webkit-transition: margin 0.25s ease-in-out;
77 background-color: #eee;
78 background: -moz-linear-gradient(left bottom, #bbd, #fff);
79 -moz-transition: margin 0.25s ease-in-out;
80 }
81
82 div.slide:nth-child(even) {
83 border-top-left-radius: 20px;
84 -moz-border-radius-topleft: 20px;
85 border-bottom-right-radius: 20px;
86 -moz-border-radius-bottomright: 20px;
87 }
88
89 div.slide:nth-child(odd) {
90 border-top-right-radius: 20px;
91 -moz-border-radius-topright: 20px;
92 border-bottom-left-radius: 20px;
93 -moz-border-radius-bottomleft: 20px;
94 }
95
96 div.slide p {
97 font-size: 20px;
98 }
99
100 section.intro p {
101 font-size: 35px;
102 }
103
104 button {
105 font-size: 20px;
106 }
107
108 .summary {
109 font-size: 30px;
110 }
111
112 .bullets {
113 font-size: 40px;
114 }
115
116 .slide.far-past {
117 display: block;
118 margin-left: -2400px;
119 }
120
121 .slide.past {
122 display: block;
123 margin-left: -1400px;
124 }
125
126 .slide.current {
127 display: block;
128 margin-left: -450px;
129 }
130
131 .slide.future {
132 display: block;
133 margin-left: 500px;
134 }
135
136 .slide.far-future {
137 display: block;
138 margin-left: 1500px;
139 }
140
141 body.three-d div.presentation {
142 /*background: -webkit-gradient(radial, 50% 50%, 10, 50% 50%, 1000, from(#333), to(#000)); */
143 }
144
145 body.three-d div.slides {
146 -webkit-transform: translateX(50px) scale(0.8) rotateY(10deg);
147 -moz-transform: translateX(50px) scale(0.8) rotateY(10deg);
148 }
149
150
151 /* Content */
152
153 @font-face { font-family: 'Junction'; src: url(src/Junction02.otf); }
154 @font-face { font-family: 'LeagueGothic'; src: url(src/LeagueGothic.otf); }
155
156 header {
157 font-family: 'Junction';
158 font-weight: normal;
159 font-size: 50px;
160 letter-spacing: -.05em;
161 color: white;
162 color: black;
163 text-shadow: rgba(0, 0, 0, 0.2) 0 2px 5px;
164 position: absolute;
165 left: 30px;
166 top: 25px;
167 margin: 0;
168 padding: 0;
169 }
170
171 .intro h1 {
172 color: black;
173 padding: 0;
174 margin: 0;
175 letter-spacing: -2px;
176 font-size: 96px;
177 }
178
179 .intro h2 {
180 color: black;
181 font-family: 'LeagueGothic';
182 padding: 0;
183 margin: 0;
184 margin-top: -5px;
185 font-size: 68px;
186 letter-spacing: -1px;
187 }
188
189 h1 {
190 display: inline;
191 font-size: 100%;
192 font-weight: normal;
193 padding: 0;
194 margin: 0;
195 }
196
197 h2 {
198 font-family: 'Junction';
199 color: black;
200 font-size: 20px;
201 margin-left: 20px;
202 margin-top: 50px;
203 }
204
205 h2:first-child {
206 margin-top: 0;
207 }
208
209 section {
210 font-family: 'Junction';
211 font-size: 50px;
212 color: #3f3f3f;
213 text-shadow: rgba(0, 0, 0, 0.2) 0 2px 5px;
214 margin-left: 30px;
215 margin-right: 30px;
216 margin-top: 100px;
217 display: block;
218 overflow: hidden;
219 }
220
221 a {
222 color: inherit;
223 display: inline-block;
224 text-decoration: none;
225 line-height: 110%;
226 border-bottom: 2px solid #3f3f3f;
227 }
228
229 #wmap a {
230 line-height: 100%;
231 border-bottom: none;
232 }
233
234 section.left {
235 float: left;
236 width: 390px;
237 }
238
239 section.small {
240 font-size: 24px;
241 }
242
243 section.small ul {
244 margin: 0 0 0 15px;
245 padding: 0;
246 }
247
248 section.small li {
249 padding-bottom: 0;
250 }
251
252 h2 {
253 padding: 0;
254 margin: 15px 0 5px 0;
255 /* font-family: GG240;*/
256 }
257
258 section.center {
259 line-height: 180%;
260 text-align: center;
261 display: table-cell;
262 vertical-align: middle;
263 height: 700px;
264 width: 900px;
265 }
266
267 pre {
268 text-align: left;
269 font-size: 16px;
270 font-family: Monaco, Courier;
271 padding-bottom: 10px;
272
273 padding: 10px 20px;
274 background: rgba(255, 0, 0, 0.05);
275 border-radius: 8px;
276 border: 1px solid rgba(255, 0, 0, 0.2);
277 }
278 .two-column {
279 -webkit-column-count: 2;
280 -moz-column-count: 2;
281 }
282
283 pre select {
284 font-size: 16px;
285 font-family: Monaco, Courier;
286 border: 1px solid #c61800;
287 }
288
289 input {
290 font-size: 16px;
291 font-family: Helvetica;
292 padding: 3px;
293 }
294 input[type="range"] {
295 width: 100%;
296 }
297
298 button {
299 font-family: Verdana;
300 }
301
302 button.large {
303 font-size: 32px;
304 }
305
306 pre b {
307 font-weight: normal;
308 color: #c61800;
309 text-shadow: #c61800 0 0 1px;
310 /*letter-spacing: -1px;*/
311 }
312 pre em {
313 font-weight: normal;
314 font-style: normal;
315 color: #18a600;
316 text-shadow: #18a600 0 0 1px;
317 }
318 pre input[type="range"] {
319 height: 6px;
320 cursor: pointer;
321 width: auto;
322 }
323 example {
324 font-size: 16px;
325 display: block;
326 padding: 10px 20px;
327 color: black;
328 background: rgba(255, 255, 255, 0.4);
329 border-radius: 8px;
330 margin-bottom: 10px;
331 border: 1px solid rgba(0, 0, 0, 0.2);
332 }
333 video {
334 border-radius: 8px;
335 border: 1px solid rgba(0, 0, 0, 0.2);
336 }
337
338 .css,
339 .js,
340 .struct
341 .html,
342 .key {
343 font-family: 'Junction';
344 color: black;
345 display: inline-block;
346 padding: 6px 10px 3px 10px;
347 font-size: 25px;
348 line-height: 30px;
349 text-shadow: none;
350 letter-spacing: 0;
351 bottom: 10px;
352 position: relative;
353 border-radius: 10px;
354 -moz-border-radius: 10px;
355 background: white;
356 box-shadow: rgba(0, 0, 0, 0.1) 0 2px 5px;
357 -webkit-box-shadow: rgba(0, 0, 0, 0.1) 0 2px 5px;
358 -moz-box-shadow: rgba(0, 0, 0, 0.1) 0 2px 5px;
359 }
360 :not(header) > .css,
361 :not(header) > .js,
362 :not(header) > .html,
363 :not(header) > .key {
364 margin: 0 5px;
365 bottom: 4px;
366 }
367
368 .css {
369 background: -webkit-gradient(linear, left top, left bottom, from(#ff4), to(#ffa));
370 background-color: #ff4;
371 background: -moz-linear-gradient(left top, #ff4, #ffa);
372 }
373 .js {
374 background: -webkit-gradient(linear, left top, left bottom, from(#4f4), to(#afa));
375 background-color: #4f4;
376 background: -moz-linear-gradient(left top, #4f4, #afa);
377 }
378 .html {
379 background: -webkit-gradient(linear, left top, left bottom, from(#e88), to(#fee));
380 background-color: #e88;
381 background: -moz-linear-gradient(left top, #e88, #fee);
382 }
383
384 li {
385 list-style: none;
386 padding: 10px 0;
387 }
388
389 .summary li::before, .bullets li::before {
390 content: '· ';
391 }
392
393 info {
394 display: block;
395 font-size: 50%;
396 text-align: center;
397 }
398
399 </style>
400 </head><body>
401 <div class="presentation">
402 <div class="slides">
403 <div class="slide">
404 <section class="center intro">
405 <p>This presentation is an HTML5 website</p>
406 <p>Press <span class="key">&rarr;</span> key to advance.</p>
407 </section>
408 </div>
409
410 <div class="slide">
411 <section class="center intro">
412 <hgroup>
413 <h1>
414 redis
415 </h1>
416 <h2>
417 A persistent key-value database
418 </h2>
419 </hgroup>
420 <p>@yinhm https://friendfeed.com/yinhm</p>
421 </section>
422 </div>
423
424
425 <div class="slide">
426 <header>Why?</header>
427 <section>
428 <ul class="summary">
429 <li>Super fast</li>
430 <li>Persistence</li>
431 <li>High level data types</li>
432 <li>Atomic</li>
433 <li>Multiple databases support</li>
434 <li>Replication, Sharding</li>
435 <li>Client libs: Ruby, Python, PHP, Java, Scala, Node.js...</li>
436 </ul>
437 </section>
438 </div>
439
440
441 <div class="slide">
442 <header>Speed</header>
443 <section>
444 <ul class="summary">
445 <li>Written in C</li>
446 <li>All the data in memory</li>
447 <li>Pipelining, Bulk Commands</li>
448 <li>epoll</li>
449 <li><a href="http://code.google.com/p/redis/wiki/Benchmarks">Benchmarks</a></li>
450 </ul>
451
452 <h2>Benchmark Results</h2>
453 <pre>
454 about <b>110,000</b> SETs per second, about <b>81,000</b> GETs per second.
455 </pre>
456
457 <P>50 simultaneous clients performing 100,000 requests on Linux
458 2.6 Xeon X3320 2.5Ghz</P>
459 </section>
460 </div>
461
462
463 <div class="slide">
464 <header>Persistence</header>
465 <section>
466 <ul class="summary">
467 <li>All the data lives in memory</li>
468 <li>Async disk persistence</li>
469 <li>Append-only file persistence mode</li>
470 </ul>
471 </section>
472 </div>
473
474 <div class="slide">
475 <header>data types</header>
476 <section>
477 <ul class="summary">
478 <li>String</li>
479 <li>List</li>
480 <li>Set</li>
481 <li>Sorted set</li>
482 <li>Hash</li>
483 <li>Pub/Sub</li>
484 </ul>
485 </section>
486 </div>
487
488 <div class="slide">
489 <header>example</header>
490 <section>
491 <pre>
492 KEY_ONLINE = lambda {|uuid| "user:online:#{uuid}"}
493 KEY_ONLINES = lambda {|i| "onlines#{uuid}"}
494
495 # for user online indication
496 # expire in 5 minutes
497 def self.update_online(user)
498 Datastore.redis.set_with_expire(KEY_ONLINE.call(user.uuid), user.uuid, 300)
499
500 # sepreate to keys: onlines0...onlines5
501 i = Time.now.to_i / 600
502 Datastore.redis.sadd(KEY_ONLINES.call(i), user.uuid)
503 end
504
505 def self.online?(user)
506 !!Datastore.redis.get(KEY_ONLINE.call(user.uuid))
507 end
508
509 def self.onlines
510 # sepreate to keys: onlines0...onlines5
511 i = Time.now.to_i / 600
512 Datastore.redis.smembers(KEY_ONLINES.call(i))
513 end
514 </pre>
515 </section>
516 </div>
517
518
519 <div class="slide">
520 <header>example: twitter </header>
521 <section>
522 <pre>
523 def update(content)
524 Datastore.redis.lpush "user:#{id}:updates", content
525
526 follower_ids.push(id).each do |id|
527 Datastore.redis.lpush "user:#{id}:timeline", content
528 Datastore.redis.publish "user:#{id}:timeline", content
529 end
530 end
531 </pre>
532 <p><a href="http://code.google.com/p/redis/wiki/TwitterAlikeExample">Wrote
533 a simple Twitter clone with PHP + Redis</a></p>
534 </section>
535 </div>
536
537 <div class="slide">
538 <header>to redis</header>
539 <section>
540 <ul class="summary">
541 <li>write Less-SQL</li>
542 <li>superfast key-value store</li>
543 <li>data structure/State/Cache store</li>
544 <li>a better, persistent memcached</li>
545 <li>life easier</li>
546 </ul>
547 </section>
548 </div>
549
550 <div class="slide">
551 <header>or not</header>
552 <section>
553 <ul class="summary">
554 <li>Data Set must fit in Memory</li>
555 <li>Possible to loss some data</li>
556 <li>between syncs(configurable)</li>
557 </ul>
558 </section>
559 </div>
560
561 <div class="slide">
562 <header>Who using it</header>
563 <section>
564 <ul class="bullets">
565 <li>We are</li>
566 <li>Engine Yard</li>
567 <li>Github</li>
568 <li>Craigslist</li>
569 <li>Superfeedr</li>
570 </ul>
571 </section>
572 </div>
573
574 <div class="slide">
575 <header>Links</header>
576 <section>
577 <ul>
578 <li><a href="http://code.google.com/p/redis/">redis</a></li>
579 <li><a href="http://www.alohaonrails.com/sessions/#where-do-i-put-this-data">Where Do I Put This Data?</a></li>
580 <li><a href="http://www.engineyard.com/blog/2009/key-value-stores-for-ruby-part-4-to-redis-or-not-to-redis/">To Redis or Not To Redis?</a></li>
581 </ul>
582 </section>
583 </div>
584
585 <div class="slide">
586 <section class="center">
587 Questions
588 </section>
589 </div>
590 </div> <!-- slides -->
591
592 </div> <!-- presentation -->
593
594 <script>
595 (function() {
596 // Since we don't have the fallback of attachEvent and
597 // other IE only stuff we won't try to run JS for IE.
598 // It will run though when using Google Chrome Frame
599 if (document.all) { return; }
600
601 var currentSlideNo;
602 var notesOn = false;
603 var slides = document.getElementsByClassName('slide');
604 var touchStartX = 0;
605
606 // var slide_hash = window.location.hash.replace(/#/, '');
607 // if (slide_hash) {
608 // for (var i = 0, len = slides.length; i < len; i++) {
609 // if (slides[i].id == slide_hash) {
610 // currentSlideNo = i;
611 // updateSlideClasses();
612 // }
613 // }
614 // }
615
616 var spaces = /\s+/, a1 = [""];
617
618 var str2array = function(s) {
619 if (typeof s == "string" || s instanceof String) {
620 if (s.indexOf(" ") < 0) {
621 a1[0] = s;
622 return a1;
623 } else {
624 return s.split(spaces);
625 }
626 }
627 return s;
628 };
629
630 var trim = function(str) {
631 return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
632 };
633
634 var addClass = function(node, classStr) {
635 classStr = str2array(classStr);
636 var cls = " " + node.className + " ";
637 for (var i = 0, len = classStr.length, c; i < len; ++i) {
638 c = classStr[i];
639 if (c && cls.indexOf(" " + c + " ") < 0) {
640 cls += c + " ";
641 }
642 }
643 node.className = trim(cls);
644 };
645
646 var removeClass = function(node, classStr) {
647 var cls;
648 if (classStr !== undefined) {
649 classStr = str2array(classStr);
650 cls = " " + node.className + " ";
651 for (var i = 0, len = classStr.length; i < len; ++i) {
652 cls = cls.replace(" " + classStr[i] + " ", " ");
653 }
654 cls = trim(cls);
655 } else {
656 cls = "";
657 }
658 if (node.className != cls) {
659 node.className = cls;
660 }
661 };
662
663 var getSlideEl = function(slideNo) {
664 if (slideNo > 0) {
665 return slides[slideNo - 1];
666 } else {
667 return null;
668 }
669 };
670
671 var getSlideTitle = function(slideNo) {
672 var el = getSlideEl(slideNo);
673
674 if (el) {
675 return el.getElementsByTagName('header')[0].innerHTML;
676 } else {
677 return null;
678 }
679 };
680
681 var changeSlideElClass = function(slideNo, className) {
682 var el = getSlideEl(slideNo);
683
684 if (el) {
685 removeClass(el, 'far-past past current future far-future');
686 addClass(el, className);
687 }
688 };
689
690 var updateSlideClasses = function() {
691 window.location.hash = "slide" + currentSlideNo;
692 changeSlideElClass(currentSlideNo - 2, 'far-past');
693 changeSlideElClass(currentSlideNo - 1, 'past');
694 changeSlideElClass(currentSlideNo, 'current');
695 changeSlideElClass(currentSlideNo + 1, 'future');
696 changeSlideElClass(currentSlideNo + 2, 'far-future');
697 };
698
699 var nextSlide = function() {
700 if (currentSlideNo < slides.length) {
701 currentSlideNo++;
702 }
703
704 updateSlideClasses();
705 };
706
707 var prevSlide = function() {
708 if (currentSlideNo > 1) {
709 currentSlideNo--;
710 }
711 updateSlideClasses();
712 };
713
714 var showNotes = function() {
715 var notes = document.querySelectorAll('.notes');
716 for (var i = 0, len = notes.length; i < len; i++) {
717 notes[i].style.display = (notesOn) ? 'none':'block';
718 }
719 notesOn = (notesOn) ? false:true;
720 };
721
722 var switch3D = function() {
723 if (document.body.className.indexOf('three-d') == -1) {
724 document.getElementsByClassName('presentation')[0].style.webkitPerspective = '1000px';
725 document.body.className += ' three-d';
726 } else {
727 window.setTimeout("document.getElementsByClassName('presentation')[0].style.webkitPerspective = '0';", 2000);
728 document.body.className = document.body.className.replace(/three-d/, '');
729 }
730 };
731
732 var handleBodyKeyDown = function(event) {
733 // console.log(event.keyCode);
734 switch (event.keyCode) {
735 case 37: // left arrow
736 prevSlide();
737 break;
738 case 39: // right arrow
739 // case 32: // space
740 nextSlide();
741 break;
742 case 50: // 2
743 showNotes();
744 break;
745 case 51: // 3
746 switch3D();
747 break;
748 }
749 };
750
751 var addTouchListeners = function() {
752 document.addEventListener('touchstart', function(e) {
753 touchStartX = e.touches[0].pageX;
754 }, false);
755 document.addEventListener('touchend', function(e) {
756 var pixelsMoved = touchStartX - e.changedTouches[0].pageX;
757 var SWIPE_SIZE = 150;
758 if (pixelsMoved > SWIPE_SIZE) {
759 nextSlide();
760 }
761 else if (pixelsMoved < -SWIPE_SIZE) {
762 prevSlide();
763 }
764 }, false);
765 };
766
767 // initialize
768
769 (function() {
770 if (window.location.hash != "") {
771 currentSlideNo = Number(window.location.hash.replace('#slide', ''));
772 } else {
773 currentSlideNo = 1;
774 }
775
776 document.addEventListener('keydown', handleBodyKeyDown, false);
777
778 var els = slides;
779 for (var i = 0, el; el = els[i]; i++) {
780 addClass(el, 'slide far-future');
781 }
782 updateSlideClasses();
783
784 // add support for finger events (filter it by property detection?)
785 addTouchListeners();
786 })();
787 })();
788 </script>
789
790 <!--[if IE]>
791 <script src="http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js"></script>
792 <script>CFInstall.check({ mode: "overlay" });</script>
793 <![endif]-->
794 </body>
795 </html>
Something went wrong with that request. Please try again.