如果要考虑易用性和效率,使用rocksDB来替代普通内存的kv是有必要的
有了rocksdb,可以range查询,可以支持columnfamily,可以各种压缩
但是rocksdb本身是一个库,是跑在RocksDBStateBackend中的
所以taskmanager挂掉后,数据还是没了,
所以RocksDBStateBackend仍然需要类似HDFS这样的分布式存储来存储snapshot
kv state需要由rockdb来管理,这是和内存或file backend最大的不同
AbstractRocksDBState
/** * Base class for {@link State} implementations that store state in a RocksDB database. * * <p>State is not stored in this class but in the {@link org.rocksdb.RocksDB} instance that * the {@link RocksDBStateBackend} manages and checkpoints. * * @param <K> The type of the key. * @param <N> The type of the namespace. * @param <S> The type of {@link State}. * @param <SD> The type of {@link StateDescriptor}. */ public abstract class AbstractRocksDBState<K, N, S extends State, SD extends StateDescriptor<S, ?>> implements KvState<K, N, S, SD, RocksDBStateBackend>, State {
/** Serializer for the namespace */ private final TypeSerializer<N> namespaceSerializer; /** The current namespace, which the next value methods will refer to */ private N currentNamespace; /** Backend that holds the actual RocksDB instance where we store state */ protected RocksDBStateBackend backend; /** The column family of this particular instance of state */ protected ColumnFamilyHandle columnFamily; /** * We disable writes to the write-ahead-log here. */ private final WriteOptions writeOptions; /** * Creates a new RocksDB backed state. * * @param namespaceSerializer The serializer for the namespace. */ protected AbstractRocksDBState(ColumnFamilyHandle columnFamily, TypeSerializer<N> namespaceSerializer, RocksDBStateBackend backend) { this.namespaceSerializer = namespaceSerializer; this.backend = backend; this.columnFamily = columnFamily; writeOptions = new WriteOptions(); writeOptions.setDisableWAL(true); } @Override public KvStateSnapshot<K, N, S, SD, RocksDBStateBackend> snapshot(long checkpointId, long timestamp) throws Exception { throw new RuntimeException("Should not be called. Backups happen in RocksDBStateBackend."); } }
RocksDBValueState
/** * {@link ValueState} implementation that stores state in RocksDB. * * @param <K> The type of the key. * @param <N> The type of the namespace. * @param <V> The type of value that the state state stores. */ public class RocksDBValueState<K, N, V> extends AbstractRocksDBState<K, N, ValueState<V>, ValueStateDescriptor<V>> implements ValueState<V> { @Override public V value() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputViewStreamWrapper out = new DataOutputViewStreamWrapper(baos); try { writeKeyAndNamespace(out); byte[] key = baos.toByteArray(); byte[] valueBytes = backend.db.get(columnFamily, key); //从db读出value if (valueBytes == null) { return stateDesc.getDefaultValue(); } return valueSerializer.deserialize(new DataInputViewStreamWrapper(new ByteArrayInputStream(valueBytes))); } catch (IOException|RocksDBException e) { throw new RuntimeException("Error while retrieving data from RocksDB.", e); } } @Override public void update(V value) throws IOException { if (value == null) { clear(); return; } ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputViewStreamWrapper out = new DataOutputViewStreamWrapper(baos); try { writeKeyAndNamespace(out); byte[] key = baos.toByteArray(); baos.reset();