Class AstyanaxStorageProvider
- java.lang.Object
-
- com.bazaarvoice.emodb.blob.db.astyanax.AstyanaxStorageProvider
-
- All Implemented Interfaces:
MetadataProvider,StorageProvider,com.bazaarvoice.emodb.table.db.astyanax.DataCopyDAO,com.bazaarvoice.emodb.table.db.astyanax.DataPurgeDAO
public class AstyanaxStorageProvider extends java.lang.Object implements StorageProvider, MetadataProvider, com.bazaarvoice.emodb.table.db.astyanax.DataCopyDAO, com.bazaarvoice.emodb.table.db.astyanax.DataPurgeDAO
A single row Cassandra implementation ofStorageProvider. Storing blobs in a single row means blobs can't be bigger than what a single Cassandra server can handle. This is unlikely to be a problem as long as it's not used to store large videos. It also means that reads of a single large blob can't be distributed across all servers in the ring but instead just N servers, where N is the replication factor. The storage strategy is to chunk up the blob into smallish columns where each chunk can fit easily in memory. To do this, there it uses 3 classes of columns: - A single metadata column with aStorageSummaryobject encoded as JSON. - N "presence" columns, one per chunk. These have no data, but are written at the same time as each chunk. A reader can quickly read the presence columns and verify that, if all presence columns exist, all the chunk columns must also exist and be available (unless a concurrent writer re-writes the blob before the chunks can be retrieved). - N chunk columns, sized so that each chunk can be transferred in a single thrift call without consuming too much memory. The Astyanax com.netflix.astyanax.recipes.storage.CassandraChunkedStorageProvider implementation has a few deficiencies that this avoids: - The Astyanax v1.0.1 ChunkedStorage recipe has minor bugs: it ignores its configured ConsistencyLevel, it doesn't have a way to set some ObjectMetadata attributes. - The consistency story seems weak. There's no way to test whether all chunks are available before starting to stream back the results, and as a result the algorithm relies heavily on retry to wait for replication. If the retry algorithm waits too long (seconds) it impacts the client, and if too many threads get stuck in retry loops it will DOS the BlobStore service. - If two different blobs are stored using the same IDs, we may end up with orphaned chunks that never get cleaned up. We'd have to write a M/R job that looks for them. - If a blob is overwritten with new data, there is a period of time when readers could see mixed results where part of the returned data is from the old blob and part is from the new blob. On the other hand, the Astyanax recipes com.netflix.astyanax.recipes.storage.ObjectReader and com.netflix.astyanax.recipes.storage.ObjectWriter are much more aggressive about retries and concurrency, so they likely have better performance than this does.
-
-
Constructor Summary
Constructors Constructor Description AstyanaxStorageProvider(com.netflix.astyanax.model.ConsistencyLevel readConsistency, com.codahale.metrics.MetricRegistry metricRegistry)
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description voidcopy(com.bazaarvoice.emodb.table.db.astyanax.AstyanaxStorage source, com.bazaarvoice.emodb.table.db.astyanax.AstyanaxStorage dest, java.lang.Runnable progress)longcountMetadata(com.bazaarvoice.emodb.table.db.Table tbl)Count metadata.voiddeleteMetadata(com.bazaarvoice.emodb.table.db.Table tbl, java.lang.String blobId)Delete metadata.voiddeleteObject(com.bazaarvoice.emodb.table.db.Table tbl, java.lang.String blobId)longgetCurrentTimestamp(com.bazaarvoice.emodb.table.db.Table tbl)intgetDefaultChunkSize()voidpurge(com.bazaarvoice.emodb.table.db.astyanax.AstyanaxStorage storage, java.lang.Runnable progress)java.nio.ByteBufferreadChunk(com.bazaarvoice.emodb.table.db.Table tbl, java.lang.String blobId, int chunkId, long timestamp)StorageSummaryreadMetadata(com.bazaarvoice.emodb.table.db.Table tbl, java.lang.String blobId)Read metadata storage summary.java.util.Iterator<java.util.Map.Entry<java.lang.String,StorageSummary>>scanMetadata(com.bazaarvoice.emodb.table.db.Table tbl, java.lang.String fromBlobIdExclusive, com.bazaarvoice.emodb.common.api.impl.LimitCounter limit)Scan metadata iterator.voidwriteChunk(com.bazaarvoice.emodb.table.db.Table tbl, java.lang.String blobId, int chunkId, java.nio.ByteBuffer data, long timestamp)voidwriteMetadata(com.bazaarvoice.emodb.table.db.Table tbl, java.lang.String blobId, StorageSummary summary)Write metadata.
-
-
-
Method Detail
-
getCurrentTimestamp
public long getCurrentTimestamp(com.bazaarvoice.emodb.table.db.Table tbl)
- Specified by:
getCurrentTimestampin interfaceStorageProvider
-
writeChunk
public void writeChunk(com.bazaarvoice.emodb.table.db.Table tbl, java.lang.String blobId, int chunkId, java.nio.ByteBuffer data, long timestamp)- Specified by:
writeChunkin interfaceStorageProvider
-
readChunk
public java.nio.ByteBuffer readChunk(com.bazaarvoice.emodb.table.db.Table tbl, java.lang.String blobId, int chunkId, long timestamp)- Specified by:
readChunkin interfaceStorageProvider
-
deleteObject
public void deleteObject(com.bazaarvoice.emodb.table.db.Table tbl, java.lang.String blobId)- Specified by:
deleteObjectin interfaceStorageProvider
-
writeMetadata
public void writeMetadata(com.bazaarvoice.emodb.table.db.Table tbl, java.lang.String blobId, StorageSummary summary)Description copied from interface:MetadataProviderWrite metadata.- Specified by:
writeMetadatain interfaceMetadataProvider- Parameters:
tbl- the tableblobId- the blob idsummary- the summary
-
readMetadata
public StorageSummary readMetadata(com.bazaarvoice.emodb.table.db.Table tbl, java.lang.String blobId)
Description copied from interface:MetadataProviderRead metadata storage summary.- Specified by:
readMetadatain interfaceMetadataProvider- Parameters:
tbl- the tableblobId- the blob id- Returns:
- the storage summary
-
deleteMetadata
public void deleteMetadata(com.bazaarvoice.emodb.table.db.Table tbl, java.lang.String blobId)Description copied from interface:MetadataProviderDelete metadata.- Specified by:
deleteMetadatain interfaceMetadataProvider- Parameters:
tbl- the tableblobId- the blob id
-
countMetadata
public long countMetadata(com.bazaarvoice.emodb.table.db.Table tbl)
Description copied from interface:MetadataProviderCount metadata.- Specified by:
countMetadatain interfaceMetadataProvider- Parameters:
tbl- the table
-
scanMetadata
public java.util.Iterator<java.util.Map.Entry<java.lang.String,StorageSummary>> scanMetadata(com.bazaarvoice.emodb.table.db.Table tbl, @Nullable java.lang.String fromBlobIdExclusive, com.bazaarvoice.emodb.common.api.impl.LimitCounter limit)
Description copied from interface:MetadataProviderScan metadata iterator.- Specified by:
scanMetadatain interfaceMetadataProvider- Parameters:
tbl- the tablefromBlobIdExclusive- the from blob id exclusivelimit- the limit- Returns:
- the iterator
-
copy
public void copy(com.bazaarvoice.emodb.table.db.astyanax.AstyanaxStorage source, com.bazaarvoice.emodb.table.db.astyanax.AstyanaxStorage dest, java.lang.Runnable progress)- Specified by:
copyin interfacecom.bazaarvoice.emodb.table.db.astyanax.DataCopyDAO
-
purge
public void purge(com.bazaarvoice.emodb.table.db.astyanax.AstyanaxStorage storage, java.lang.Runnable progress)- Specified by:
purgein interfacecom.bazaarvoice.emodb.table.db.astyanax.DataPurgeDAO
-
getDefaultChunkSize
public int getDefaultChunkSize()
- Specified by:
getDefaultChunkSizein interfaceStorageProvider
-
-