对于缓存和数据本身,维护缓存一致性共有以下几种方式:
- 先删缓存,再更新数据库数据
- 此时可能会出现更新还未完成的情况,此时
- 先更新数据库,再更新缓存
- 当更新数据库后,若缓存未更新,可能会读到旧数据
为什么是删除缓存,而不是更新缓存?
如果数据库更新了一千次,那缓存也需要更新对应的次数,但是在这个时间段内,并不会有这么多次读取该缓存,因此我们选择更新而不是缓存。等到需要访问数据时,去添加缓存。
也可以为缓存设置过期时间
客户端缓存
在客户端缓存每个device对应的partitionGroup的leader,减少集群节点内部的转发次数
...
客户端缓存相关的文档
Map<设备全路径, Endpoint>
客户端缓存不需要保证一致性,因为无法客户端缓存不需要保证一致性,因为而且每次缓存失效后都去访问client清缓存,会产生client数目次RTT,而且需要服务端维护所有连接的client信息。对于客户端缓存的不一致,是可以被容忍的,每个客户端即使缓存中保存的EndPoint是旧数据,可以通过一次RTT转发至正确的节点上,后面通过TSStatus中返回新的EndPoint对客户端缓存进行更新。
数据分区表缓存
数据分区表缓存在每个Datanode,用于缓存保存时间分片的物理节点。数据分区表缓存在查询和写入过程中都需要用到,若无缓存,则需要向ConfigNode请求对应数据分区表项。
数据结构
Map<存储组, Map<设备组, Map<时间段,
List<VSG 共识组>>>>Map<VSG 共识组, List<物理节点>>
更新方式
实时负载均衡:某节点上压力过大,需要进行设备组的迁移
构建DataPartitionrRequest向ConfigNode申请数据分区表项,通过一次rpc(confignode不需要同步)
删除存储组(缓存失效)
负载均衡(缓存失效)List<Leader>>>>
- 使用LRU缓存
- 给定配置项 DATA_PARTITION_CACHE_MEMORY,控制缓存大小
- 使用方式
- 在所有insert操作和查询操作时使用该缓存
更新方式
- 所有需要调用lookupDataRegions接口向ConfigNode获取数据分区信息的操作,在查询完成后,新增缓存项
- 所有insert操作(insertRow,insertRows,insertTablet,insertMultiTablets,insertRowsOfOneDevice)
- 所有查询语句(executeQueryStatement)
- 根据TSStatus中的EndPoint,更新缓存项
- 删除存储组:需要清所有节点上的该存储组的数据分区缓存,删除某个存储组的所有缓存
- 在DataNode删除本地数据之前,删除cache中的缓存
实时负载均衡:某节点上压力过大,需要进行设备组的迁移
- todo
- 所有需要调用lookupDataRegions接口向ConfigNode获取数据分区信息的操作,在查询完成后,新增缓存项
元数据分区表缓存
元数据分区表存在于每个Datanode中,在写入或查询时,本地元数据缓存miss时,需要向MManager请求元数据,此时需要元数据分区表定位元数据所在的MManager位置。
数据结构
Map<存储组, Map<设备组, MManager共识组>>
Map<MManager共识组, List<物理节点>>
更新方式
- 创建时间序列
迁移设备组的元数据到其他MManager共识组
构建MetaDataPartitionRequest向ConfigNode申请元数据分区表项,通过一次rpc得到对应的分区表项
删除存储组(缓存失效)
元数据负载均衡
...