0
<ul>Building Java Applications  with  Apache Cassandra </ul><ul>Nate McCall [email_address] @zznate </ul>
<ul>What is Apache Cassandra? </ul>
CAP Theorem  C onsistency A vailability  P artition Tolerance “ Thou shalt have but 2”  - Conjecture made by Eric Brewer i...
<ul>Apache Cassandra Concepts </ul>- Explicit choice of partition tolerance and availability. Consistency is tunable. - No...
Generally complements another system(s)  (Not intended to be one-size-fits-all) *** You should always use the right tool f...
How does this differ from an RDBMS?
How does this differ from an RDBMS? Substantially.
vs. RDBMS - No Joins  Unless:  - you do them on the client  - you do them via Map/Reduce
vs. RDBMS - Schema Optional  (Though you can add meta information for validation and type checking)  *** Supports secondar...
vs. RDBMS - Prematerialized and Transaction-less - No ACID transactions  - Limited support for ad-hoc queries
vs. RDBMS - Prematerialized and Transaction-less - No ACID transactions  - Limited support for ad-hoc queries *** You are ...
<ul>vs. RDBMS - Facilitates Consolidation </ul>It can be your caching layer * Off-heap cache (provided you install JNA) It...
vs. RDBMS - Shared-Nothing Architecture Every node plays the same role: no masters, no slaves, no special nodes *** No sin...
<ul>vs. RDBMS - Real Linear Scalability </ul>Want 2x performance? Add 2x nodes. *** 'No downtime' included!
<ul>vs. RDBMS - Performance </ul>Reads on par with writes
<ul>Storage (Briefly)  </ul>
<ul>Storage (Briefly)  </ul><ul>Understanding the on-disk format is extremely helpful in designing your data model correct...
<ul>Storage - SSTable </ul><ul>- SSTables are immutable (“Merge on read”) <li>- Newest timestamp wins </li></ul>
<ul>Storage – Compaction </ul><ul>Merge SSTables – keeping count down making Merge on Read more efficient <li>Discards Tom...
<ul>Data Model </ul>
<ul>Data Model </ul><ul>&quot;...sparse, persistent, distributed, multi-dimensional sorted map.&quot; <li>(The “Bigtable” ...
<ul>Data Model </ul><ul>Keyspace <li>- Collection of Column Families
- Controls replication
Column Family
- Similar to a table
- Columns ordered by name </li></ul>
<ul>Data Model – Column Family </ul><ul>Static Column Family <li>- Model my object data
Dynamic Column Family
- Pre-calculated query results
Nothing stopping you from mixing them! </li></ul>
<ul>Data Model – Static CF </ul><ul>GOOG </ul><ul>AAPL </ul><ul>NFLX </ul><ul>NOK </ul><ul><li>price: 589.55 </li></ul><ul...
<ul>Data Model – Prematerialized Query </ul><ul>StockHist </ul><ul>10/25/2011: 6.71 </ul><ul>GOOG </ul><ul>AAPL </ul><ul>N...
<ul>API Operations  </ul>
Five general categories <ul>Retrieving Writing/Updating/Removing (all the same op!) <ul>Increment counters </ul>Meta Infor...
Using a Client Hector Client: http://hector-client.org - Most popular Java client  - In use at very large installations - ...
<ul>Sample Project for Experimenting </ul>https://github.com/zznate/cassandra-tutorial https://github.com/zznate/hector-ex...
<ul>ColumnFamilyTemplate </ul>Familiar, type-safe approach - based on template-method design pattern - generic: ColumnFami...
<ul>ColumnFamilyTemplate </ul>new ThriftColumnFamilyTemplate(keyspaceName,  columnFamilyName,  StringSerializer.get(),  St...
<ul>ColumnFamilyTemplate </ul>ColumnFamilyResult<String, String> res = cft.queryColumns(&quot;zznate&quot;); String value ...
<ul>ColumnFamilyTemplate </ul>ColumnFamilyResult wrapper =  template.queryColumns(&quot;GOOG&quot;, &quot;AAPL&quot;, &quo...
<ul>ColumnFamilyTemplate </ul>ColumnFamilyUpdater updater = template.createUpdater(&quot;AAPL&quot;);  updater.setString(&...
<ul>ColumnFamilyTemplate </ul>template.deleteColumn(&quot;AAPL&quot;, &quot;notNeededStuff&quot;); template.deleteColumn(&...
<ul>Deletion </ul>
<ul>Deletion </ul><ul><li>Again: Every mutation is an insert!
- Merge on read
- Sstables are immutable
- Highest timestamp wins </li></ul>
<ul>Deletion – As Seen by CLI </ul><ul>[default@Tutorial] list StateCity; <li>Using default limit of 100
-------------------
RowKey: CA Burlingame
=> (column=650, value=33372e3537783132322e3334, timestamp=1310340410528000)
-------------------
RowKey: TX Austin
=> (column=202, value=33302e3237783039372e3734, timestamp=1310143852392000)
=> (column=203, value=33302e3237783039372e3734, timestamp=1310143852444000)
=> (column=204, value=33302e3332783039372e3733, timestamp=1310143852448000)
=> (column=205, value=33302e3332783039372e3733, timestamp=1310143852453000)
=> (column=206, value=33302e3332783039372e3733, timestamp=1310143852457000) </li></ul>
<ul>Deletion – As Seen by CLI </ul><ul>[default@Tutorial] list StateCity; <li>Using default limit of 100
Upcoming SlideShare
Loading in...5
×

Meetup cassandra for_java_cql

2,193

Published on

Slides from 10/26/2011 Cassandra Austin Meetup group

Published in: Technology, Education
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,193
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
103
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Transcript of "Meetup cassandra for_java_cql"

  1. 1. <ul>Building Java Applications with Apache Cassandra </ul><ul>Nate McCall [email_address] @zznate </ul>
  2. 2. <ul>What is Apache Cassandra? </ul>
  3. 3. CAP Theorem C onsistency A vailability P artition Tolerance “ Thou shalt have but 2” - Conjecture made by Eric Brewer in 2000 - Published as formal proof in 2002 - See: http://en.wikipedia.org/wiki/CAP_theorem for more
  4. 4. <ul>Apache Cassandra Concepts </ul>- Explicit choice of partition tolerance and availability. Consistency is tunable. - No read before write - Merge on read - Idempotent - Schema Optional - All nodes share the same role - Still performs well with larger-than-memory data sets
  5. 5. Generally complements another system(s) (Not intended to be one-size-fits-all) *** You should always use the right tool for the right job anyway
  6. 6. How does this differ from an RDBMS?
  7. 7. How does this differ from an RDBMS? Substantially.
  8. 8. vs. RDBMS - No Joins Unless: - you do them on the client - you do them via Map/Reduce
  9. 9. vs. RDBMS - Schema Optional (Though you can add meta information for validation and type checking) *** Supports secondary indexes too: “ … WHERE state = 'TX' ”
  10. 10. vs. RDBMS - Prematerialized and Transaction-less - No ACID transactions - Limited support for ad-hoc queries
  11. 11. vs. RDBMS - Prematerialized and Transaction-less - No ACID transactions - Limited support for ad-hoc queries *** You are going to give up both of these anyway when you shard an RDBMS ***
  12. 12. <ul>vs. RDBMS - Facilitates Consolidation </ul>It can be your caching layer * Off-heap cache (provided you install JNA) It can be your analytics infrastructure * true map/reduce * pig driver * hive driver coming soon
  13. 13. vs. RDBMS - Shared-Nothing Architecture Every node plays the same role: no masters, no slaves, no special nodes *** No single point of failure
  14. 14. <ul>vs. RDBMS - Real Linear Scalability </ul>Want 2x performance? Add 2x nodes. *** 'No downtime' included!
  15. 15. <ul>vs. RDBMS - Performance </ul>Reads on par with writes
  16. 16. <ul>Storage (Briefly) </ul>
  17. 17. <ul>Storage (Briefly) </ul><ul>Understanding the on-disk format is extremely helpful in designing your data model correctly </ul>
  18. 18. <ul>Storage - SSTable </ul><ul>- SSTables are immutable (“Merge on read”) <li>- Newest timestamp wins </li></ul>
  19. 19. <ul>Storage – Compaction </ul><ul>Merge SSTables – keeping count down making Merge on Read more efficient <li>Discards Tombstones (more on this later!) </li></ul>
  20. 20. <ul>Data Model </ul>
  21. 21. <ul>Data Model </ul><ul>&quot;...sparse, persistent, distributed, multi-dimensional sorted map.&quot; <li>(The “Bigtable” paper) </li></ul>
  22. 22. <ul>Data Model </ul><ul>Keyspace <li>- Collection of Column Families
  23. 23. - Controls replication
  24. 24. Column Family
  25. 25. - Similar to a table
  26. 26. - Columns ordered by name </li></ul>
  27. 27. <ul>Data Model – Column Family </ul><ul>Static Column Family <li>- Model my object data
  28. 28. Dynamic Column Family
  29. 29. - Pre-calculated query results
  30. 30. Nothing stopping you from mixing them! </li></ul>
  31. 31. <ul>Data Model – Static CF </ul><ul>GOOG </ul><ul>AAPL </ul><ul>NFLX </ul><ul>NOK </ul><ul><li>price: 589.55 </li></ul><ul><li>price: 401.76 </li></ul><ul>price: 78.73 </ul><ul>name : Google </ul><ul>name : Apple </ul><ul>name : Netflix </ul><ul>price: 6.90 </ul><ul>name : Nokia </ul><ul>exchange : NYSE </ul><ul>Stocks </ul>
  32. 32. <ul>Data Model – Prematerialized Query </ul><ul>StockHist </ul><ul>10/25/2011: 6.71 </ul><ul>GOOG </ul><ul>AAPL </ul><ul>NFLX </ul><ul>NOK </ul><ul>10/24/2011: 6.76 </ul><ul>10/21/2011: 6.61 </ul><ul>10/25/2011: 77.37 </ul><ul>10/24/2011: 118.84 </ul><ul>10/21/2011: 117.04 </ul><ul>10/25/2011: 397.77 </ul><ul>10/24/2011: 405.77 </ul><ul>10/21/2011: 392.87 </ul><ul>10/25/2011: 583.16 </ul><ul>10/24/2011: 596.42 </ul><ul>10/21/2011: 590.49 </ul>
  33. 33. <ul>API Operations </ul>
  34. 34. Five general categories <ul>Retrieving Writing/Updating/Removing (all the same op!) <ul>Increment counters </ul>Meta Information Schema Manipulation CQL Execution </ul>
  35. 35. Using a Client Hector Client: http://hector-client.org - Most popular Java client - In use at very large installations - A number of tools and utilities built on top - Very active community - MIT Licensed *** like any open source project fully dependent on another open source project it has its worts
  36. 36. <ul>Sample Project for Experimenting </ul>https://github.com/zznate/cassandra-tutorial https://github.com/zznate/hector-examples Built using Hector Really basic – designed to be beginner level w/ very few moving parts Modify/abuse/alter as needed *** Descriptions of what is going on and how to run each example are in the Javadoc comments. 
  37. 37. <ul>ColumnFamilyTemplate </ul>Familiar, type-safe approach - based on template-method design pattern - generic: ColumnFamilyTemplate<K,N> (K is the key type, N the column name type) ColumnFamilyTemplate template = new ThriftColumnFamilyTemplate(keyspaceName, columnFamilyName, StringSerializer.get(), StringSerializer.get()); *** (no generics for clarity)
  38. 38. <ul>ColumnFamilyTemplate </ul>new ThriftColumnFamilyTemplate(keyspaceName, columnFamilyName, StringSerializer.get(), StringSerializer.get()); Key Format Column Name Format - Cassandra calls this a “comparator” - Remember: defines column order in on-disk format
  39. 39. <ul>ColumnFamilyTemplate </ul>ColumnFamilyResult<String, String> res = cft.queryColumns(&quot;zznate&quot;); String value = res.getString(&quot;email&quot;); Date startDate = res.getDate(“startDate”); Key Format Column Name Format
  40. 40. <ul>ColumnFamilyTemplate </ul>ColumnFamilyResult wrapper = template.queryColumns(&quot;GOOG&quot;, &quot;AAPL&quot;, &quot;NFLX&quot;); String googName = wrapper.getString(&quot;name&quot;); wrapper.next(); String aaplName = wrapper.getString(&quot;name&quot;); wrapper.next(); String nflxName = wrapper.getString(&quot;name&quot;); Querying multiple rows and iterating over results
  41. 41. <ul>ColumnFamilyTemplate </ul>ColumnFamilyUpdater updater = template.createUpdater(&quot;AAPL&quot;); updater.setString(&quot;exchange&quot;,&quot;NASDAQ&quot;); updater.addKey(&quot;GOOG&quot;); updater.setString(&quot;exchange&quot;,&quot;NASDAQ&quot;); template.update(updater); Inserting data with ColumnFamilyUpdater
  42. 42. <ul>ColumnFamilyTemplate </ul>template.deleteColumn(&quot;AAPL&quot;, &quot;notNeededStuff&quot;); template.deleteColumn(&quot;GOOG&quot;, &quot;somethingElse&quot;); template.deleteColumn(&quot;GOOG&quot;, &quot;aDifferentColumnName&quot;); ... template.deleteRow(“NOK”); template.executeBatch(); Deleting Data with ColumnFamilyTemplate
  43. 43. <ul>Deletion </ul>
  44. 44. <ul>Deletion </ul><ul><li>Again: Every mutation is an insert!
  45. 45. - Merge on read
  46. 46. - Sstables are immutable
  47. 47. - Highest timestamp wins </li></ul>
  48. 48. <ul>Deletion – As Seen by CLI </ul><ul>[default@Tutorial] list StateCity; <li>Using default limit of 100
  49. 49. -------------------
  50. 50. RowKey: CA Burlingame
  51. 51. => (column=650, value=33372e3537783132322e3334, timestamp=1310340410528000)
  52. 52. -------------------
  53. 53. RowKey: TX Austin
  54. 54. => (column=202, value=33302e3237783039372e3734, timestamp=1310143852392000)
  55. 55. => (column=203, value=33302e3237783039372e3734, timestamp=1310143852444000)
  56. 56. => (column=204, value=33302e3332783039372e3733, timestamp=1310143852448000)
  57. 57. => (column=205, value=33302e3332783039372e3733, timestamp=1310143852453000)
  58. 58. => (column=206, value=33302e3332783039372e3733, timestamp=1310143852457000) </li></ul>
  59. 59. <ul>Deletion – As Seen by CLI </ul><ul>[default@Tutorial] list StateCity; <li>Using default limit of 100
  60. 60. -------------------
  61. 61. RowKey: CA Burlingame
  62. 62. -------------------
  63. 63. RowKey: TX Austin
  64. 64. => (column=202, value=33302e3237783039372e3734, timestamp=1310143852392000)
  65. 65. => (column=203, value=33302e3237783039372e3734, timestamp=1310143852444000)
  66. 66. => (column=204, value=33302e3332783039372e3733, timestamp=1310143852448000)
  67. 67. => (column=205, value=33302e3332783039372e3733, timestamp=1310143852453000)
  68. 68. => (column=206, value=33302e3332783039372e3733, timestamp=1310143852457000) </li></ul>
  69. 69. <ul>Deletion – FYI </ul><ul>mutator.addDeletion(&quot;202230&quot;, &quot;Npanxx&quot;, “city”, stringSerializer); </ul><ul>Does not exist? You just inserted a tombstone! </ul><ul>Sending a deletion for a non-existing row: </ul><ul>[default@Tutorial] list Npanxx; <li>Using default limit of 100
  70. 70. . . .
  71. 71. -------------------
  72. 72. RowKey: 202230
  73. 73. -------------------
  74. 74. . . . </li></ul>
  75. 75. <ul>Integrating with existing patterns </ul><ul><li><bean id=&quot;cassandraHostConfigurator&quot;
  76. 76. class=&quot;me.prettyprint.cassandra.service.CassandraHostConfigurator&quot;>
  77. 77. <constructor-arg value=&quot;localhost:9170&quot;/>
  78. 78. </bean>
  79. 79. <bean id=&quot;cluster&quot; class=&quot;me.prettyprint.cassandra.service.ThriftCluster&quot;>
  80. 80. <constructor-arg value=&quot;TestCluster&quot;/>
  81. 81. <constructor-arg ref=&quot;cassandraHostConfigurator&quot;/>
  82. 82. </bean>
  83. 83. <bean id=&quot;consistencyLevelPolicy&quot; class=&quot;me.prettyprint.cassandra.model.ConfigurableConsistencyLevel&quot;>
  84. 84. <property name=&quot;defaultReadConsistencyLevel&quot; value=&quot;ONE&quot;/>
  85. 85. </bean>
  86. 86. <bean id=&quot;keyspaceOperator&quot; class=&quot;me.prettyprint.hector.api.factory.HFactory&quot;
  87. 87. factory-method=&quot;createKeyspace&quot;>
  88. 88. <constructor-arg value=&quot;Keyspace1&quot;/>
  89. 89. <constructor-arg ref=&quot;cluster&quot;/>
  90. 90. <constructor-arg ref=&quot;consistencyLevelPolicy&quot;/>
  91. 91. </bean>
  92. 92. <bean id=&quot;simpleCassandraDao&quot; class=&quot;me.prettyprint.cassandra.dao.SimpleCassandraDao&quot;>
  93. 93. <property name=&quot;keyspace&quot; ref=&quot;keyspaceOperator&quot;/>
  94. 94. <property name=&quot;columnFamilyName&quot; value=&quot;Standard1&quot;/>
  95. 95. </bean> </li></ul>
  96. 96. <ul>Integrating with existing patterns </ul><ul><li>Hector Object Mapper:
  97. 97. https://github.com/rantav/hector/wiki/Hector-Object-Mapper-%28HOM%29
  98. 98. Hector JPA:
  99. 99. https://github.com/riptano/hector-jpa </li></ul>
  100. 100. <ul>CQL via JDBC </ul>
  101. 101. <ul>CQL via JDBC </ul><ul><li>- Integrate with existing tools (Spring Framework's JdbcTemplate in this case)
  102. 102. *** Still some caveats and missing features </li></ul>
  103. 103. <ul>CQL via JDBC </ul><ul><li>https://github.com/riptano/jdbc-conn-pool
  104. 104. - see portfolio_example sub project </li></ul>
  105. 105. <ul>CQL via JDBC: Components </ul><ul><li>- HCQLDataSource (from jdbc-pool)
  106. 106. - Spring Framework's JdbcTemplate
  107. 107. - DAO class with associated domain objects
  108. 108. - Junit
  109. 109. - Spring Framework's SpringJUnit4ClassRunner (context setup and injection)
  110. 110. - EmbededServerHelper from hector-test (manage Cassandra lifecycle, directories and configuration) </li></ul>
  111. 111. <ul>CQL via JDBC: Configuration </ul><ul><li>Pool Configuration
  112. 112. - Cluster name, keyspace and at least 1 host required
  113. 113. - Additional settings for:
  114. 114. * fail over semantics
  115. 115. * automatic host discovery
  116. 116. * timeout counters and thresholds </li></ul>
  117. 117. <ul>CQL via JDBC: Configuration (JNDI) </ul><ul><li><Resource name= &quot;cassandra/CassandraClientFactory&quot;
  118. 118. auth= &quot;Container&quot;
  119. 119. type= &quot;me.prettyprint.cassandra.api.Keyspace&quot;
  120. 120. factory= &quot;me.prettyprint.cassandra.jndi.CassandraClientJndiResourceFactory&quot;
  121. 121. hosts= &quot;cass1:9160,cass2:9160,cass3:9160&quot;
  122. 122. user= &quot;user&quot;
  123. 123. password= &quot;passwd&quot;
  124. 124. keyspace=&quot; Keyspace1&quot;
  125. 125. clusterName= &quot;Test Cluster&quot;
  126. 126. maxActive= &quot;20&quot;
  127. 127. maxWaitTimeWhenExhausted= &quot;10&quot;
  128. 128. failoverPolicy= &quot;ON_FAIL_TRY_ALL_AVAILABLE&quot;
  129. 129. autoDiscoverHosts= &quot;true&quot;
  130. 130. runAutoDiscoveryAtStartup= &quot;true&quot; /> </li></ul>
  131. 131. <ul>CQL via JDBC: Configuration (Spring) </ul><ul><li><bean class= &quot;com.datastax.drivers.jdbc.pool.cassandra.jdbc.HCQLDataSource&quot;
  132. 132. id= &quot;ds&quot; >
  133. 133. <property name= &quot;clusterName&quot; value= &quot;TestCluster&quot; />
  134. 134. <property name= &quot;keyspaceName&quot; value= &quot;PortfolioDemo&quot; />
  135. 135. <property name= &quot;hosts&quot; value= &quot;127.0.0.1:9170&quot; />
  136. 136. </bean>
  137. 137. <bean class= &quot;org.springframework.jdbc.core.JdbcTemplate&quot;
  138. 138. id=&quot; jdbcTemplate&quot; >
  139. 139. <constructor-arg ref= &quot;ds&quot; />
  140. 140. </bean> </li></ul>
  141. 141. <ul>CQL via JDBC: Components </ul><ul><li>private static final String PORTFOLIOS_INSERT =
  142. 142. &quot;BEGIN BATCH &quot;
  143. 143. + &quot;INSERT INTO Portfolios (KEY, BLU, CJS, DAL) VALUES (168,'19', '7', '38') &quot;
  144. 144. + &quot;INSERT INTO Portfolios (KEY, BSX, CHK, DNB, MCI, SR) VALUES (236,'32', '27', '7','8','3') &quot;
  145. 145. + &quot;APPLY BATCH&quot; ;
  146. 146. ...
  147. 147. jdbcTemplate.execute(PORTFOLIOS_INSERT); </li></ul>Inserting Test Data
  148. 148. <ul>CQL via JDBC: Components </ul><ul><li>public Stock mapRow(ResultSet rs, int row) throws SQLException {
  149. 149. CassandraResultSet crs = (CassandraResultSet)rs;
  150. 150. Stock stock = new Stock();
  151. 151. stock.setTicker(new String(crs.getKey()));
  152. 152. stock.setPrice(crs.getDouble(&quot;price&quot;));
  153. 153. return stock;
  154. 154. }
  155. 155. See PortfolioDao#loadStocks </li></ul>Reading Data via RowMapper
  156. 156. <ul>Development Resources </ul>CQL Documentation (and CQL Shell) http://www.datastax.com/docs/1.0/dml/using_cql Hector Documentation http://hector-client.org <ul><li>Cassandra Maven Plugin (exec-cql goal) http://mojo.codehaus.org/cassandra-maven-plugin/
  157. 157. CCM localhost cassandra cluster https://github.com/pcmanus/ccm
  158. 158. OpsCenter http://www.datastax.com/products/opscenter </li></ul><ul>Cassandra AMIs https://github.com/riptano/CassandraClusterAMI </ul>
  159. 159. <ul>Putting it Together </ul>
  160. 160. <ul>Take control of consistency </ul><ul><li>If you do need a high degree of consistency, use thresholds to trigger different behavior
  161. 161. - Bank account:
  162. 162. “ on values over $10,000, wait to here from all replicas”
  163. 163. - Distributed Shopping Cart:
  164. 164. Show a confirmation page to verify order resolution
  165. 165. *** What is your appetite for risk? </li></ul>
  166. 166. Uniquely identify operations in the application <ul><li>Facilitates idempotent behavior and out-of-order execution </li></ul>
  167. 167. <ul>Denormalization </ul><ul><li>The point of normalization is to avoid update anomalies
  168. 168. ***But In an append-only system, we don't do updates </li></ul>
  169. 169. <ul>Summary </ul><ul><li>- Take advantage of strengths
  170. 170. - Look for idempotence and asynchronicity in your business processes
  171. 171. - If it's not in the API, you are probably doing it wrong
  172. 172. - Seek death is still possible if you model incorrectly </li></ul>
  173. 173. <ul>Questions </ul><ul>Nate McCall [email_address] @zznate </ul>
  174. 174. <ul>Additional Resources </ul><ul><li>DataStax Documentation: http://www.datastax.com/docs/0.8/index
  175. 175. Apache Cassandra project wiki: http://wiki.apache.org/cassandra/
  176. 176. “ The Dynamo Paper”
  177. 177. http://www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf
  178. 178. P. Helland. Building on Quicksand
  179. 179. http://arxiv.org/pdf/0909.1788
  180. 180. P. Helland. Life Beyond Distributed Transactions
  181. 181. http://www.ics.uci.edu/~cs223/papers/cidr07p15.pdf
  182. 182. S. Anand. “Netflix's Transition to High-Availability Storage Systems”
  183. 183. http://media.amazonwebservices.com/Netflix_Transition_to_a_Key_v3.pdf
  184. 184. “ The Megastore Paper”
  185. 185. http://research.google.com/pubs/archive/36971.pdf </li></ul>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×