chore(pd): translate CJK comments to English (#2536)

This commit is contained in:
V_Galaxy 2024-05-13 16:16:02 +08:00 committed by GitHub
parent c1e8ea5aba
commit b056c5facd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
64 changed files with 839 additions and 905 deletions

View File

@ -164,7 +164,6 @@ public abstract class AbstractClient implements Closeable {
log.error(method.getFullMethodName() + " exception, {}", e.getMessage());
if (e instanceof StatusRuntimeException) {
if (retry < stubProxy.getHostCount()) {
// 网络不通关掉之前连接换host重新连接
synchronized (this) {
stubProxy.setBlockingStub(null);
}

View File

@ -42,7 +42,7 @@ public class AbstractClientStubProxy {
public String nextHost() {
String host = hostList.poll();
hostList.offer(host); //移到尾部
hostList.offer(host);
return host;
}

View File

@ -105,13 +105,6 @@ public class ClientCache {
return null;
}
/**
* 根据key的hashcode返回分区信息
*
* @param graphName
* @param code
* @return
*/
public KVPair<Partition, Shard> getPartitionByCode(String graphName, long code) {
try {
GraphCache graph = initGraph(graphName);
@ -172,12 +165,6 @@ public class ClientCache {
}
}
/**
* 返回key所在的分区信息
*
* @param key
* @return
*/
public KVPair<Partition, Shard> getPartitionByKey(String graphName, byte[] key) {
int code = PartitionUtils.calcHashcode(key);
return getPartitionByCode(graphName, code);
@ -193,8 +180,6 @@ public class ClientCache {
RangeMap<Long, Integer> range = graph.getRange();
graph.addPartition(partId, partition);
if (p != null) {
// old [1-3) [2-3)覆盖了 [1-3) 变成[1-2) 不应该删除原先的[1-3)
// 当确认老的 start, end 都是自己的时候才可以删除老的. (即还没覆盖
if (Objects.equals(partition.getId(), range.get(partition.getStartKey())) &&
Objects.equals(partition.getId(), range.get(partition.getEndKey() - 1))) {
range.remove(range.getEntry(partition.getStartKey()).getKey());

View File

@ -45,10 +45,10 @@ public abstract class DiscoveryClient implements Closeable, Discoverable {
private final Timer timer = new Timer("serverHeartbeat", true);
private final AtomicBoolean requireResetStub = new AtomicBoolean(false);
protected int period; //心跳周期
protected int period;
LinkedList<String> pdAddresses = new LinkedList<>();
ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private volatile int currentIndex; // 当前在用pd地址位置
private volatile int currentIndex;
private int maxTime = 6;
private ManagedChannel channel = null;
private DiscoveryServiceGrpc.DiscoveryServiceBlockingStub registerStub;
@ -88,9 +88,6 @@ public abstract class DiscoveryClient implements Closeable, Discoverable {
return null;
}
/***
* 按照pd列表重置stub
*/
private void resetStub() {
String errLog = null;
for (int i = currentIndex + 1; i <= pdAddresses.size() + currentIndex; i++) {
@ -115,11 +112,6 @@ public abstract class DiscoveryClient implements Closeable, Discoverable {
}
}
/***
* 按照某个pd的地址重置channel和stub
* @param singleAddress
* @throws PDException
*/
private void resetChannel(String singleAddress) throws PDException {
readWriteLock.writeLock().lock();
@ -146,7 +138,7 @@ public abstract class DiscoveryClient implements Closeable, Discoverable {
}
/***
* 获取注册节点信息
* Obtain the registration node information
* @param query
* @return
*/
@ -167,7 +159,7 @@ public abstract class DiscoveryClient implements Closeable, Discoverable {
}
/***
* 启动心跳任务
* Start the heartbeat task
*/
@Override
public void scheduleTask() {

View File

@ -28,10 +28,10 @@ import org.apache.hugegraph.pd.grpc.discovery.RegisterType;
public class DiscoveryClientImpl extends DiscoveryClient {
private final String id;
private final RegisterType type; // 心跳类型备用
private final RegisterType type;
private final String version;
private final String appName;
private final int times; // 心跳过期次数备用
private final int times;
private final String address;
private final Map labels;
private final Consumer registerConsumer;

View File

@ -53,7 +53,7 @@ import io.grpc.stub.AbstractBlockingStub;
import lombok.extern.slf4j.Slf4j;
/**
* PD客户端实现类
* PD client implementation class
*/
@Slf4j
public class PDClient {
@ -78,7 +78,7 @@ public class PDClient {
}
/**
* 创建PDClient对象并初始化stub
* Create a PD client object and initialize the stub
*
* @param config
* @return
@ -210,7 +210,6 @@ public class PDClient {
}
private synchronized void closeStub(boolean closeWatcher) {
// TODO ManagedChannel 没有正常关闭
stubProxy.set(null);
cache.reset();
@ -308,7 +307,8 @@ public class PDClient {
}
/**
* Store注册返回storeID初次注册会返回新ID
* Store registration, the store ID will be returned, and the initial registration will
* return a new ID
*
* @param store
* @return
@ -325,7 +325,7 @@ public class PDClient {
}
/**
* 根据storeId返回Store对象
* Returns the Store object based on the store ID
*
* @param storeId
* @return
@ -348,7 +348,7 @@ public class PDClient {
}
/**
* 更新Store信息包括上下线等
* Update the store information, including online and offline
*
* @param store
* @return
@ -368,7 +368,7 @@ public class PDClient {
}
/**
* 返回活跃的Store
* Return to the active store
*
* @param graphName
* @return
@ -400,7 +400,7 @@ public class PDClient {
}
/**
* 返回活跃的Store
* Return to the active store
*
* @param graphName
* @return
@ -418,7 +418,7 @@ public class PDClient {
}
/**
* Store心跳定期调用保持在线状态
* Store heartbeat, call regularly, stay online
*
* @param stats
* @throws PDException
@ -452,7 +452,7 @@ public class PDClient {
}
/**
* 查询Key所属分区信息
* Query the partition to which the key belongs
*
* @param graphName
* @param key
@ -461,7 +461,6 @@ public class PDClient {
*/
public KVPair<Metapb.Partition, Metapb.Shard> getPartition(String graphName, byte[] key) throws
PDException {
// 先查cachecache没有命中在调用PD
KVPair<Metapb.Partition, Metapb.Shard> partShard = cache.getPartitionByKey(graphName, key);
partShard = getKvPair(graphName, key, partShard);
return partShard;
@ -477,7 +476,7 @@ public class PDClient {
}
/**
* 根据hashcode查询所属分区信息
* Query the partition information based on the hashcode
*
* @param graphName
* @param hashCode
@ -487,7 +486,6 @@ public class PDClient {
public KVPair<Metapb.Partition, Metapb.Shard> getPartitionByCode(String graphName,
long hashCode)
throws PDException {
// 先查cachecache没有命中在调用PD
KVPair<Metapb.Partition, Metapb.Shard> partShard =
cache.getPartitionByCode(graphName, hashCode);
if (partShard == null) {
@ -520,14 +518,14 @@ public class PDClient {
}
/**
* 获取Key的哈希值
* Obtain the hash value of the key
*/
public int keyToCode(String graphName, byte[] key) {
return PartitionUtils.calcHashcode(key);
}
/**
* 根据分区id返回分区信息, RPC请求
* Returns partition information based on the partition ID and RPC request
*
* @param graphName
* @param partId
@ -605,7 +603,7 @@ public class PDClient {
}
/**
* 返回startKey和endKey跨越的所有分区信息
* Returns information about all partitions spanned by the start and end keys
*
* @param graphName
* @param startKey
@ -626,8 +624,7 @@ public class PDClient {
partitions.add(startPartShard);
while (startPartShard.getKey().getEndKey() < endPartShard.getKey().getEndKey()
&& startPartShard.getKey().getEndKey() <
PartitionUtils.MAX_VALUE /*排除最后一个分区*/) {
&& startPartShard.getKey().getEndKey() < PartitionUtils.MAX_VALUE) {
startPartShard = getPartitionByCode(graphName, startPartShard.getKey().getEndKey());
partitions.add(startPartShard);
}
@ -635,7 +632,7 @@ public class PDClient {
}
/**
* 根据条件查询分区信息
* Query partition information based on conditions
*
* @return
* @throws PDException
@ -654,12 +651,6 @@ public class PDClient {
return response.getPartitionsList();
}
/**
* 查找指定store上的指定partitionId
*
* @return
* @throws PDException
*/
public List<Metapb.Partition> queryPartitions(long storeId, int partitionId) throws
PDException {
@ -765,32 +756,30 @@ public class PDClient {
}
/**
* 删除分区缓存
* Delete the partitioned cache
*/
public void invalidPartitionCache(String graphName, int partitionId) {
// 检查是否存在缓存
if (null != cache.getPartitionById(graphName, partitionId)) {
cache.removePartition(graphName, partitionId);
}
}
/**
* 删除分区缓存
* Delete the partitioned cache
*/
public void invalidPartitionCache() {
// 检查是否存在缓存
cache.removePartitions();
}
/**
* 删除分区缓存
* Delete the partitioned cache
*/
public void invalidStoreCache(long storeId) {
cache.removeStore(storeId);
}
/**
* Hugegraph server 调用Leader发生改变更新缓存
* Update the cache
*/
public void updatePartitionLeader(String graphName, int partId, long leaderStoreId) {
KVPair<Metapb.Partition, Metapb.Shard> partShard = null;
@ -817,7 +806,6 @@ public class PDClient {
if (config.isEnableCache()) {
if (shard == null) {
// 分区的shard中未找到leader说明分区发生了迁移
cache.removePartition(graphName, partId);
}
}
@ -828,7 +816,7 @@ public class PDClient {
}
/**
* Hugegraph-store调用更新缓存
* Update the cache
*
* @param partition
*/
@ -904,10 +892,7 @@ public class PDClient {
} catch (Exception e) {
log.error(method.getFullMethodName() + " exception, {}", e.getMessage());
if (e instanceof StatusRuntimeException) {
StatusRuntimeException se = (StatusRuntimeException) e;
//se.getStatus() == Status.UNAVAILABLE &&
if (retry < stubProxy.getHostCount()) {
// 网络不通关掉之前连接换host重新连接
closeStub(true);
return blockingUnaryCall(method, req, ++retry);
}
@ -938,7 +923,7 @@ public class PDClient {
}
/**
* 返回Store状态信息
* Returns the store status information
*/
public List<Metapb.Store> getStoreStatus(boolean offlineExcluded) throws PDException {
Pdpb.GetAllStoresRequest request = Pdpb.GetAllStoresRequest.newBuilder()
@ -1031,8 +1016,12 @@ public class PDClient {
}
/**
* 工作模式
* Auto自动分裂每个Store上分区数达到最大值
* Working mode
* AutoIf the number of partitions on each store reaches the maximum value, you need to
* specify the store group id. The store group id is 0, which is the default partition
* splitData(ClusterOp.OperationMode mode, int storeGroupId, List<ClusterOp.SplitDataParam>
* params)
* mode = Auto storeGroupId, params
*
* @throws PDException
*/
@ -1046,9 +1035,11 @@ public class PDClient {
}
/**
* 工作模式
* Auto自动分裂每个Store上分区数达到最大值
* Expert:专家模式需要指定splitParams
* Working mode
* AutoIf the number of partitions on each store reaches the maximum value, you need to
* specify the store group id. The store group id is 0, which is the default partition
* Expert:Expert ModeSpecifier is required splitParams, limit SplitDataParam in the same
* store group
*
* @param mode
* @param params
@ -1075,7 +1066,8 @@ public class PDClient {
}
/**
* 自动转移达到每个Store上分区数量相同
* To automatically transfer to the same number of partitions on each Store, it is
* recommended to use balancePartition(int storeGroupId) to specify the storeGroupId
*
* @throws PDException
*/
@ -1090,12 +1082,13 @@ public class PDClient {
}
/**
* //工作模式
* // Auto自动转移达到每个Store上分区数量相同
* // Expert:专家模式需要指定transferParams
* Migrate partitions in manual mode
* //Working mode
* // AutoAutomatic transfer to the same number of partitions per Store
* // Expert:Expert ModeSpecifier is required transferParams
*
* @param mode
* @param params
* @param params Designation transferParams, expert moderequest source store / target store
* in the same store group
* @throws PDException
*/
public void movePartition(Pdpb.OperationMode mode, List<Pdpb.MovePartitionParam> params) throws
@ -1128,7 +1121,7 @@ public class PDClient {
}
/**
* 平衡不同store中leader的数量
* Balance the number of leaders in different stores
*/
public void balanceLeaders() throws PDException {
Pdpb.BalanceLeadersRequest request = Pdpb.BalanceLeadersRequest.newBuilder()
@ -1139,7 +1132,7 @@ public class PDClient {
}
/**
* 从pd中删除store
* Remove the store from the PD
*/
public Metapb.Store delStore(long storeId) throws PDException {
Pdpb.DetStoreRequest request = Pdpb.DetStoreRequest.newBuilder()
@ -1152,7 +1145,7 @@ public class PDClient {
}
/**
* 对rocksdb整体进行compaction
* Compaction on rocksdb as a whole
*
* @throws PDException
*/
@ -1166,7 +1159,7 @@ public class PDClient {
}
/**
* 对rocksdb指定表进行compaction
* Compaction on rocksdb specified tables
*
* @param tableName
* @throws PDException
@ -1182,9 +1175,9 @@ public class PDClient {
}
/**
* 分区合并把当前的分区缩容至toCount个
* Merge partitions to reduce the current partition to toCount
*
* @param toCount 缩容到分区的个数
* @param toCount The number of partitions that can be scaled down
* @throws PDException
*/
public void combineCluster(int toCount) throws PDException {
@ -1198,7 +1191,9 @@ public class PDClient {
}
/**
* 将单图缩容到 toCount个
* Scaling a single image to toCount is similar to splitting to ensure that the number of
* partitions in the same store group is the same.
* If you have special requirements, you can consider migrating to other groups
*
* @param graphName graph name
* @param toCount target count
@ -1228,7 +1223,7 @@ public class PDClient {
}
/**
* 用于 store的 shard list重建
* Used for the store's shard list rebuild
*
* @param groupId shard group id
* @param shards shard listdelete when shards size is 0
@ -1316,7 +1311,7 @@ public class PDClient {
public String nextHost() {
String host = hostList.poll();
hostList.offer(host); //移到尾部
hostList.offer(host);
return host;
}

View File

@ -19,11 +19,13 @@ package org.apache.hugegraph.pd.client;
public final class PDConfig {
//TODO multi-server
// TODO: multi-server
private String serverHost = "localhost:9000";
private long grpcTimeOut = 60000; // grpc调用超时时间 10秒
// 是否接收PD异步通知
// The timeout period for grpc call is 10 seconds
private long grpcTimeOut = 60000;
// Whether to receive asynchronous PD notifications
private boolean enablePDNotify = false;
private boolean enableCache = false;
@ -59,8 +61,6 @@ public final class PDConfig {
@Deprecated
public PDConfig setEnablePDNotify(boolean enablePDNotify) {
this.enablePDNotify = enablePDNotify;
// TODO 临时代码hugegraph修改完后删除
this.enableCache = enablePDNotify;
return this;
}

View File

@ -78,7 +78,8 @@ public interface PDPulse {
Notifier<PartitionHeartbeatRequest.Builder> connectPartition(Listener<PulseResponse> listener);
/**
* 切换成新的host channel/host的检查如果需要关闭notifier调用close方法
* Switch to the new host. Do a channel/host check, and if you need to close, notifier calls
* the close method.
*
* @param host new host
* @param notifier notifier

View File

@ -35,18 +35,18 @@ import com.google.common.collect.RangeMap;
import com.google.common.collect.TreeRangeMap;
/**
* 放弃 copy on write 的方式
* 1. graph * partition 数量极多的时候效率严重下降不能用
* abandon copy on write way
* 1. When the number of graph * partitions is extremely large, the efficiency is severely
* reduced and cannot be used
*/
public class PartitionCache {
// 读写锁对象
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final Map<String, AtomicBoolean> locks = new HashMap<>();
Lock writeLock = readWriteLock.writeLock();
// 每张图一个缓存
// One cache per graph
private volatile Map<String, RangeMap<Long, Integer>> keyToPartIdCache;
// graphName + PartitionID 组成 key
// graphName + PartitionID
private volatile Map<String, Map<Integer, Metapb.Partition>> partitionCache;
private volatile Map<Integer, Metapb.ShardGroup> shardGroupCache;
private volatile Map<Long, Metapb.Store> storeCache;
@ -96,7 +96,7 @@ public class PartitionCache {
}
/**
* 根据 partitionId 返回分区信息
* Returns partition information based on partitionId
*
* @param graphName
* @param partId
@ -116,7 +116,7 @@ public class PartitionCache {
}
/**
* 返回 key 所在的分区信息
* Returns the partition information where the key is located
*
* @param key
* @return
@ -127,7 +127,7 @@ public class PartitionCache {
}
/**
* 根据 key hashcode 返回分区信息
* Returns partition information based on the hashcode of the key
*
* @param graphName
* @param code
@ -177,8 +177,10 @@ public class PartitionCache {
partitionCache.computeIfAbsent(graphName, k -> new HashMap<>()).put(partId, partition);
if (old != null) {
// old [1-3) [2-3) 覆盖了 [1-3) 变成 [1-2) 不应该删除原先的 [1-3)
// 当确认老的 start, end 都是自己的时候才可以删除老的(即还没覆盖
// old [1-3] is covered by [2-3]. When [1-3) becomes [1-2], the original [1-3]
// should not be deleted
// When you confirm that the old start and end are your own, you can delete the
// old ones. (i.e. not covered yet)
var graphRange = keyToPartIdCache.get(graphName);
if (Objects.equals(partition.getId(), graphRange.get(partition.getStartKey())) &&
Objects.equals(partition.getId(), graphRange.get(partition.getEndKey() - 1))) {

View File

@ -22,7 +22,7 @@ public class PartitionUtils {
public static final int MAX_VALUE = 0xffff;
/**
* 计算key的hashcode
* compute key hashcode
*
* @param key
* @return hashcode

View File

@ -71,7 +71,7 @@ public class ConfigService implements RaftStateListener {
}
/**
* 从存储中读取配置项并覆盖全局的PDConfig对象
* Read the configuration item from the storage and overwrite the global PD Config object
*
* @return
*/
@ -120,8 +120,9 @@ public class ConfigService implements RaftStateListener {
}
/**
* meta store中的数量
* 由于可能会受分区分裂/合并的影响原始的partition count不推荐使用
* Meta store
* The original partition count is not recommended due to the fact that it may be affected by
* partition splitting/merging
*
* @return partition count of cluster
* @throws PDException when io error

View File

@ -49,7 +49,8 @@ public class IdService {
}
/**
* 获取自增循环不重复id, 达到上限后从0开始自增.自动跳过正在使用的cid
* Obtain the non-duplicate ID of the auto-increment cycle, and automatically increment from
* 0 after the upper limit is reached
*
* @param key
* @param max
@ -65,7 +66,7 @@ public class IdService {
}
/**
* 删除一个自增循环id
* Delete an auto-increment loop ID
*
* @param key
* @param cid

View File

@ -44,7 +44,6 @@ import lombok.extern.slf4j.Slf4j;
public class KvService {
public static final char KV_DELIMITER = '@';
// TODO 主前缀之后增加类名做区分
private static final String TTL_PREFIX = "T";
private static final String KV_PREFIX = "K";
private static final String LOCK_PREFIX = "L";

View File

@ -28,7 +28,7 @@ import org.apache.hugegraph.pd.grpc.pulse.SplitPartition;
import org.apache.hugegraph.pd.grpc.pulse.TransferLeader;
/**
* 分区命令监听
* Partition command listening
*/
public interface PartitionInstructionListener {

View File

@ -52,7 +52,7 @@ import org.apache.hugegraph.pd.raft.RaftStateListener;
import lombok.extern.slf4j.Slf4j;
/**
* 分区管理
* Partition management
*/
@Slf4j
public class PartitionService implements RaftStateListener {
@ -61,10 +61,10 @@ public class PartitionService implements RaftStateListener {
private final StoreNodeService storeService;
private final PartitionMeta partitionMeta;
private final PDConfig pdConfig;
// 分区命令监听
// Partition command listening
private final List<PartitionInstructionListener> instructionListeners;
// 分区状态监听
// Partition status listeners
private final List<PartitionStatusListener> statusListeners;
public PartitionService(PDConfig config, StoreNodeService storeService) {
@ -83,7 +83,8 @@ public class PartitionService implements RaftStateListener {
public void onStoreStatusChanged(Metapb.Store store, Metapb.StoreState old,
Metapb.StoreState status) {
if (status == Metapb.StoreState.Tombstone) {
// Store被停机通知所有该store所有分区迁移数据
// When the store is stopped, notify all partitions of the store and migrate
// the data
storeOffline(store);
}
}
@ -103,7 +104,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 返回Key所属的partition
* return key partition
*
* @param graphName
* @param key
@ -116,7 +117,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 根据hashcode返回所属的partition
* Returns the partition to which it belongs based on the hashcode
*
* @param graphName
* @param code
@ -127,7 +128,7 @@ public class PartitionService implements RaftStateListener {
if (code < 0 || code >= PartitionUtils.MAX_VALUE) {
throw new PDException(Pdpb.ErrorType.NOT_FOUND_VALUE, "code error");
}
// 根据Code查找分区id如果没有找到创建新的分区
// Find the partition ID based on the code, and if it doesn't find, create a new partition
Metapb.Partition partition = partitionMeta.getPartitionByCode(graphName, code);
if (partition == null) {
@ -152,7 +153,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 根据ID返回分区信息
* Returns partition information based on ID
*
* @param graphName
* @param partId
@ -168,7 +169,6 @@ public class PartitionService implements RaftStateListener {
Metapb.PartitionShard partShard = Metapb.PartitionShard.newBuilder()
.setPartition(partition)
// 此处需要返回正确的leader暂时默认取第一个
.setLeader(storeService.getLeader(
partition, 0))
.build();
@ -185,7 +185,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 获取图的所有分区
* Get all partitions of the graph
*/
public List<Metapb.Partition> getPartitions() {
return partitionMeta.getPartitions();
@ -199,7 +199,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 查找在store上的所有分区
* Find all the partitions on the store
*
* @param store
* @return
@ -223,7 +223,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 产生一个新的分区
* Creates a new partition
*
* @param graphName
* @return
@ -232,7 +232,7 @@ public class PartitionService implements RaftStateListener {
Metapb.Graph graph = partitionMeta.getAndCreateGraph(graphName);
int partitionSize = PartitionUtils.MAX_VALUE / graph.getPartitionCount();
if (PartitionUtils.MAX_VALUE % graph.getPartitionCount() != 0) {
// 有余数分区除不尽
// There is a remainder, and the partition is inexhaustible
partitionSize++;
}
@ -240,12 +240,12 @@ public class PartitionService implements RaftStateListener {
long startKey = (long) partitionSize * partitionId;
long endKey = (long) partitionSize * (partitionId + 1);
// 检查本地
// Check Local
Metapb.Partition partition = partitionMeta.getPartitionById(graphName, partitionId);
if (partition == null) {
storeService.allocShards(null, partitionId);
// 分配store
// Assign a store
partition = Metapb.Partition.newBuilder()
.setId(partitionId)
.setVersion(0)
@ -264,11 +264,12 @@ public class PartitionService implements RaftStateListener {
}
/**
* 计算Key所属的分区此处采用Hash映射的方法
* compute graph partition idpartition gap * store group id + offset
*
* @param graphName
* @param key
* @return
* @param graph graph
* @param offset offset
* @return new partition id
* @throws PDException
*/
protected int getPartitionId(String graphName, byte[] key) throws PDException {
int code = PartitionUtils.calcHashcode(key);
@ -277,8 +278,9 @@ public class PartitionService implements RaftStateListener {
}
/**
* 获取key范围所跨越的所有分区
* 暂时使用hashcode计算正常做法基于key进行查询
* Gets all partitions spanned by the key range
* For the time being, hashcode is used for calculation, and the normal practice is to query
* based on the key
*
* @param graphName
* @param startKey
@ -296,7 +298,8 @@ public class PartitionService implements RaftStateListener {
partShards.add(
Metapb.PartitionShard.newBuilder()
.setPartition(partition)
// 此处需要返回正确的leader暂时默认取第一个
// Here you need to return the correct leader, and
// temporarily default to the first one
.setLeader(storeService.getLeader(partition, 0))
.build()
);
@ -314,7 +317,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 更新分区以及图的状态
* Update the status of partitions and graphs
*
* @param graph
* @param partId
@ -350,7 +353,6 @@ public class PartitionService implements RaftStateListener {
partitionMeta.reload();
onPartitionRemoved(partition);
// source中有些是 offline的删除后需要更新图的状态
try {
Metapb.PartitionState state = Metapb.PartitionState.PState_Normal;
for (Metapb.Partition pt : partitionMeta.getPartitions(partition.getGraphName())) {
@ -381,7 +383,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 获取图的分区状态
* Get the partition status of the graph
*/
public List<Metapb.PartitionStats> getPartitionStatus(String graphName)
throws PDException {
@ -389,7 +391,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 返回图的信息
* Returns the information of the graph
*/
public List<Metapb.Graph> getGraphs() throws PDException {
return partitionMeta.getGraphs();
@ -400,7 +402,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 删除图以及图的所有分区
* Delete the diagram and all partitions of the diagram
*/
public Metapb.Graph delGraph(String graphName) throws PDException {
log.info("delGraph {}", graphName);
@ -414,7 +416,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 修改图信息需要通知到store
* To modify the graph information, you need to notify the store
*/
public synchronized Metapb.Graph updateGraph(Metapb.Graph graph) throws PDException {
Metapb.Graph lastGraph = partitionMeta.getAndCreateGraph(graph.getGraphName());
@ -439,12 +441,11 @@ public class PartitionService implements RaftStateListener {
.build();
partitionMeta.updateGraph(graph);
// 分区数发生改变
// The number of partitions has changed
if (lastGraph.getPartitionCount() != graph.getPartitionCount()) {
log.info("updateGraph graph: {}, partition count changed from {} to {}",
graph.getGraphName(), lastGraph.getPartitionCount(),
graph.getPartitionCount());
// TODO 修改图的分区数需要进行数据迁移
}
return graph;
}
@ -468,7 +469,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 存储被下线迁移分区数据
* The storage is taken offline and the partition data is migrated
*
* @param store
*/
@ -491,7 +492,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 存储被下线迁移分区数据
* The storage is taken offline and the partition data is migrated
*/
public synchronized void shardOffline(Metapb.Partition partition, long storeId) {
try {
@ -537,7 +538,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 重新分配shard
* Reassign shards
*
* @param graph
* @param partition
@ -571,7 +572,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 迁移分区副本
* Migrate partition copies
*/
public synchronized void movePartitionsShard(Integer partitionId, long fromStore,
long toStore) {
@ -599,7 +600,7 @@ public class PartitionService implements RaftStateListener {
// storeService.updateShardGroup(partitionId, shards, -1, -1);
// storeService.onShardGroupStatusChanged(shardGroup, newShardGroup);
fireChangeShard(partition, shards, ConfChangeType.CONF_CHANGE_TYPE_ADJUST);
// shard group和 graph无关迁移一个就够了
// Shard groups have nothing to do with Graph, just one is enough
break;
}
} catch (PDException e) {
@ -608,9 +609,9 @@ public class PartitionService implements RaftStateListener {
}
/**
* 把集群中所有的分区拆成split
* Split all partitions in the cluster into splits
*
* @param splits 拆分分区
* @param splits Split partitions
*/
public synchronized void splitPartition(List<KVPair<Integer, Integer>> splits) throws
PDException {
@ -631,13 +632,12 @@ public class PartitionService implements RaftStateListener {
}
/**
* 分区分裂 把一个图拆分到N
* Partition splitting, splitting a graph into N pieces
*
* @param graph graph
* @param toCount target count
* @throws PDException
*/
public synchronized void splitPartition(Metapb.Graph graph, int toCount) throws PDException {
var partitionCount = getPartitions(graph.getGraphName()).size();
@ -656,7 +656,7 @@ public class PartitionService implements RaftStateListener {
" current partition count");
}
// 由于是整数倍数扩充因子为 toCount / current count
// Since it is an integer multiple,The enrichment factor is toCount / current count
var splitCount = toCount / partitionCount;
var list = new ArrayList<KVPair<Integer, Integer>>();
for (int i = 0; i < partitionCount; i++) {
@ -677,7 +677,7 @@ public class PartitionService implements RaftStateListener {
splits.sort(Comparator.comparing(KVPair::getKey));
log.info("split partition, graph: {}, splits:{}", graph, splits);
// 从最后一个partition下标开始
// Start with the last partition subscript
var i = getPartitions(graph.getGraphName()).size();
for (var pair : splits) {
@ -688,7 +688,7 @@ public class PartitionService implements RaftStateListener {
long splitLen = (partition.getEndKey() - partition.getStartKey()) / splitCount;
List<Metapb.Partition> newPartitions = new ArrayList<>();
// 第一个分区也就是原分区
// The first partition is the original partition
newPartitions.add(partition.toBuilder()
.setStartKey(partition.getStartKey())
.setEndKey(partition.getStartKey() + splitLen)
@ -724,8 +724,10 @@ public class PartitionService implements RaftStateListener {
if (j != 0) {
partitionMeta.updatePartition(newPartition);
}
// 创建shard group如果为空则按照partition的shard group为蓝本去创建保证在一个机器上
// 如果存在则由于各个图的分区数量不一样需要store端复制到其他机器上
// Create a shard group, if it is empty, create it according to the shard
// group of the partition, and ensure that it is on one machine
// If it exists, the number of partitions in each graph is not the same, and
// the store side needs to be copied to other machines
var shardGroup = storeService.getShardGroup(newPartition.getId());
if (shardGroup == null) {
shardGroup = storeService.getShardGroup(partition.getId()).toBuilder()
@ -735,7 +737,7 @@ public class PartitionService implements RaftStateListener {
updateShardGroupCache(shardGroup);
}
// 做shard list的检查
// check shard list
if (shardGroup.getShardsCount() != pdConfig.getPartition().getShardCount()) {
storeService.reallocShards(shardGroup);
}
@ -746,11 +748,12 @@ public class PartitionService implements RaftStateListener {
.build();
fireSplitPartition(partition, splitPartition);
// 修改Partition状态为下线任务完成后恢复为上线
// Change the partition status to Offline, and resume the partition status to
// Offline after the task is completed
updatePartitionState(partition.getGraphName(), partition.getId(),
Metapb.PartitionState.PState_Offline);
// 记录事务
// Record transactions
var task = MetaTask.Task.newBuilder().setPartition(partition)
.setSplitPartition(splitPartition)
.build();
@ -761,8 +764,8 @@ public class PartitionService implements RaftStateListener {
}
/**
* 转移leader到其他shard上.
* 转移一个partition即可
* transfer leader to other shard
* Just transfer a partition
*/
public void transferLeader(Integer partId, Metapb.Shard shard) {
try {
@ -784,16 +787,17 @@ public class PartitionService implements RaftStateListener {
}
/**
* 分区合并将整个集群的分区数合并到toCount个
* // todo : Check the corresponding store group and check the logic
* Partition merging: Merges the number of partitions in the entire cluster into toCount
*
* @param toCount 目标分区数
* @param toCount The number of partitions to be targeted
* @throws PDException when query errors
*/
public void combinePartition(int toCount) throws PDException {
int shardsTotalCount = getShardGroupCount();
for (var graph : getGraphs()) {
// 对所有大于toCount分区的图都进行缩容
// All graphs larger than the toCount partition are scaled in
if (graph.getPartitionCount() > toCount) {
combineGraphPartition(graph, toCount, shardsTotalCount);
}
@ -801,19 +805,18 @@ public class PartitionService implements RaftStateListener {
}
/**
* 针对单个图进行分区合并
* For a single graph, perform partition merging
*
* @param graphName the name of the graph
* @param toCount the target partition count
* @throws PDException when query errors
*/
public void combineGraphPartition(String graphName, int toCount) throws PDException {
combineGraphPartition(getGraph(graphName), toCount, getShardGroupCount());
}
/**
* 单图合并的内部实现
* Internal implementation of single-graph merging
*
* @param graph the name of the graph
* @param toCount the target partition count
@ -845,22 +848,22 @@ public class PartitionService implements RaftStateListener {
throw new PDException(3, "Graph Combine process exists");
}
// 按照 key start 排序合并后的key range 是连续的
// According to key start sort
var partitions = getPartitions(graph.getGraphName()).stream()
.sorted(Comparator.comparing(
Metapb.Partition::getStartKey))
.collect(Collectors.toList());
// 分区编号不一定是连续的
// Partition numbers do not have to be sequential
var sortPartitions = getPartitions(graph.getGraphName())
.stream()
.sorted(Comparator.comparing(Metapb.Partition::getId))
.collect(Collectors.toList());
var groupSize = partitions.size() / toCount; // merge group size
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 共12个分区, 合并成4个
// 方案0,1,2 => 0, 3,4,5 -> 1, 6,7,8 ->2, 9,10,11 -> 3
// 保证分区的连续性.
// 0~12 to 4 partitions
// scheme0,1,2 => 0, 3,4,5 -> 1, 6,7,8 ->2, 9,10,11 -> 3
// Ensure the continuity of partitions
for (int i = 0; i < toCount; i++) {
var startKey = partitions.get(i * groupSize).getStartKey();
var endKey = partitions.get(i * groupSize + groupSize - 1).getEndKey();
@ -874,7 +877,7 @@ public class PartitionService implements RaftStateListener {
for (int j = 0; j < groupSize; j++) {
var partition = partitions.get(i * groupSize + j);
// 分区id相同就跳过
// If the partition ID is the same, skip it
if (i == partition.getId()) {
continue;
}
@ -888,12 +891,12 @@ public class PartitionService implements RaftStateListener {
.setKeyEnd(partition.getEndKey())
.build();
taskInfoMeta.addMovePartitionTask(partition, movePartition);
// source 下线
// source is offline
updatePartitionState(partition.getGraphName(), partition.getId(),
Metapb.PartitionState.PState_Offline);
fireMovePartition(partition, movePartition);
}
// target 下线
// target offline
updatePartitionState(targetPartition.getGraphName(), targetPartition.getId(),
Metapb.PartitionState.PState_Offline);
}
@ -902,7 +905,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 通过 storeService 获取 raft group 总数
* get raft group count from storeService
*
* @return the count of raft groups
*/
@ -917,30 +920,31 @@ public class PartitionService implements RaftStateListener {
}
/**
* 判断图分区是否能够从from合并到to个
* Determine whether the graph partition can be retrieved from f to t
*
* @param fromCount 现在的分区数
* @param toCount 目标分区数
* @param fromCount The number of partitions now
* @param toCount The number of partitions to be targeted
* @return true when available , or otherwise
*/
private boolean checkTargetCount(int fromCount, int toCount, int shardCount) {
// 要介于 1 ~ N 中间而且可以整除
// It should be between 1 ~ N and divisible
return toCount >= 1 && toCount < fromCount && fromCount % toCount == 0 &&
toCount < shardCount;
}
/**
* 处理分区心跳 记录Leader信息
* 检查term和version比较是否是最新的消息
* Process partition heartbeats and record leader information
* Check the term and version to see if it's the latest message
*
* @param stats
*/
public void partitionHeartbeat(Metapb.PartitionStats stats) throws PDException {
Metapb.ShardGroup shardGroup = storeService.getShardGroup(stats.getId());
// shard group version changes
// (shard group 由pd控制, 在分裂等操作后可能出现短暂不一致的情况以pd为准
// store控制shard leader
// shard group version changes or leader changes
// (The shard group is controlled by the PD, and there may be brief inconsistencies after
// operations such as splitting, subject to PD)
// store Upload the final one raft group data
if (shardGroup != null &&
(shardGroup.getVersion() < stats.getLeaderTerm() ||
shardGroup.getConfVer() < stats.getConfVer())) {
@ -954,13 +958,13 @@ public class PartitionService implements RaftStateListener {
// partitionMeta.getAndCreateGraph(partition.getGraphName());
checkShardState(partition, stats);
}
// 统计信息
// statistics
partitionMeta.updatePartitionStats(stats.toBuilder()
.setTimestamp(System.currentTimeMillis()).build());
}
/**
* 检查shard状态离线shard影响到分区状态
* Check the shard status, offline shard affects the partition status
*
* @param stats
*/
@ -1000,7 +1004,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 发起改变shard命令
* Initiates the Change Shard command
*
* @param changeType
*/
@ -1028,7 +1032,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 发送分区分裂消息
* Send a partition split message
*
* @param partition
*/
@ -1045,7 +1049,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 发送Leader切换消息
* Send a Leader Switchover message
*/
protected void fireTransferLeader(Metapb.Partition partition, TransferLeader transferLeader) {
log.info("fireTransferLeader partition: {}-{} leader :{}",
@ -1060,10 +1064,10 @@ public class PartitionService implements RaftStateListener {
}
/**
* 发送分区移动数据的消息
* Send a message to the partition to move data
*
* @param partition 原分区
* @param movePartition 目标分区包含 key range
* @param partition Original partition
* @param movePartition Target partitioncontains key range
*/
protected void fireMovePartition(Metapb.Partition partition, MovePartition movePartition) {
log.info("fireMovePartition partition: {} -> {}",
@ -1106,7 +1110,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* 处理图迁移任务
* Handle graph migration tasks
*
* @param task
*/
@ -1125,7 +1129,7 @@ public class PartitionService implements RaftStateListener {
task.getPartition().getId(), task.getMovePartition().getTargetPartition().getId(),
task.getState());
// 已经被处理前面有failed)
// HAS BEEN PROCESSED(There is it in front)
if (pdMetaTask != null) {
var newTask = pdMetaTask.toBuilder().setState(task.getState()).build();
taskInfoMeta.updateMovePartitionTask(newTask);
@ -1153,10 +1157,10 @@ public class PartitionService implements RaftStateListener {
}
/**
* 当所有的迁移子任务成功:
* 1. 发送清理source分区指令
* 2. 设置target上线, 更新key range, 更新 graph partition count
* 3. 删除move task任务结束
* When all migration subtasks succeed:
* 1. Send cleanup source partition directives
* 2. Set up target onlinerenewal key range, renewal graph partition count
* 3. delete move taskmission ended
*
* @param subTasks all move sub tasks
* @param graphName graph name
@ -1175,20 +1179,21 @@ public class PartitionService implements RaftStateListener {
for (MetaTask.Task subTask : subTasks) {
var source = subTask.getPartition();
var targetPartition = subTask.getMovePartition().getTargetPartition();
// 是否处理过
// Whether it has been dealt with or not
if (!targetPartitionIds.contains(targetPartition.getId())) {
// 更新range
// renewal range
var old = getPartitionById(targetPartition.getGraphName(), targetPartition.getId());
var newPartition = Metapb.Partition.newBuilder(old)
.setStartKey(targetPartition.getStartKey())
.setEndKey(targetPartition.getEndKey())
.setState(Metapb.PartitionState.PState_Normal)
.build();
// key range之前更新避免store没有分区的问题, 需要到pd查询
// Update before the key range to avoid the problem that the store does not have
// a partition and needs to be queried to the pd
updatePartition(List.of(newPartition));
targetPartitions.add(newPartition);
// 发送key range 变更消息
// Send key range change messages
PartitionKeyRange partitionKeyRange = PartitionKeyRange.newBuilder()
.setPartitionId(old.getId())
.setKeyStart(
@ -1196,12 +1201,13 @@ public class PartitionService implements RaftStateListener {
.setKeyEnd(
targetPartition.getEndKey())
.build();
// 通知store
// Notice store
fireChangePartitionKeyRange(
old.toBuilder().setState(Metapb.PartitionState.PState_Normal).build(),
partitionKeyRange);
// target 设置为上线. source 理论上可能被删掉所以不处理
// Set Target to go live. source could theoretically be deleted, so it is not
// processed
updatePartitionState(newPartition.getGraphName(), newPartition.getId(),
Metapb.PartitionState.PState_Normal);
@ -1213,7 +1219,9 @@ public class PartitionService implements RaftStateListener {
.setKeyEnd(source.getEndKey())
.setCleanType(
CleanType.CLEAN_TYPE_EXCLUDE_RANGE)
// target partition只需要清理数据不需要删除分区
// The partition of the target only
// needs to clean up the data, and does
// not need to delete the partition
.setDeletePartition(!deleteFlags.contains(
source.getId()))
.build();
@ -1226,14 +1234,14 @@ public class PartitionService implements RaftStateListener {
CleanType.CLEAN_TYPE_EXCLUDE_RANGE,
cleanPartition.getDeletePartition());
// 清理掉被移动分区的数据
// Clean up the data of the partition to be moved
fireCleanPartition(source, cleanPartition);
}
// 更新key range, 本地更新client更新
// renewal key range, Local updatesclient renewal
// updatePartition(targetPartitions);
// 更新target 分区状态source 可能被删掉所以不处理
// renewal target Partition status, source may be deleted, so do not process
targetPartitions.forEach(p -> {
try {
updatePartitionState(p.getGraphName(), p.getId(),
@ -1245,21 +1253,21 @@ public class PartitionService implements RaftStateListener {
partitionMeta.reload();
// 更新graph partition count
// renewal graph partition count
var graph = getGraph(graphName).toBuilder()
.setPartitionCount(targetPartitionIds.size())
.build();
updateGraph(graph);
// 事务完成
// The transaction is complete
taskInfoMeta.removeMoveTaskPrefix(graphName);
}
/**
* 如果缩容任务有失败的回滚合并操作
* 1. 清理原来的target 分区将迁移过来的数据再删掉
* 2. 将source/target 分区设置为上线
* 3. 删除task任务结束
* If the scale-in task fails, roll back the merge operation
* 1. Clean up the original target partition and delete the migrated data
* 2. Set the source/target partition to go live
* 3. Delete the task, and the task ends
*
* @param graphName graph name
* @param taskInfoMeta task info meta
@ -1267,12 +1275,12 @@ public class PartitionService implements RaftStateListener {
*/
private void handleMoveTaskIfFailed(String graphName, TaskInfoMeta taskInfoMeta) throws
PDException {
// 发送清理target分区的任务, 回滚target分区
// Send cleanup target partition tasks,rollback target partition
var targetPartitionIds = new HashSet<Integer>();
for (var metaTask : taskInfoMeta.scanMoveTask(graphName)) {
var source = metaTask.getPartition();
// 设置 source 为上线
// Set source to upline
updatePartitionState(source.getGraphName(), source.getId(),
Metapb.PartitionState.PState_Normal);
var movedPartition = metaTask.getMovePartition().getTargetPartition();
@ -1294,16 +1302,16 @@ public class PartitionService implements RaftStateListener {
fireCleanPartition(targetPartition, cleanPartition);
targetPartitionIds.add(targetPartition.getId());
// 设置target 上线
// Set Target online
updatePartitionState(targetPartition.getGraphName(), targetPartition.getId(),
Metapb.PartitionState.PState_Normal);
}
// 清理掉任务列表
// Clean up the task list
taskInfoMeta.removeMoveTaskPrefix(graphName);
}
/**
* 处理clean task
* dispose clean task
*
* @param task clean task
*/
@ -1316,7 +1324,7 @@ public class PartitionService implements RaftStateListener {
task.getState()
);
// 如果失败重试
// If it fails, try again?
}
public synchronized void handleSplitTask(MetaTask.Task task) throws PDException {
@ -1366,7 +1374,7 @@ public class PartitionService implements RaftStateListener {
var source = subTask.getPartition();
var newPartition = subTask.getSplitPartition().getNewPartitionList().get(0);
// 发送key range 变更消息
// Send key range change messages
PartitionKeyRange partitionKeyRange = PartitionKeyRange.newBuilder()
.setPartitionId(source.getId())
.setKeyStart(
@ -1374,16 +1382,18 @@ public class PartitionService implements RaftStateListener {
.setKeyEnd(
newPartition.getEndKey())
.build();
// 通知store
// Notice store
fireChangePartitionKeyRange(source, partitionKeyRange);
// target 设置为上线. source 理论上可能被删掉所以不处理
// Set Target to go live. source could theoretically be deleted, so it is not processed
CleanPartition cleanPartition = CleanPartition.newBuilder()
.setKeyStart(newPartition.getStartKey())
.setKeyEnd(newPartition.getEndKey())
.setCleanType(
CleanType.CLEAN_TYPE_KEEP_RANGE)
// target partition只需要清理数据不需要删除分区
// The partition of the target only
// needs to clean up the data, and does
// not need to delete the partition
.setDeletePartition(false)
.build();
@ -1397,7 +1407,7 @@ public class PartitionService implements RaftStateListener {
fireCleanPartition(source, cleanPartition);
// 更新partition state
// renewal partition state
for (var sp : subTask.getSplitPartition().getNewPartitionList()) {
partitions.add(
sp.toBuilder().setState(Metapb.PartitionState.PState_Normal).build());
@ -1419,13 +1429,13 @@ public class PartitionService implements RaftStateListener {
storeService.getShardGroups().size());
}
// 更新graph partition count
// renewal graph partition count
var newGraph = graph.toBuilder()
.setPartitionCount(graph.getPartitionCount() + addedPartitions)
.build();
updateGraph(newGraph);
// 事务完成
// The transaction is complete
taskInfoMeta.removeSplitTaskPrefix(graphName);
}
@ -1452,18 +1462,18 @@ public class PartitionService implements RaftStateListener {
updatePartitionState(partition.getGraphName(), partition.getId(),
Metapb.PartitionState.PState_Normal);
}
// 清理掉任务列表
// Clean up the task list
taskInfoMeta.removeSplitTaskPrefix(graphName);
}
/**
* 接收到Leader改变的消息
* 更新图状态触发分区变更
* todo : What is the impact of partition changes??
* Received a message that the leader has changed
* Update the status of the graph and trigger a partition change
*/
protected void onPartitionChanged(Metapb.Partition old, Metapb.Partition partition) {
log.info("onPartitionChanged partition: {}", partition);
if (old != null && old.getState() != partition.getState()) {
// 状态改变重置图的状态
Metapb.PartitionState state = Metapb.PartitionState.PState_Normal;
for (Metapb.Partition pt : partitionMeta.getPartitions(partition.getGraphName())) {
if (pt.getState().getNumber() > state.getNumber()) {
@ -1491,7 +1501,7 @@ public class PartitionService implements RaftStateListener {
}
/**
* PD的leader发生改变需要重新加载数据
* The leader of the PD has changed and the data needs to be reloaded
*/
@Override
public void onRaftLeaderChanged() {
@ -1503,31 +1513,17 @@ public class PartitionService implements RaftStateListener {
}
}
/**
* 分区状态发生改变需要传播到图集群
*
* @param graph
* @param partId
* @param state
*/
public void onPartitionStateChanged(String graph, int partId,
Metapb.PartitionState state) throws PDException {
updatePartitionState(graph, partId, state);
}
/**
* Shard状态发生改变需要传播到分区集群
*
* @param graph
* @param partId
* @param state
*/
public void onShardStateChanged(String graph, int partId, Metapb.PartitionState state) {
}
/**
* 发送rocksdb compaction 消息
* Send rocksdb compaction message
*
* @param partId
* @param tableName

View File

@ -20,7 +20,7 @@ package org.apache.hugegraph.pd;
import org.apache.hugegraph.pd.grpc.Metapb;
/**
* 分区状态监听
* Partition status listeners
*/
public interface PartitionStatusListener {

View File

@ -48,14 +48,13 @@ import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
/**
* HgStore注册保活管理类
* Hg Store registration and keep-alive management
*/
@Slf4j
public class StoreNodeService {
private static final Long STORE_HEART_BEAT_INTERVAL = 30000L;
private static final String graphSpaceConfPrefix = "HUGEGRAPH/hg/GRAPHSPACE/CONF/";
// Store状态监听
private final List<StoreStatusListener> statusListeners;
private final List<ShardGroupStatusListener> shardGroupStatusListeners;
private final StoreInfoMeta storeInfoMeta;
@ -96,7 +95,6 @@ public class StoreNodeService {
@Override
public void onPartitionChanged(Metapb.Partition old, Metapb.Partition partition) {
if (old != null && old.getState() != partition.getState()) {
// 状态改变重置集群状态
try {
List<Metapb.Partition> partitions =
partitionService.getPartitionById(partition.getId());
@ -128,7 +126,7 @@ public class StoreNodeService {
}
/**
* 集群是否准备就绪
* Whether the cluster is ready or not
*
* @return
*/
@ -138,36 +136,37 @@ public class StoreNodeService {
}
/**
* Store注册记录Store的ip地址首次注册需要生成store_ID
* Store registration, record the IP address of the Store, and the first registration needs
* to generate a store_ID
*
* @param store
*/
public Metapb.Store register(Metapb.Store store) throws PDException {
if (store.getId() == 0) {
// 初始注册生成新id保证Id不重复
// Initial registration, generate a new ID, and ensure that the ID is not duplicated.
store = newStoreNode(store);
}
if (!storeInfoMeta.storeExists(store.getId())) {
log.error("Store id {} does not belong to this PD, address = {}", store.getId(),
store.getAddress());
// storeId不存在抛出异常
// storeId does not exist, an exception is thrown
throw new PDException(Pdpb.ErrorType.STORE_ID_NOT_EXIST_VALUE,
String.format("Store id %d doest not exist.", store.getId()));
}
// 如果store状态为Tombstone拒绝注册
// If the store status is Tombstone, the registration is denied.
Metapb.Store lastStore = storeInfoMeta.getStore(store.getId());
if (lastStore.getState() == Metapb.StoreState.Tombstone) {
log.error("Store id {} has been removed, Please reinitialize, address = {}",
store.getId(), store.getAddress());
// storeId不存在抛出异常
// storeId does not exist, an exception is thrown
throw new PDException(Pdpb.ErrorType.STORE_HAS_BEEN_REMOVED_VALUE,
String.format("Store id %d has been removed. %s", store.getId(),
store.getAddress()));
}
// offline或者up或者在初始激活列表中自动上线
// offline or up, or in the initial activation list, go live automatically
Metapb.StoreState storeState = lastStore.getState();
if (storeState == Metapb.StoreState.Offline || storeState == Metapb.StoreState.Up
|| inInitialStoreList(store)) {
@ -189,33 +188,34 @@ public class StoreNodeService {
long current = System.currentTimeMillis();
boolean raftChanged = false;
// 上线状态的Raft Address 发生了变更
// On-line status Raft Address there has been a change
if (!Objects.equals(lastStore.getRaftAddress(), store.getRaftAddress()) &&
storeState == Metapb.StoreState.Up) {
// 时间间隔太短而且raft有变更则认为是无效的store
// If the time interval is too short and the raft changes, it is considered an
// invalid store
if (current - lastStore.getLastHeartbeat() < STORE_HEART_BEAT_INTERVAL * 0.8) {
throw new PDException(Pdpb.ErrorType.STORE_PROHIBIT_DUPLICATE_VALUE,
String.format("Store id %d may be duplicate. addr: %s",
store.getId(), store.getAddress()));
} else if (current - lastStore.getLastHeartbeat() > STORE_HEART_BEAT_INTERVAL * 1.2) {
// 认为发生了变更
// It is considered that a change has occurred
raftChanged = true;
} else {
// 等待下次注册
// Wait for the next registration
return Metapb.Store.newBuilder(store).setId(0L).build();
}
}
// 存储store信息
// Store information
storeInfoMeta.updateStore(store);
if (storeState == Metapb.StoreState.Up) {
// 更新store 活跃状态
// Update the store active status
storeInfoMeta.keepStoreAlive(store);
onStoreStatusChanged(store, Metapb.StoreState.Offline, Metapb.StoreState.Up);
checkStoreStatus();
}
// 等store信息保存后再发送变更
// Wait for the store information to be saved before sending the changes
if (raftChanged) {
onStoreRaftAddressChanged(store);
}
@ -229,7 +229,7 @@ public class StoreNodeService {
}
/**
* 产生一个新的store对象
* Creates a new store object
*
* @param store
* @return
@ -249,7 +249,7 @@ public class StoreNodeService {
}
/**
* 根据store_id返回Store信息
* Returns Store information based on store_id
*
* @param id
* @return
@ -265,7 +265,7 @@ public class StoreNodeService {
}
/**
* 更新Store信息检测Store状态的变化通知到Hugestore
* Update the store information, detect the change of store status, and notify Hugestore
*/
public synchronized Metapb.Store updateStore(Metapb.Store store) throws PDException {
log.info("updateStore storeId: {}, address: {}, state: {}", store.getId(),
@ -290,10 +290,10 @@ public class StoreNodeService {
storeInfoMeta.updateStore(store);
if (store.getState() != Metapb.StoreState.Unknown &&
store.getState() != lastStore.getState()) {
// 如果希望将store下线
// If you want to take the store offline
if (store.getState() == Metapb.StoreState.Exiting) {
if (lastStore.getState() == Metapb.StoreState.Exiting) {
//如果已经是下线中的状态则不作进一步处理
// If it is already in the offline state, no further processing will be made
return lastStore;
}
@ -302,19 +302,23 @@ public class StoreNodeService {
activeStores.forEach(s -> {
storeMap.put(s.getId(), s);
});
//如果store已经离线直接从活跃中删除如果store在线暂时不从活跃中删除等把状态置成Tombstone的时候再删除
// If the store is offline, delete it directly from active, and if the store is
// online, temporarily delete it from active, and then delete it when the status
// is set to Tombstone
if (!storeMap.containsKey(store.getId())) {
log.info("updateStore removeActiveStores store {}", store.getId());
storeInfoMeta.removeActiveStore(store);
}
storeTurnoff(store);
} else if (store.getState() == Metapb.StoreState.Offline) { //监控到store已经离线从活跃中删除
} else if (store.getState() == Metapb.StoreState.Offline) {
// Monitor that the store has gone offline and is removed from the active
storeInfoMeta.removeActiveStore(store);
} else if (store.getState() == Metapb.StoreState.Tombstone) {
// 状态发生改变Store关机修改shardGroup进行副本迁移
// When the status changes, the store is shut down, the shardGroup is modified,
// and the replica is migrated
log.info("updateStore removeActiveStores store {}", store.getId());
storeInfoMeta.removeActiveStore(store);
// 存储下线
// Storage goes offline
storeTurnoff(store);
} else if (store.getState() == Metapb.StoreState.Up) {
storeInfoMeta.keepStoreAlive(store);
@ -326,13 +330,13 @@ public class StoreNodeService {
}
/**
* store被关机重新分配shardGroup的shard
* The shard of the shardGroup is reassigned
*
* @param store
* @throws PDException
*/
public synchronized void storeTurnoff(Metapb.Store store) throws PDException {
// 遍历ShardGroup重新分配shard
// Traverse ShardGroup,redistribution
for (Metapb.ShardGroup group : getShardGroupsByStore(store.getId())) {
Metapb.ShardGroup.Builder builder = Metapb.ShardGroup.newBuilder(group);
builder.clearShards();
@ -346,7 +350,8 @@ public class StoreNodeService {
}
/**
* 根据图名返回stores信息如果graphName为空返回所有store信息
* Returns stores information based on the graph name, and if graphName is empty, all store
* information is returned
*
* @throws PDException
*/
@ -391,7 +396,7 @@ public class StoreNodeService {
}
/**
* 返回活跃的store
* Returns the active store
*
* @param graphName
* @return
@ -420,16 +425,19 @@ public class StoreNodeService {
}
/**
* 给partition分配store根据图的配置决定分配几个peer
* 分配完所有的shards保存ShardGroup对象store不变动只执行一次
* todo : New logic
* Assign a store to the partition and decide how many peers to allocate according to the
* configuration of the graph
* After allocating all the shards, save the ShardGroup object (store does not change, only
* executes once)
*/
public synchronized List<Metapb.Shard> allocShards(Metapb.Graph graph, int partId) throws
PDException {
// 多图共用raft分组因此分配shard只依赖partitionId.
// 图根据数据大小可以设置分区的数量但总数不能超过raft分组数量
// Multiple graphs share raft grouping, so assigning shard only depends on partitionId.
// The number of partitions can be set based on the size of the data, but the total
// number cannot exceed the number of raft groups
if (storeInfoMeta.getShardGroup(partId) == null) {
// 获取活跃的store key
// 根据 partionID计算store
// Get active store key
List<Metapb.Store> stores = storeInfoMeta.getActiveStores();
if (stores.size() == 0) {
@ -445,17 +453,18 @@ public class StoreNodeService {
int shardCount = pdConfig.getPartition().getShardCount();
shardCount = Math.min(shardCount, stores.size());
//两个shard无法选出leader
// 不能为0
// Two shards could not elect a leader
// It cannot be 0
if (shardCount == 2 || shardCount < 1) {
shardCount = 1;
}
// 一次创建完所有的ShardGroup保证初始的groupID有序方便人工阅读
// All ShardGroups are created at one time to ensure that the initial groupIDs are
// orderly and easy for humans to read
for (int groupId = 0; groupId < pdConfig.getConfigService().getPartitionCount();
groupId++) {
int storeIdx = groupId % stores.size(); //store分配规则简化为取模
int storeIdx = groupId % stores.size(); // Assignment rules, simplified to modulo
List<Metapb.Shard> shards = new ArrayList<>();
for (int i = 0; i < shardCount; i++) {
Metapb.Shard shard =
@ -464,7 +473,7 @@ public class StoreNodeService {
Metapb.ShardRole.Follower) //
.build();
shards.add(shard);
storeIdx = (storeIdx + 1) >= stores.size() ? 0 : ++storeIdx; // 顺序选择
storeIdx = (storeIdx + 1) >= stores.size() ? 0 : ++storeIdx; // Sequential
}
Metapb.ShardGroup group = Metapb.ShardGroup.newBuilder()
@ -484,8 +493,8 @@ public class StoreNodeService {
}
/**
* 根据graph的shard_count重新分配shard
* 发送变更change shard指令
* Based on the shard_count of the graph, reallocate shards
* Send change shard
*/
public synchronized List<Metapb.Shard> reallocShards(Metapb.ShardGroup shardGroup) throws
PDException {
@ -505,8 +514,8 @@ public class StoreNodeService {
int shardCount = pdConfig.getPartition().getShardCount();
shardCount = Math.min(shardCount, stores.size());
if (shardCount == 2 || shardCount < 1) {
// 两个shard无法选出leader
// 不能为0
// Two shards could not elect a leader
// It cannot be 0
shardCount = 1;
}
@ -514,12 +523,12 @@ public class StoreNodeService {
shards.addAll(shardGroup.getShardsList());
if (shardCount > shards.size()) {
// 需要增加shard
// Need to add shards
log.info("reallocShards ShardGroup {}, add shards from {} to {}",
shardGroup.getId(), shards.size(), shardCount);
int storeIdx = shardGroup.getId() % stores.size(); //store分配规则简化为取模
int storeIdx = shardGroup.getId() % stores.size();
for (int addCount = shardCount - shards.size(); addCount > 0; ) {
// 检查是否已经存在
// Check if it already exists
if (!isStoreInShards(shards, stores.get(storeIdx).getId())) {
Metapb.Shard shard = Metapb.Shard.newBuilder()
.setStoreId(stores.get(storeIdx).getId())
@ -527,10 +536,10 @@ public class StoreNodeService {
shards.add(shard);
addCount--;
}
storeIdx = (storeIdx + 1) >= stores.size() ? 0 : ++storeIdx; // 顺序选择
storeIdx = (storeIdx + 1) >= stores.size() ? 0 : ++storeIdx;
}
} else if (shardCount < shards.size()) {
// 需要减shard
// Need to reduce shard
log.info("reallocShards ShardGroup {}, remove shards from {} to {}",
shardGroup.getId(), shards.size(), shardCount);
@ -566,7 +575,7 @@ public class StoreNodeService {
}
/**
* 根据partition的数量分配group shard
* According to the number of partitionsdistribute group shard
*
* @param groups list of (partition id, count)
* @return total groups
@ -574,7 +583,7 @@ public class StoreNodeService {
public synchronized int splitShardGroups(List<KVPair<Integer, Integer>> groups) throws
PDException {
int sum = groups.stream().map(pair -> pair.getValue()).reduce(0, Integer::sum);
// shard group 太大
// shard group is too big
if (sum > getActiveStores().size() * pdConfig.getPartition().getMaxShardsPerStore()) {
throw new PDException(Pdpb.ErrorType.Too_Many_Partitions_Per_Store_VALUE,
"can't satisfy target shard group count");
@ -586,8 +595,9 @@ public class StoreNodeService {
}
/**
* 分配shard group为分裂做准备
* Alloc shard group, prepare for the split
*
* @param
* @return true
* @throws PDException
*/
@ -639,10 +649,10 @@ public class StoreNodeService {
}
/**
* 通知 store 进行shard group的重建操作
* Notify the Store to rebuild the shard group
*
* @param groupId raft group id
* @param shards shard list: 如果为空则删除对应的partition engine
* @param shards shard list: If it is empty, delete the corresponding one partition engine
*/
public void shardGroupOp(int groupId, List<Metapb.Shard> shards) throws PDException {
@ -665,7 +675,7 @@ public class StoreNodeService {
}
/**
* 删除 shard group
* Delete shard group
*
* @param groupId shard group id
*/
@ -677,7 +687,7 @@ public class StoreNodeService {
onShardGroupStatusChanged(group, null);
// 修正store的分区数. (分区合并导致)
// Fix the number of partitions for the store. (Result from partition merge)
var shardGroups = getShardGroups();
if (shardGroups != null) {
var count1 = pdConfig.getConfigService().getPDConfig().getPartitionCount();
@ -699,7 +709,7 @@ public class StoreNodeService {
}
/**
* 接收Store的心跳
* Receive the heartbeat of the Store
*
* @param storeStats
* @throws PDException
@ -708,7 +718,7 @@ public class StoreNodeService {
this.storeInfoMeta.updateStoreStats(storeStats);
Metapb.Store lastStore = this.getStore(storeStats.getStoreId());
if (lastStore == null) {
//store不存在
// store does not exist
throw new PDException(Pdpb.ErrorType.STORE_ID_NOT_EXIST_VALUE,
String.format("Store id %d does not exist.",
storeStats.getStoreId()));
@ -720,14 +730,16 @@ public class StoreNodeService {
storeStats.getStoreId()));
}
Metapb.Store nowStore;
// 如果正在做store下线操作
// If you are going to take the store offline
if (lastStore.getState() == Metapb.StoreState.Exiting) {
List<Metapb.Store> activeStores = this.getActiveStores();
Map<Long, Metapb.Store> storeMap = new HashMap<>();
activeStores.forEach(store -> {
storeMap.put(store.getId(), store);
});
// 下线的store的分区为0说明已经迁移完毕可以下线如果非0则迁移还在进行需要等待
// If the partition of the offline store is 0, it means that the migration has been
// completed and can be taken offline, if it is not 0, the migration is still in
// progress and you need to wait
if (storeStats.getPartitionCount() > 0 &&
storeMap.containsKey(storeStats.getStoreId())) {
nowStore = Metapb.Store.newBuilder(lastStore)
@ -799,9 +811,9 @@ public class StoreNodeService {
}
/**
* 检查集群健康状态
* 活跃机器数是否大于最小阈值
* 分区shard在线数已否过半 *
* Check the cluster health status
* Whether the number of active machines is greater than the minimum threshold
* The number of partition shards online has exceeded half
*/
public synchronized void checkStoreStatus() {
Metapb.ClusterStats.Builder builder = Metapb.ClusterStats.newBuilder()
@ -821,7 +833,7 @@ public class StoreNodeService {
});
if (builder.getState() == Metapb.ClusterState.Cluster_OK) {
// 检查每个分区的在线shard数量是否大于半数
// Check whether the number of online shards for each partition is greater than half
for (Metapb.ShardGroup group : this.getShardGroups()) {
int count = 0;
for (Metapb.Shard shard : group.getShardsList()) {
@ -881,9 +893,10 @@ public class StoreNodeService {
}
/**
* 检查当前store是否可下线
* 活跃机器数小于等于最小阈值不可下线
* 分区shard在线数不超过半数 不可下线
* Check whether the current store can be discontinued
* If the number of active machines is less than or equal to the minimum threshold, they
* cannot be taken offline
* If the number of shards in the partition is not more than half, it cannot be offline
*/
public boolean checkStoreCanOffline(Metapb.Store currentStore) {
try {
@ -900,7 +913,7 @@ public class StoreNodeService {
return false;
}
// 检查每个分区的在线shard数量是否大于半数
// Check whether the number of online shards for each partition is greater than half
for (Metapb.ShardGroup group : this.getShardGroups()) {
int count = 0;
for (Metapb.Shard shard : group.getShardsList()) {
@ -920,7 +933,7 @@ public class StoreNodeService {
}
/**
* 对store上的对rocksdb进行compaction
* Compaction on rocksdb on the store
*
* @param groupId
* @param tableName
@ -929,9 +942,9 @@ public class StoreNodeService {
public synchronized void shardGroupsDbCompaction(int groupId, String tableName) throws
PDException {
// 通知所有的store对rocksdb进行compaction
// Notify all stores to compaction rocksdb
partitionService.fireDbCompaction(groupId, tableName);
// TODO 异常怎么处理
// TODO How to deal with exceptions?
}
public Map getQuota() throws PDException {
@ -1037,7 +1050,7 @@ public class StoreNodeService {
}
/**
* 获得分区的Leader
* Get the leader of the partition
*
* @param partition
* @param initIdx

View File

@ -44,18 +44,21 @@ import org.apache.hugegraph.pd.raft.RaftEngine;
import lombok.extern.slf4j.Slf4j;
/**
* 任务调度服务定时检查Store资源分区的状态及时迁移数据错误节点
* 1监测Store是否离线
* 2监测Partition的副本是否正确
* 3监测Partition的工作模式是否正确
* 4监测Partition是否需要分裂,监测分裂是否完成
* The task scheduling service checks the status of stores, resources, and partitions on a
* regular basis, migrates data in a timely manner, and errors are on nodes
* 1. Monitor whether the store is offline
* 2. Check whether the replica of the partition is correct
* 3. Check whether the working mode of the partition is correct
* 4. Monitor whether the partition needs to be split and whether the split is completed
*/
@Slf4j
public class TaskScheduleService {
private static final String BALANCE_SHARD_KEY = "BALANCE_SHARD_KEY";
private final long TurnOffAndBalanceInterval = 30 * 60 * 1000; //机器下线30后才能进行动态平衡
private final long BalanceLeaderInterval = 30 * 1000; // leader平衡时间间隔
// The dynamic balancing can only be carried out after the machine is offline for 30 minutes
private final long TurnOffAndBalanceInterval = 30 * 60 * 1000;
// leader balances the time interval
private final long BalanceLeaderInterval = 30 * 1000;
private final PDConfig pdConfig;
private final long clusterStartTime; //
private final StoreNodeService storeService;
@ -65,14 +68,12 @@ public class TaskScheduleService {
private final StoreMonitorDataService storeMonitorDataService;
private final KvService kvService;
private final LogService logService;
// 先按照value排序再按照key排序
private final Comparator<KVPair<Long, Integer>> kvPairComparatorAsc = (o1, o2) -> {
if (o1.getValue() == o2.getValue()) {
return o1.getKey().compareTo(o2.getKey());
}
return o1.getValue().compareTo(o2.getValue());
};
// 先按照value排序(倒序)再按照key排序(升序
private final Comparator<KVPair<Long, Integer>> kvPairComparatorDesc = (o1, o2) -> {
if (o1.getValue() == o2.getValue()) {
return o2.getKey().compareTo(o1.getKey());
@ -157,7 +158,7 @@ public class TaskScheduleService {
if (status == Metapb.StoreState.Up) {
executor.schedule(() -> {
try { //store 上线后延时1分钟进行leader平衡
try {
balancePartitionLeader(false);
} catch (PDException e) {
log.error("exception {}", e);
@ -190,7 +191,7 @@ public class TaskScheduleService {
}
/**
* 巡查所有的store检查是否在线存储空间是否充足
* Inspect all stores to see if they are online and have enough storage space
*/
public List<Metapb.Store> patrolStores() throws PDException {
if (!isLeader()) {
@ -198,7 +199,7 @@ public class TaskScheduleService {
}
List<Metapb.Store> changedStores = new ArrayList<>();
// 检查store在线状态
// Check your store online status
List<Metapb.Store> stores = storeService.getStores("");
Map<Long, Metapb.Store> activeStores = storeService.getActiveStores("")
.stream().collect(
@ -208,7 +209,7 @@ public class TaskScheduleService {
if ((store.getState() == Metapb.StoreState.Up
|| store.getState() == Metapb.StoreState.Unknown)
&& !activeStores.containsKey(store.getId())) {
// 不在线修改状态为离线
// If you are not online, the modification status is offline
changeStore = Metapb.Store.newBuilder(store)
.setState(Metapb.StoreState.Offline)
.build();
@ -220,8 +221,8 @@ public class TaskScheduleService {
pdConfig.getStore().getMaxDownTime() * 1000) &&
(System.currentTimeMillis() - clusterStartTime >
pdConfig.getStore().getMaxDownTime() * 1000))) {
//手工修改为下线或者离线达到时长
// 修改状态为关机, 增加 checkStoreCanOffline 检测
// Manually change the parameter to Offline or Offline Duration
// Modify the status to shut down and increase checkStoreCanOffline detect
if (storeService.checkStoreCanOffline(store)) {
changeStore = Metapb.Store.newBuilder(store)
.setState(Metapb.StoreState.Tombstone).build();
@ -239,22 +240,22 @@ public class TaskScheduleService {
}
/**
* 巡查所有的分区检查副本数是否正确
* Inspect all partitions to check whether the number of replicas is correct and the number
* of replicas in the shard group
*/
public List<Metapb.Partition> patrolPartitions() throws PDException {
if (!isLeader()) {
return null;
}
// 副本数不一致重新分配副本
// If the number of replicas is inconsistent, reallocate replicas
for (Metapb.ShardGroup group : storeService.getShardGroups()) {
if (group.getShardsCount() != pdConfig.getPartition().getShardCount()) {
storeService.reallocShards(group);
// 避免后面的 balance partition shard 马上执行.
kvService.put(BALANCE_SHARD_KEY, "DOING", 180 * 1000);
}
}
//检查shard是否在线
// Check if the shard is online.
Map<Long, Metapb.Store> tombStores = storeService.getTombStores().stream().collect(
Collectors.toMap(Metapb.Store::getId, t -> t));
@ -277,8 +278,8 @@ public class TaskScheduleService {
}
/**
* 在Store之间平衡分区的数量
* 机器转为UP半小时后才能进行动态平衡
* Balance the number of partitions between stores
* It takes half an hour for the machine to turn to UP before it can be dynamically balanced
*/
public synchronized Map<Integer, KVPair<Long, Long>> balancePartitionShard() throws
PDException {
@ -289,7 +290,7 @@ public class TaskScheduleService {
}
if (System.currentTimeMillis() - lastStoreTurnoffTime < TurnOffAndBalanceInterval) {
return null;//机器下线半小时后才能进行动态平衡
return null;
}
int activeStores = storeService.getActiveStores().size();
@ -298,8 +299,6 @@ public class TaskScheduleService {
return null;
}
// 避免频繁调用. (当改变副本数需要调整shard list此时又需要平衡分区会发送重复的指令造成结果不可预料
// 严重会删除掉分区.
if (Objects.equals(kvService.get(BALANCE_SHARD_KEY), "DOING")) {
return null;
}
@ -309,20 +308,18 @@ public class TaskScheduleService {
int averageCount = totalShards / activeStores;
int remainder = totalShards % activeStores;
// 统计每个store上分区, StoreId ->PartitionID, ShardRole
// Count the partitions on each store, StoreId -> PartitionID, ShardRole
Map<Long, Map<Integer, Metapb.ShardRole>> partitionMap = new HashMap<>();
storeService.getActiveStores().forEach(store -> {
partitionMap.put(store.getId(), new HashMap<>());
});
// 如果是leaner 说明迁移正在进行不要重复提交任务
AtomicReference<Boolean> isLeaner = new AtomicReference<>(false);
partitionService.getPartitions().forEach(partition -> {
try {
storeService.getShardList(partition.getId()).forEach(shard -> {
Long storeId = shard.getStoreId();
// 判断每个shard为leaner或者状态非正常状态
if (shard.getRole() == Metapb.ShardRole.Learner
|| partition.getState() != Metapb.PartitionState.PState_Normal) {
isLeaner.set(true);
@ -342,24 +339,25 @@ public class TaskScheduleService {
return null;
}
// 按照shard数量由高到低排序store
// According to shard sort the quantity from highest to lowest
List<KVPair<Long, Integer>> sortedList = new ArrayList<>();
partitionMap.forEach((storeId, shards) -> {
sortedList.add(new KVPair(storeId, shards.size()));
});
// 由大到小排序的list
sortedList.sort(((o1, o2) -> o2.getValue().compareTo(o1.getValue())));
// 最大堆
// The largest heap, moved in store -> shard count
PriorityQueue<KVPair<Long, Integer>> maxHeap = new PriorityQueue<>(sortedList.size(),
(o1, o2) -> o2.getValue()
.compareTo(
o1.getValue()));
// 各个副本的 committedIndex
// of individual copies committedIndex
Map<Integer, Map<Long, Long>> committedIndexMap = partitionService.getCommittedIndexStats();
// 分区ID --> 源StoreID,目标StoreID
// Partition ID -->source StoreID, target StoreID
Map<Integer, KVPair<Long, Long>> movedPartitions = new HashMap<>();
// 移除多余的shard, 按照shards由多到少的顺序遍历store余数remainder优先给shards多的store分配减少迁移的概率
// Remove redundant shards, traverse the stores in the order of shards from most to
// least, and the remainder is allocated to the store with more shards first, reducing
// the probability of migration
for (int index = 0; index < sortedList.size(); index++) {
long storeId = sortedList.get(index).getKey();
if (!partitionMap.containsKey(storeId)) {
@ -368,7 +366,8 @@ public class TaskScheduleService {
}
Map<Integer, Metapb.ShardRole> shards = partitionMap.get(storeId);
int targetCount = index < remainder ? averageCount + 1 : averageCount;
// 移除多余的shard, 添加源StoreID. 非Leader并且该分区唯一
// Remove the redundant shards and add the source StoreID. is not a leader, and the
// partition is unique
if (shards.size() > targetCount) {
int movedCount = shards.size() - targetCount;
log.info(
@ -420,7 +419,7 @@ public class TaskScheduleService {
if (partitionMap.containsKey(destStoreId)) {
destContains = partitionMap.get(destStoreId).containsKey(partitionId);
}
// 如果目的store已经包含了该partition则取一下store
// If the destination store already contains the partition, take the store
if (!destContains) {
moveEntry.getValue().setValue(pair.getKey());
log.info(
@ -442,9 +441,9 @@ public class TaskScheduleService {
kvService.put(BALANCE_SHARD_KEY, "DOING", 180 * 1000);
// 开始迁移
// Start the migration
movedPartitions.forEach((partId, storePair) -> {
// 源和目标storeID都不为0
// Neither the source nor destination storeID is 0
if (storePair.getKey() > 0 && storePair.getValue() > 0) {
partitionService.movePartitionsShard(partId, storePair.getKey(),
storePair.getValue());
@ -457,7 +456,7 @@ public class TaskScheduleService {
}
/**
* 在Store之间平衡分区的Leader的数量
* Balance the number of leaders of partitions between stores
*/
public synchronized Map<Integer, Long> balancePartitionLeader(boolean immediately) throws
PDException {
@ -475,13 +474,12 @@ public class TaskScheduleService {
List<Metapb.ShardGroup> shardGroups = storeService.getShardGroups();
// 分裂或者缩容任务的时候退出
// When a task is split or scaled-in, it is exited
var taskMeta = storeService.getTaskInfoMeta();
if (taskMeta.hasSplitTaskDoing() || taskMeta.hasMoveTaskDoing()) {
throw new PDException(1001, "split or combine task is processing, please try later!");
}
// 数据迁移的时候退出
if (Objects.equals(kvService.get(BALANCE_SHARD_KEY), "DOING")) {
throw new PDException(1001, "balance shard is processing, please try later!");
}
@ -502,7 +500,6 @@ public class TaskScheduleService {
log.info("balancePartitionLeader, shard group size: {}, by store: {}", shardGroups.size(),
storeShardCount);
// 按照 target count store id稳定排序
PriorityQueue<KVPair<Long, Integer>> targetCount =
new PriorityQueue<>(kvPairComparatorDesc);
@ -520,7 +517,6 @@ public class TaskScheduleService {
targetCount.add(new KVPair<>(sortedGroups.get(i).getKey(), v));
sum += v;
}
// 最后一个, 除不尽的情况保证总数正确
targetCount.add(new KVPair<>(sortedGroups.get(sortedGroups.size() - 1).getKey(),
shardGroups.size() - sum));
log.info("target count: {}", targetCount);
@ -529,7 +525,8 @@ public class TaskScheduleService {
var map = group.getShardsList().stream()
.collect(Collectors.toMap(Metapb.Shard::getStoreId, shard -> shard));
var tmpList = new ArrayList<KVPair<Long, Integer>>();
// store比较多的情况可能不包含对应的store id. 则先将不符合的store保存到临时列表直到找到一个合适的store
// If there are many stores, they may not contain the corresponding store ID. Save
// the non-compliant stores to the temporary list until you find a suitable store
while (!targetCount.isEmpty()) {
var pair = targetCount.poll();
var storeId = pair.getKey();
@ -549,7 +546,7 @@ public class TaskScheduleService {
pair.setValue(pair.getValue() - 1);
tmpList.add(pair);
}
// 找到了则处理完成
// If it is found, the processing is complete
break;
} else {
tmpList.add(pair);
@ -574,14 +571,13 @@ public class TaskScheduleService {
shardMap.forEach((storeId, committedIndex) -> {
sortedList.add(committedIndex);
});
// 由大到小排序的list
sortedList.sort(Comparator.reverseOrder());
maxGap = sortedList.get(0) - sortedList.get(sortedList.size() - 1);
return maxGap;
}
/**
* 执行分区分裂分为自动分裂和手工分裂
* Perform partition splitting, which is divided into automatic splitting and manual splitting
*
* @return
* @throws PDException
@ -602,9 +598,11 @@ public class TaskScheduleService {
}
/**
* 自动进行分区分裂每个store达到最大分区数量
* 执行条件
* 分裂后每台机器分区数量少于partition.max-partitions-per-store
* Partition splitting is performed automatically, and each store reaches the maximum number
* of partitions
* execution conditions
* The number of partitions per machine after the split is less than partition
* .max-partitions-per-store
*
* @throws PDException
*/
@ -623,11 +621,7 @@ public class TaskScheduleService {
}
}
//For TEST
// pdConfig.getPartition().setMaxShardsPerStore(pdConfig.getPartition()
// .getMaxShardsPerStore()*2);
// 计算集群能能支持的最大split count
// The maximum split count that a compute cluster can support
int splitCount = pdConfig.getPartition().getMaxShardsPerStore() *
storeService.getActiveStores().size() /
(storeService.getShardGroups().size() *
@ -640,12 +634,12 @@ public class TaskScheduleService {
+ pdConfig.getPartition().getMaxShardsPerStore());
}
// 每store未达最大分区数进行分裂
// If the maximum number of partitions per store is not reached, it will be split
log.info("Start to split partitions..., split count = {}", splitCount);
// 设置集群状态为下线
// Set the cluster status to Offline
storeService.updateClusterStatus(Metapb.ClusterState.Cluster_Offline);
// 修改默认分区数量
// Modify the default number of partitions
// pdConfig.getConfigService().setPartitionCount(storeService.getShardGroups().size() *
// splitCount);
@ -658,8 +652,9 @@ public class TaskScheduleService {
}
/**
* Store汇报任务状态
* 分区状态发生改变重新计算分区所在的ShardGroup图和整个集群的状态
* Store reports the status of the task
* The state of the partition changes, and the state of the ShardGroup, graph, and the entire
* cluster where the partition resides
*
* @param task
*/
@ -684,7 +679,7 @@ public class TaskScheduleService {
}
/**
* 对rocksdb进行compaction
* Compaction on rocksdb
*
* @throws PDException
*/
@ -702,39 +697,44 @@ public class TaskScheduleService {
}
/**
* 判断是否能把一个store的分区全部迁出给出判断结果和迁移方案
* Determine whether all partitions of a store can be migrated out, and give the judgment
* result and migration plan
*/
public Map<String, Object> canAllPartitionsMovedOut(Metapb.Store sourceStore) throws
PDException {
if (!isLeader()) {
return null;
}
// 分析一个store上面的分区是否可以完全迁出
// Analyze whether the partition on a store can be completely checked out
Map<String, Object> resultMap = new HashMap<>();
// 定义对象用于保存源store上面的分区 StoreId ->PartitionID, ShardRole
// The definition object is used to hold the partition above the source store StoreId
// ->PartitionID, ShardRole
Map<Long, Map<Integer, Metapb.ShardRole>> sourcePartitionMap = new HashMap<>();
sourcePartitionMap.put(sourceStore.getId(), new HashMap<>());
// 定义对象用于保存其他活跃store上面的分区 StoreId ->PartitionID, ShardRole
// The definition object is used to hold the partition above the other active stores
// StoreId ->PartitionID, ShardRole
Map<Long, Map<Integer, Metapb.ShardRole>> otherPartitionMap = new HashMap<>();
Map<Long, Long> availableDiskSpace = new HashMap<>(); // 每个store剩余的磁盘空间
Map<Integer, Long> partitionDataSize = new HashMap<>(); // 记录待迁移的分区的数据量
// The amount of disk space remaining for each store
Map<Long, Long> availableDiskSpace = new HashMap<>();
// Record the amount of data in the partition to be migrated
Map<Integer, Long> partitionDataSize = new HashMap<>();
storeService.getActiveStores().forEach(store -> {
if (store.getId() != sourceStore.getId()) {
otherPartitionMap.put(store.getId(), new HashMap<>());
// 记录其他store的剩余的磁盘空间, 单位为Byte
// Records the remaining disk space of other stores, in bytes
availableDiskSpace.put(store.getId(), store.getStats().getAvailable());
} else {
resultMap.put("current_store_is_online", true);
}
});
// 统计待迁移的分区的数据大小 (从storeStats中统计单位为KB)
// Count the size of the partition to be migrated (from storeStats in KB)
for (Metapb.GraphStats graphStats : sourceStore.getStats().getGraphStatsList()) {
partitionDataSize.put(graphStats.getPartitionId(),
partitionDataSize.getOrDefault(graphStats.getPartitionId(), 0L)
+ graphStats.getApproximateSize());
}
// 给sourcePartitionMap otherPartitionMap赋值
// Assign values to sourcePartitionMap and otherPartitionMap
partitionService.getPartitions().forEach(partition -> {
try {
storeService.getShardList(partition.getId()).forEach(shard -> {
@ -752,13 +752,14 @@ public class TaskScheduleService {
throw new RuntimeException(e);
}
});
// 统计待移除的分区即源store上面的所有分区
// Count the partitions to be removed: all partitions on the source store
Map<Integer, KVPair<Long, Long>> movedPartitions = new HashMap<>();
for (Map.Entry<Integer, Metapb.ShardRole> entry : sourcePartitionMap.get(
sourceStore.getId()).entrySet()) {
movedPartitions.put(entry.getKey(), new KVPair<>(sourceStore.getId(), 0L));
}
// 统计其他store的分区数量, 用小顶堆保存以便始终把分区数量较少的store优先考虑
// Count the number of partitions of other stores and save them with a small top heap, so
// that stores with fewer partitions are always prioritized
PriorityQueue<KVPair<Long, Integer>> minHeap = new PriorityQueue<>(otherPartitionMap.size(),
(o1, o2) -> o1.getValue()
.compareTo(
@ -766,24 +767,28 @@ public class TaskScheduleService {
otherPartitionMap.forEach((storeId, shards) -> {
minHeap.add(new KVPair(storeId, shards.size()));
});
// 遍历待迁移的分区,优先迁移到分区比较少的store
// Traverse the partitions to be migrated, and prioritize the migration to the store with
// fewer partitions
Iterator<Map.Entry<Integer, KVPair<Long, Long>>> moveIterator =
movedPartitions.entrySet().iterator();
while (moveIterator.hasNext()) {
Map.Entry<Integer, KVPair<Long, Long>> moveEntry = moveIterator.next();
int partitionId = moveEntry.getKey();
List<KVPair<Long, Integer>> tmpList = new ArrayList<>(); // 记录已经弹出优先队列的元素
// Record the elements that have popped up in the priority
List<KVPair<Long, Integer>> tmpList = new ArrayList<>();
while (minHeap.size() > 0) {
KVPair<Long, Integer> pair = minHeap.poll(); //弹出首个元素
KVPair<Long, Integer> pair = minHeap.poll(); // The first element pops up
long storeId = pair.getKey();
int partitionCount = pair.getValue();
Map<Integer, Metapb.ShardRole> shards = otherPartitionMap.get(storeId);
final int unitRate = 1024; // 平衡不同存储单位的进率
final int unitRate = 1024; // Balance the feed rate of different storage units
if ((!shards.containsKey(partitionId)) && (
availableDiskSpace.getOrDefault(storeId, 0L) / unitRate >=
partitionDataSize.getOrDefault(partitionId, 0L))) {
// 如果目标store上面不包含该分区且目标store剩余空间能容纳该分区则进行迁移
moveEntry.getValue().setValue(storeId); //设置移动的目标store
// If the partition is not included on the destination store and the
// remaining space of the destination store can accommodate the partition,
// the migration is performed
moveEntry.getValue().setValue(storeId); // Set the target store for the move
log.info("plan to move partition {} to store {}, " +
"available disk space {}, current partitionSize:{}",
partitionId,
@ -791,12 +796,12 @@ public class TaskScheduleService {
availableDiskSpace.getOrDefault(storeId, 0L) / unitRate,
partitionDataSize.getOrDefault(partitionId, 0L)
);
// 更新该store预期的剩余空间
// Update the expected remaining space for the store
availableDiskSpace.put(storeId, availableDiskSpace.getOrDefault(storeId, 0L)
- partitionDataSize.getOrDefault(partitionId,
0L) *
unitRate);
// 更新统计变量中该store的分区数量
// Update the number of partitions for that store in the stat variable
partitionCount += 1;
pair.setValue(partitionCount);
tmpList.add(pair);
@ -807,7 +812,7 @@ public class TaskScheduleService {
}
minHeap.addAll(tmpList);
}
//检查是否未存在未分配目标store的分区
// Check that there are no partitions that don't have a target store assigned
List<Integer> remainPartitions = new ArrayList<>();
movedPartitions.forEach((partId, storePair) -> {
if (storePair.getValue() == 0L) {
@ -830,10 +835,10 @@ public class TaskScheduleService {
if (!isLeader()) {
return null;
}
// 开始迁移
// Start the migration
log.info("begin move partitions:");
movedPartitions.forEach((partId, storePair) -> {
// 源和目标storeID都不为0
// Neither the source nor destination storeID is 0
if (storePair.getKey() > 0 && storePair.getValue() > 0) {
partitionService.movePartitionsShard(partId, storePair.getKey(),
storePair.getValue());

View File

@ -33,23 +33,26 @@ import org.springframework.stereotype.Component;
import lombok.Data;
/**
* PD配置文件
* PD profile
*/
@Data
@Component
public class PDConfig {
// cluster ID
@Value("${pd.cluster_id:1}")
private long clusterId; // 集群ID
private long clusterId;
// The patrol task interval
@Value("${pd.patrol-interval:300}")
private long patrolInterval = 300; //巡查任务时间间隔
private long patrolInterval = 300;
@Value("${pd.data-path}")
private String dataPath;
@Value("${pd.initial-store-count:3}")
private int minStoreCount;
// 初始store列表该列表内的store自动激活
// The initial store list, within which the store is automatically activated
// format: store_addresss, store_address, store_address/group_id, store_address/group_id
@Value("${pd.initial-store-list: ''}")
private String initialStoreList;
@Value("${grpc.host}")
@ -84,8 +87,8 @@ public class PDConfig {
}
/**
* 初始分区数量
* Store数量 * 每Store最大副本数 /每分区副本数
* The initial number of partitions
* Number of Stores * Maximum number of replicas per Store / Number of replicas per partition
*
* @return
*/
@ -144,7 +147,7 @@ public class PDConfig {
private int port;
@Value("${pd.cluster_id:1}")
private long clusterId; // 集群ID
private long clusterId;
@Value("${grpc.port}")
private int grpcPort;
@ -157,7 +160,7 @@ public class PDConfig {
@Configuration
public class Store {
// store 心跳超时时间
// store Heartbeat timeout
@Value("${store.keepAlive-timeout:300}")
private long keepAliveTimeout = 300;
@Value("${store.max-down-time:1800}")
@ -249,11 +252,10 @@ public class PDConfig {
private int totalCount = 0;
// 每个Store最大副本数
// Maximum number of replicas per Store
@Value("${partition.store-max-shard-count:24}")
private int maxShardsPerStore = 24;
// 默认分副本数量
@Value("${partition.default-shard-count:3}")
private int shardCount = 3;
@ -273,7 +275,8 @@ public class PDConfig {
@Configuration
public class Discovery {
// 客户端注册后无心跳最长次数超过后之前的注册信息会被删除
// After the client registers, the maximum number of heartbeats is not reached, and after
// that, the previous registration information will be deleted
@Value("${discovery.heartbeat-try-count:3}")
private int heartbeatOutTimes = 3;
}

View File

@ -34,7 +34,7 @@ public class ConfigMetaStore extends MetadataRocksDBStore {
}
/**
* 更新图空间存储状态信息
* Update the storage status of the graph space
*
* @param
*/

View File

@ -35,7 +35,7 @@ import com.caucho.hessian.io.Hessian2Output;
import lombok.extern.slf4j.Slf4j;
/**
* 自增id的实现类
* Implementation class for auto-increment ID.
*/
@Slf4j
public class IdMetaStore extends MetadataRocksDBStore {
@ -46,7 +46,7 @@ public class IdMetaStore extends MetadataRocksDBStore {
private static final String CID_DEL_SLOT_PREFIX = "@CID_DEL_SLOT@";
private static final String SEPARATOR = "@";
private static final ConcurrentHashMap<String, Object> SEQUENCES = new ConcurrentHashMap<>();
private static long CID_DEL_TIMEOUT = 24 * 3600 * 1000;
private static final long CID_DEL_TIMEOUT = 24 * 3600 * 1000;
private final long clusterId;
public IdMetaStore(PDConfig pdConfig) {
@ -67,7 +67,7 @@ public class IdMetaStore extends MetadataRocksDBStore {
}
/**
* 获取自增id
* Get auto-increment ID.
*
* @param key
* @param delta
@ -108,17 +108,19 @@ public class IdMetaStore extends MetadataRocksDBStore {
}
/**
* 在删除name标识的cid的24小时内重复申请同一个name的cid保持同一值
* 如此设计为了防止缓存的不一致造成数据错误
* Within 24 hours of deleting the cid identified by the name,
* repeat applying for the same name's cid to keep the same value.
* This design is to prevent inconsistent caching, causing data errors.
*
* @param key
* @param name cid 标识
* @param name cid identifier
* @param max
* @return
* @throws PDException
*/
public long getCId(String key, String name, long max) throws PDException {
// 检测是否有过期的cid删除图的频率比较低此处对性能影响不大
// Check for expired cids to delete. The frequency of deleting graphs is relatively low,
// so this has little performance impact.
byte[] delKeyPrefix = (CID_DEL_SLOT_PREFIX +
key + SEPARATOR).getBytes(Charset.defaultCharset());
synchronized (this) {
@ -136,11 +138,11 @@ public class IdMetaStore extends MetadataRocksDBStore {
}
});
// 从延时删除队列恢复Key
// Restore key from delayed deletion queue
byte[] cidDelayKey = getCIDDelayKey(key, name);
byte[] value = getOne(cidDelayKey);
if (value != null) {
// 从延迟删除队列删除
// Remove from delayed deletion queue
remove(cidDelayKey);
return ((long[]) deserialize(value))[0];
} else {
@ -150,7 +152,7 @@ public class IdMetaStore extends MetadataRocksDBStore {
}
/**
* 添加到删除队列延后删除
* Add to the deletion queue for delayed deletion.
*/
public long delCIdDelay(String key, String name, long cid) throws PDException {
byte[] delKey = getCIDDelayKey(key, name);
@ -159,10 +161,12 @@ public class IdMetaStore extends MetadataRocksDBStore {
}
/**
* 获取自增循环不重复id, 达到上限后从0开始自增
* Get an auto-incrementing cyclic non-repeating ID. When the upper limit is reached, it
* starts from 0 again.
*
* @param key
* @param max id上限达到该值后重新从0开始自增
* @param max the upper limit of the ID. After reaching this value, it starts incrementing
* from 0 again.
* @return
* @throws PDException
*/
@ -173,7 +177,7 @@ public class IdMetaStore extends MetadataRocksDBStore {
byte[] bs = getOne(keyBs);
long current = bs != null ? bytesToLong(bs) : 0L;
long last = current == 0 ? max - 1 : current - 1;
{ // 查找一个未使用的cid
{ // Find an unused cid
List<KV> kvs = scanRange(genCIDSlotKey(key, current), genCIDSlotKey(key, max));
for (KV kv : kvs) {
if (current == bytesToLong(kv.getValue())) {
@ -219,7 +223,7 @@ public class IdMetaStore extends MetadataRocksDBStore {
}
/**
* 删除一个循环id释放id值
* Delete a cyclic ID and release its value.
*
* @param key
* @param cid

View File

@ -24,7 +24,7 @@ import org.apache.hugegraph.pd.store.HgKVStoreImpl;
import org.apache.hugegraph.pd.store.RaftKVStore;
/**
* 存储工厂类创建相关对象的存储类
* Storage Factory class to create a storage class for related objects
*/
public class MetadataFactory {

View File

@ -108,7 +108,6 @@ public class MetadataRocksDBStore extends MetadataStoreBase {
@Override
public List<KV> scanPrefix(byte[] prefix) throws PDException {
//TODO 使用rocksdb 前缀查询
try {
return this.store.scanPrefix(prefix);
} catch (Exception e) {

View File

@ -30,7 +30,7 @@ import com.google.protobuf.Parser;
public abstract class MetadataStoreBase {
// public long timeout = 3; // 请求超时时间默认三秒
// public long timeout = 3;
public abstract byte[] getOne(byte[] key) throws PDException;
@ -39,9 +39,8 @@ public abstract class MetadataStoreBase {
public abstract void put(byte[] key, byte[] value) throws PDException;
/**
* 带有过期时间的put
* A put with an expiration time
*/
public abstract void putWithTTL(byte[] key,
byte[] value,
long ttl) throws PDException;
@ -57,7 +56,7 @@ public abstract class MetadataStoreBase {
public abstract void removeWithTTL(byte[] key) throws PDException;
/**
* 前缀查询
* Prefix queries
*
* @param prefix
* @return
@ -66,13 +65,12 @@ public abstract class MetadataStoreBase {
public abstract List<KV> scanPrefix(byte[] prefix) throws PDException;
/**
* 前缀查询
* Prefix queries
*
* @param prefix
* @return
* @throws PDException
*/
public abstract <E> List<E> scanPrefix(Parser<E> parser, byte[] prefix) throws PDException;
public abstract List<KV> scanRange(byte[] start, byte[] end) throws PDException;
@ -81,13 +79,12 @@ public abstract class MetadataStoreBase {
PDException;
/**
* 检查Key是否存在
* Check if the key exists
*
* @param key
* @return
* @throws PDException
*/
public abstract boolean containsKey(byte[] key) throws PDException;
public abstract long remove(byte[] key) throws PDException;

View File

@ -28,7 +28,7 @@ import org.apache.hugegraph.pd.grpc.Metapb;
import lombok.extern.slf4j.Slf4j;
/**
* 分区信息管理
* Partition information management
*/
@Slf4j
public class PartitionMeta extends MetadataRocksDBStore {
@ -46,7 +46,7 @@ public class PartitionMeta extends MetadataRocksDBStore {
}
/**
* 初始化加载所有的分区
* Initialize, load all partitions
*/
public void init() throws PDException {
loadShardGroups();
@ -69,7 +69,8 @@ public class PartitionMeta extends MetadataRocksDBStore {
}
/**
* partition shard group分开存储再init的时候需要加载进来
* The partition and shard group are stored separately, and when they are init, they need to
* be loaded
*
* @throws PDException
*/
@ -89,7 +90,7 @@ public class PartitionMeta extends MetadataRocksDBStore {
}
/**
* 根据id查找分区 (先从缓存找再到数据库中找
* Find partitions by ID (first from the cache, then from the database)
*
* @param graphName
* @param partId
@ -124,7 +125,7 @@ public class PartitionMeta extends MetadataRocksDBStore {
}
/**
* 根据code查找分区
* Find partitions based on code
*/
public Metapb.Partition getPartitionByCode(String graphName, long code) throws PDException {
var pair = cache.getPartitionByCode(graphName, code);
@ -144,14 +145,12 @@ public class PartitionMeta extends MetadataRocksDBStore {
partitionCount = pdConfig.getPartition().getTotalCount();
}
// 管理图只有一个分区
if (graphName.endsWith("/s") || graphName.endsWith("/m")) {
partitionCount = 1;
}
Metapb.Graph graph = cache.getGraph(graphName);
if (graph == null) {
// 保存图信息
graph = Metapb.Graph.newBuilder()
.setGraphName(graphName)
.setPartitionCount(partitionCount)
@ -163,7 +162,7 @@ public class PartitionMeta extends MetadataRocksDBStore {
}
/**
* 保存分区信息
* Save the partition information
*
* @param partition
* @return
@ -179,14 +178,6 @@ public class PartitionMeta extends MetadataRocksDBStore {
return partition;
}
/**
* 检查数据库是否存在对应的图不存在则创建
* 更新partition的 version, conf version shard list
*
* @param partition
* @return
* @throws PDException
*/
public Metapb.Partition updateShardList(Metapb.Partition partition) throws PDException {
if (!cache.hasGraph(partition.getGraphName())) {
getAndCreateGraph(partition.getGraphName());
@ -205,7 +196,7 @@ public class PartitionMeta extends MetadataRocksDBStore {
}
/**
* 删除所有分区
* Delete all partitions
*/
public long removeAllPartitions(String graphName) throws PDException {
cache.removeAll(graphName);
@ -227,7 +218,7 @@ public class PartitionMeta extends MetadataRocksDBStore {
}
/**
* 获取分区状态
* Get the partition status
*/
public Metapb.PartitionStats getPartitionStats(String graphName, int id) throws PDException {
byte[] prefix = MetadataKeyHelper.getPartitionStatusKey(graphName, id);
@ -235,7 +226,7 @@ public class PartitionMeta extends MetadataRocksDBStore {
}
/**
* 获取分区状态
* Get the partition status
*/
public List<Metapb.PartitionStats> getPartitionStats(String graphName) throws PDException {
byte[] prefix = MetadataKeyHelper.getPartitionStatusPrefixKey(graphName);
@ -243,7 +234,7 @@ public class PartitionMeta extends MetadataRocksDBStore {
}
/**
* 更新图信息
* Update the diagram information
*
* @param graph
* @return
@ -251,7 +242,6 @@ public class PartitionMeta extends MetadataRocksDBStore {
public Metapb.Graph updateGraph(Metapb.Graph graph) throws PDException {
log.info("updateGraph {}", graph);
byte[] key = MetadataKeyHelper.getGraphKey(graph.getGraphName());
// 保存图信息
put(key, graph.toByteString().toByteArray());
cache.updateGraph(graph);
return graph;
@ -281,7 +271,7 @@ public class PartitionMeta extends MetadataRocksDBStore {
}
/**
* 删除图并删除图id
* Delete the diagram and delete the diagram ID
*/
public long removeGraph(String graphName) throws PDException {
byte[] key = MetadataKeyHelper.getGraphKey(graphName);

View File

@ -28,7 +28,7 @@ import org.apache.hugegraph.pd.grpc.Metapb;
import lombok.extern.slf4j.Slf4j;
/**
* Store信息存储
* Store information storage
*/
@Slf4j
public class StoreInfoMeta extends MetadataRocksDBStore {
@ -55,7 +55,7 @@ public class StoreInfoMeta extends MetadataRocksDBStore {
}
/**
* 更新Store信息
* Update the Store information
*
* @param store
* @throws PDException
@ -66,7 +66,7 @@ public class StoreInfoMeta extends MetadataRocksDBStore {
}
/**
* 更新Store的存活状态
* Update the survivability status of the store
*
* @param store
*/
@ -87,7 +87,7 @@ public class StoreInfoMeta extends MetadataRocksDBStore {
}
/**
* 获取所有的store
* Get all the stores
*
* @param graphName
* @return
@ -99,9 +99,8 @@ public class StoreInfoMeta extends MetadataRocksDBStore {
}
/**
* 获取活跃的Store
* Get an active store
*
* @param graphName
* @return
* @throws PDException
*/
@ -120,7 +119,7 @@ public class StoreInfoMeta extends MetadataRocksDBStore {
}
/**
* 检查storeid是否存在
* Check whether the storeID exists
*
* @param storeId
* @return
@ -131,7 +130,7 @@ public class StoreInfoMeta extends MetadataRocksDBStore {
}
/**
* 更新存储状态信息
* Update the storage status information
*
* @param storeStats
*/
@ -185,7 +184,7 @@ public class StoreInfoMeta extends MetadataRocksDBStore {
}
/**
* @return store及状态信息
* @return store and status information
* @throws PDException
*/
public List<Metapb.Store> getStoreStatus(boolean isActive) throws PDException {

View File

@ -27,7 +27,7 @@ import org.apache.hugegraph.pd.grpc.pulse.MovePartition;
import org.apache.hugegraph.pd.grpc.pulse.SplitPartition;
/**
* 任务管理
* Task management
*/
public class TaskInfoMeta extends MetadataRocksDBStore {
@ -36,7 +36,7 @@ public class TaskInfoMeta extends MetadataRocksDBStore {
}
/**
* 添加分区分裂任务
* Add a partition splitting task
*/
public void addSplitTask(int groupID, Metapb.Partition partition, SplitPartition splitPartition)
throws PDException {
@ -115,9 +115,9 @@ public class TaskInfoMeta extends MetadataRocksDBStore {
}
/**
* 按照prefix删除迁移任务一次分组的
* Delete the migration task by prefixing it and group them all at once
*
* @param graphName 图名称
* @param graphName graphName
* @throws PDException io error
*/
public void removeMoveTaskPrefix(String graphName) throws PDException {

View File

@ -55,7 +55,9 @@ public class KVOperation {
private byte[] key;
private byte[] value;
private Object attach; // 原始对象用于本机处理减少一次反序列化操作
// Raw object, used for native processing, reducing the number of deserialization
// operations
private Object attach;
private Object arg;
private byte op;

View File

@ -92,25 +92,25 @@ public class RaftEngine {
log.error("The RaftEngine parameter is incorrect." +
" When RAFT is enabled, the number of peers " + "cannot be less than 3");
}
// 设置 Node 参数包括日志存储路径和状态机实例
// Set node parameters, including the log storage path and state machine instance
NodeOptions nodeOptions = new NodeOptions();
nodeOptions.setFsm(stateMachine);
nodeOptions.setEnableMetrics(true);
// 日志路径
// Log path
nodeOptions.setLogUri(raftPath + "/log");
// raft 元数据路径
// raft metadata path
nodeOptions.setRaftMetaUri(raftPath + "/meta");
// 快照路径
// Snapshot path
nodeOptions.setSnapshotUri(raftPath + "/snapshot");
// 初始集群
// Initial cluster
nodeOptions.setInitialConf(initConf);
// 快照时间间隔
// Snapshot interval
nodeOptions.setSnapshotIntervalSecs(config.getSnapshotInterval());
nodeOptions.setRpcConnectTimeoutMs(config.getRpcTimeout());
nodeOptions.setRpcDefaultTimeout(config.getRpcTimeout());
nodeOptions.setRpcInstallSnapshotTimeout(config.getRpcTimeout());
// 设置 raft 配置
// Set the raft configuration
RaftOptions raftOptions = nodeOptions.getRaftOptions();
nodeOptions.setEnableMetrics(true);
@ -118,7 +118,7 @@ public class RaftEngine {
final PeerId serverId = JRaftUtils.getPeerId(config.getAddress());
rpcServer = createRaftRpcServer(config.getAddress());
// 构建 raft 组并启动 raft
// construct raft group and start raft
this.raftGroupService =
new RaftGroupService(groupId, serverId, nodeOptions, rpcServer, true);
this.raftNode = raftGroupService.start(false);
@ -128,7 +128,7 @@ public class RaftEngine {
}
/**
* 创建 raft rpc server用于 pd 之间通讯
* Create a Raft RPC Server for communication between PDs
*/
private RpcServer createRaftRpcServer(String raftAddr) {
Endpoint endpoint = JRaftUtils.getEndPoint(raftAddr);
@ -164,7 +164,7 @@ public class RaftEngine {
}
/**
* 添加 Raft 任务grpc 通过该接口给 raft 发送数据
* Add a raft task, and grpc sends data to raft through this interface
*/
public void addTask(Task task) {
if (!isLeader()) {
@ -193,7 +193,7 @@ public class RaftEngine {
}
/**
* leader 发消息获取 grpc 地址
* Send a message to the leader to get the grpc address;
*/
public String getLeaderGrpcAddress() throws ExecutionException, InterruptedException {
if (isLeader()) {

View File

@ -46,7 +46,7 @@ public class RaftRpcClient {
}
/**
* 请求快照
* Request a snapshot
*/
public CompletableFuture<RaftRpcProcessor.GetMemberResponse>
getGrpcAddress(final String address) {

View File

@ -237,7 +237,6 @@ public class RaftStateMachine extends StateMachineAdapter {
try {
// TODO: remove file from meta
// SnapshotReader 沒有提供刪除文件的接口
FileUtils.deleteDirectory(new File(snapshotDir));
File file = new File(snapshotArchive);
if (file.exists()) {

View File

@ -20,7 +20,7 @@ package org.apache.hugegraph.pd.raft;
import org.apache.hugegraph.pd.common.PDException;
/**
* 接收raft发送的数据
* Receives data sent by raft
*/
public interface RaftTaskHandler {

View File

@ -79,7 +79,7 @@ public class RaftKVStore implements HgKVStore, RaftTaskHandler {
}
/**
* 查询可以不走raft直接读取
* Queries can be read without rafting
*/
@Override
public byte[] get(byte[] key) throws PDException {
@ -180,7 +180,7 @@ public class RaftKVStore implements HgKVStore, RaftTaskHandler {
}
/**
* 需要走Raft的真实操作
* Need to walk the real operation of Raft
*/
private void doPut(byte[] key, byte[] value) throws PDException {

View File

@ -37,43 +37,44 @@ license:
license-path: ./conf/hugegraph.license
grpc:
port: 8686
# grpc 的服务地址,部署时需要改为本地实际 IPv4 地址
# The service address of grpc needs to be changed to the actual local IPv4 address when deploying.
host: 127.0.0.1
server:
# rest 服务端口号
# REST service port number
port: 8620
pd:
# 存储路径
# Storage path
data-path: ./pd_data
# 自动扩容的检查周期,定时检查每个 store 的分区数量,自动进行分区数量平衡
# The check cycle of automatic expansion regularly checks the number of partitions in each store and automatically balances the number of partitions
patrol-interval: 1800
# 初始 store 列表,在列表内的 store 自动激活
# The initial store list, grpc IP: grpc port, the store in the list is automatically activated
initial-store-count: 1
# grpc IP:grpc port
initial-store-list: 127.0.0.1:8500
raft:
# 本机 raft 服务地址
# The address of the local raft service
address: 127.0.0.1:8610
# pd 集群服务地址
# The service address of the PD cluster
peers-list: 127.0.0.1:8610
store:
# store 下线时间。超过该时间,认为 store 永久不可用,分配副本到其他机器,单位秒
# The time when the store went offline. After that time, the store is considered permanently unavailable, and the replica is allocated to another machine, in seconds
max-down-time: 172800
# 是否开启 store 监控数据存储
# Specifies whether to enable store monitoring data storage
monitor_data_enabled: true
# 监控数据的间隔minute (默认), hour, second
# The interval between monitoring data, minute, hour, second
# default: 1 min * 1 day = 1440
monitor_data_interval: 1 minute
# 监控数据的保留时间 1 天; day, month, year
# Retention time of monitoring data is 1 day; day, month, year
monitor_data_retention: 1 day
initial-store-count: 1
partition:
# 默认每个分区副本数
# Default number of replicas per partition
default-shard-count: 1
# 默认每机器最大副本数,初始分区数 = store-max-shard-count * store-number / default-shard-count
# The default maximum number of replicas per machine
# the initial number of partitions= store-max-shard-count * store-number / default-shard-count
store-max-shard-count: 12

View File

@ -33,8 +33,8 @@ management:
grpc:
port: $GRPC_PORT$
# grpc的服务地址,
#注意部署时需要改为本地实际IPv4地址。
# grpc's service address,
# Note: You need to change to the local actual Iv 4 address when deploying.
host: $GRPC_HOST$
netty-server:
max-inbound-message-size: 100MB
@ -43,29 +43,30 @@ server:
port : $SERVER_PORT$
pd:
# 集群ID区分不同的PD集群
# Cluster ID: to distinguish different PD clusters
patrol-interval: 2147483647
data-path: $PD_DATA_PATH$
raft:
address: $RAFT_ADDRESS$
# raft集群
# raft cluster
peers-list: $RAFT_PEERS_LIST$
# 快照生成时间间隔,单位秒
# The interval between snapshot generation, in seconds
snapshotInterval: 300
metrics: true
store:
# store心跳超时时间超过该时间认为store临时不可用转移Leader到其他副本,单位秒
# If the store heartbeat timeout period exceeds this time, the store is temporarily unavailable and the leader is transferred to another replica in seconds
keepAlive-timeout: 60
# store下线时间。超过该时间认为store永久不可用分配副本到其他机器单位秒
# The time when the store went offline. After that time, the store is considered permanently unavailable, and the replica is allocated to another machine, in seconds
max-down-time: 1800
partition:
# 默认分区总数
# The default total number of partitions
default-total-count: 30
# 默认每个分区副本数
# Default number of replicas per partition
default-shard-count: 3
discovery:
#客户端注册后,无心跳最长次数,超过后,之前的注册信息会被删除
# After the client registers, the maximum number of heartbeats is not reached, and after that, the
previous registration information will be deleted
heartbeat-try-count: 3

View File

@ -92,23 +92,15 @@
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
</pluginArtifact>
<!--默认值-->
<protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
<!--默认值-->
<!--<outputDirectory>${project.build.directory}/generated-sources/protobuf/java</outputDirectory>-->
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
<!--设置是否在生成java文件之前清空outputDirectory的文件默认值为true设置为false时也会覆盖同名文件-->
<clearOutputDirectory>false</clearOutputDirectory>
<!--更多配置信息可以查看https://www.xolstice.org/protobuf-maven-plugin/compile-mojo.html-->
</configuration>
<executions>
<execution>
<!--在执行mvn compile的时候会执行以下操作-->
<phase>generate-sources</phase>
<goals>
<!--生成OuterClass类-->
<goal>compile</goal>
<!--生成Grpc类-->
<goal>compile-custom</goal>
</goals>
</execution>

View File

@ -30,7 +30,6 @@ enum TaskType {
Change_KeyRange = 5;
}
//
message Task {
uint64 id = 1;
TaskType type = 2;
@ -38,7 +37,6 @@ message Task {
int64 start_timestamp = 4;
metapb.Partition partition = 5;
string message = 6;
//shard执行的任务状态
repeated ShardTaskState shardState = 7;
ChangeShard changeShard = 9;
SplitPartition splitPartition = 10;
@ -49,10 +47,10 @@ message Task {
enum TaskState{
Task_Unknown = 0;
Task_Ready = 1; //
Task_Doing = 2; //
Task_Done = 3; //
Task_Exit = 4; //退
Task_Ready = 1;
Task_Doing = 2;
Task_Done = 3;
Task_Exit = 4;
Task_Stop = 10;
Task_Success = 11;
Task_Failure = 12;

View File

@ -21,17 +21,17 @@ option java_package = "org.apache.hugegraph.pd.grpc";
import "google/protobuf/any.proto";
enum ClusterState{
//
// Cluster health
Cluster_OK = 0;
//
// Partition warning: There are some faulty nodes, which do not affect read/write for a short time
Cluster_Warn = 2;
// 线
// The partition is offline, which can be read but cannot be written
Cluster_Offline = 10;
// ,
// If the partition is faulty and cannot be read or written, you need to repair the faulty node as soon as possible.
Cluster_Fault = 11;
Cluster_Not_Ready = -1;
}
//
// Cluster status
message ClusterStats{
ClusterState state = 1;
string message = 2;
@ -40,15 +40,13 @@ message ClusterStats{
enum StoreState {
Unknown = 0;
//
// Not activated
Pending = 4;
// 线
// online
Up = 1;
// 线
// Offline
Offline = 2;
// 线
Exiting = 5;
// 线
Tombstone = 3;
}
@ -64,7 +62,7 @@ message Store {
string address = 2;
string raft_address = 3;
repeated StoreLabel labels = 4;
// Store软件版本号
// Store Software version number
string version = 5;
StoreState state = 6;
// The start timestamp of the current store
@ -73,7 +71,7 @@ message Store {
// The last heartbeat timestamp of the store.
int64 last_heartbeat = 9;
StoreStats stats = 10;
//
// The version number of the data format
int32 data_version = 11;
int32 cores = 12;
string data_path = 13;
@ -103,38 +101,37 @@ message ShardGroup{
message Graph {
string graph_name = 2;
// 0raft分组总数
// The number of partitions, 0 indicates invalid and cannot be greater than the total number of raft packets
int32 partition_count = 3;
//
PartitionState state = 10;
string message = 11;
GraphState graph_state = 12;
}
//
// Partition working status
enum PartitionState{
PState_None = 0;
//
PState_Normal = 1;
//
// Partition warning: There are some faulty nodes, which do not affect read/write for a short time
PState_Warn = 2;
// 线
// The partition is offline, which can be read but cannot be written
PState_Offline = 10;
// ,
// If the partition is faulty and cannot be read or written, you need to repair the faulty node as soon as possible.
PState_Fault = 11;
}
message PartitionV36 {
uint32 id = 1;
string graph_name = 3;
// [start_key, end_key).
// Partition range [start_key, end_key].
uint64 start_key = 4;
uint64 end_key = 5;
repeated Shard shards = 6;
// Leader任期leader切换后递增
// Leader term, leader increment after switching
uint64 version = 7;
// shards版本号
// shards The version number, which is incremented with each change
uint64 conf_ver = 8;
//
// Current working status
PartitionState state = 10;
string message = 11;
}
@ -142,16 +139,16 @@ message PartitionV36 {
message Partition {
uint32 id = 1;
string graph_name = 3;
// [start_key, end_key).
// Partition range [start_key, end_key].
uint64 start_key = 4;
uint64 end_key = 5;
// Partition shard listshard group ), version conf version不再有实际的意义
// The partition object no longer stores the shard list (which is queried according to the corresponding shard group), and the version and conf version are no longer meaningful
// repeated Shard shards = 6;
// key range
// key range increment after each change
uint64 version = 7;
// shards版本号
// shards The version number, which is incremented with each change
// uint64 conf_ver = 8;
//
// Current working status
PartitionState state = 10;
string message = 11;
}
@ -159,21 +156,21 @@ message Partition {
message PartitionShard {
metapb.Partition partition = 1;
metapb.Shard leader = 2;
// 线Shard
// Offline Shard
repeated metapb.Shard offline_shards = 3;
}
//
// The storage location where the record partition is located
message PartitionStore {
uint32 partition_id = 1;
string graph_name = 3;
//
// Storage location
string store_location = 4;
}
message PartitionRaft {
uint32 partition_id = 1;
string graph_name = 3;
//
// Storage location
string raft_location = 4;
}
@ -181,42 +178,43 @@ message ShardStats{
uint64 store_id = 2;
ShardRole role = 3;
ShardState state = 4;
//
// The progress of the installation of the snapshot
uint32 progress = 5;
}
message PartitionStats{
uint32 id = 1;
// raft分组的任期.
// raft Term of office of the group.
uint64 leader_term = 2;
repeated string graph_name = 3;
metapb.Shard leader = 4;
// 线 shards
// Offline shards
repeated metapb.Shard shard = 5;
repeated metapb.Shard learner = 6;
uint64 conf_ver = 7;
//
// partition status
PartitionState state = 8;
repeated ShardStats shardStats = 9;
//
// The approximate size of the partition
uint64 approximate_size = 10;
// key的近似数量
// The approximate number of partition keys
uint64 approximate_keys = 13;
// heartbeat timestamp
int64 timestamp = 16;
}
message GraphStats{
//
// graph
string graph_name = 1;
//
// The approximate size of the partition
uint64 approximate_size = 2;
// key的近似数量
// The approximate number of partition keys
uint64 approximate_keys = 3;
// // committed index
// uint64 committed_index = 4;
uint32 partition_id = 5;
ShardRole role = 6;
//
// Current working status
PartitionState work_state = 8;
}
@ -252,11 +250,11 @@ message QueryStats {
enum ShardState{
SState_None = 0;
//
// Normal
SState_Normal = 1;
//
// Install snapshots
SState_Snapshot = 2;
// 线
// Offline
SState_Offline = 10;
}
@ -310,14 +308,14 @@ message StoreStats {
repeated RecordPair system_metrics = 25;
}
//
// Partition query criteria
message PartitionQuery{
optional uint64 store_id = 1; // 0 store_id
optional uint64 store_id = 1; // 0 Indicates that the query criteria do not contain store_id
optional string graph_name = 2;
optional uint32 partition_id = 4;
}
//PD
// PD Node information
message Member {
uint64 cluster_id = 1;
string raft_url = 3;
@ -329,37 +327,38 @@ message Member {
string replicator_state = 9;
}
//
// Graph space configuration
message GraphSpace{
string name = 1;
//
// Maximum occupied storage
uint64 storage_limit = 2;
// 使
// Space used
uint64 used_size = 3;
//
// Modify time
uint64 timestamp = 10;
}
// PD
// PD Config
message PDConfig{
uint64 version = 1;
// , Store数量动态计算
// The number of partitions is dynamically calculated based on the number of stores at the initialization and modified after splitting
// The exact count needs to be determined based on the store group
int32 partition_count = 2;
//
// Number of replicas per partition
int32 shard_count = 3;
// pd集群列表
// pd List of clusters
string peers_list = 4;
// store数量
// The minimum number of stores in the cluster
int32 min_store_count = 6;
// store最大副本数
// Maximum number of replicas per store
int32 max_Shards_Per_Store = 7;
//
// Modify time
uint64 timestamp = 10;
}
//
// Message persistence
message QueueItem{
string item_id = 1;
string item_class = 2;
@ -387,8 +386,7 @@ enum GraphMode{
}
enum GraphModeReason{
Empty = 0; //
Initiative = 1; //
Quota = 2; //
Empty = 0;
Initiative = 1; // Active status settings
Quota = 2; // The limit condition is reached
}

View File

@ -22,9 +22,7 @@ option java_package = "org.apache.hugegraph.pd.grpc.common";
option java_outer_classname = "HgPdCommonProto";
message RequestHeader {
// ID.
uint64 cluster_id = 1;
// ID.
uint64 sender_id = 2;
}

View File

@ -56,8 +56,8 @@ message PulseAckRequest {
int64 notice_id = 2;
}
// peer增减leader改变等事件发生时leader发送心跳
// pd对分区进行shard增减通过Response发送给leader
// When an event such as a partition heartbeat occurs such as the increase or decrease of peers in a partition or the change of leader, the leader sends a heartbeat.
// At the same time, the pd adds or decreases shards to the partition and sends the response to the leader
message PartitionHeartbeatRequest {
RequestHeader header = 1;
// Leader Peer sending the heartbeat
@ -83,15 +83,15 @@ message PartitionHeartbeatResponse {
ChangeShard change_shard = 4;
TransferLeader transfer_leader = 5;
// SplitPartition是原分区
// Split into multiple partitions, with the first SplitPartition being the original partition and the second starting being the new partition
SplitPartition split_partition = 6;
// rocksdb compaction null是针对所有
// rocksdb compaction specifies the table, null is for all
DbCompaction db_compaction = 7;
// partition的数据 target
// Migrate data from the partition to the target
MovePartition move_partition = 8;
// partition的graph的数据
// Clean up the data for the partition of the graph
CleanPartition clean_partition = 9;
// partition key range
// partition key range variation
PartitionKeyRange key_range = 10;
}
@ -113,11 +113,11 @@ message DbCompaction {
string table_name = 3;
}
message MovePartition{
// target partition的key range为range
message MovePartition {
// The new range after migration
metapb.Partition target_partition = 1;
// partition key start key end的所有数据
// target partition
// partition's key start and key end,
// will migrate to target partition
uint64 key_start = 2;
uint64 key_end = 3;
}
@ -126,7 +126,7 @@ message CleanPartition {
uint64 key_start = 1;
uint64 key_end = 2;
CleanType clean_type = 3;
bool delete_partition = 4; //
bool delete_partition = 4; // Whether to delete the partition
}
message PartitionKeyRange{
@ -159,12 +159,12 @@ enum ConfChangeType {
CONF_CHANGE_TYPE_ADD_NODE = 1;
CONF_CHANGE_TYPE_REMOVE_NODE = 2;
CONF_CHANGE_TYPE_ADD_LEARNER_NODE = 3;
CONF_CHANGE_TYPE_ADJUST = 4; // shardleader根据新的配置动态增减
CONF_CHANGE_TYPE_ADJUST = 4; // Adjust the shard, and the leader dynamically increases or decreases according to the new configuration.
}
enum CleanType {
CLEAN_TYPE_KEEP_RANGE = 0; // range
CLEAN_TYPE_EXCLUDE_RANGE = 1; // range
CLEAN_TYPE_KEEP_RANGE = 0; // Only this range remains
CLEAN_TYPE_EXCLUDE_RANGE = 1; // Delete this range
}
enum PdInstructionType {

View File

@ -98,6 +98,5 @@ enum NodeEventType {
NODE_EVENT_TYPE_NODE_ONLINE = 1;
NODE_EVENT_TYPE_NODE_OFFLINE = 2;
NODE_EVENT_TYPE_NODE_RAFT_CHANGE = 3;
// pd leader
NODE_EVENT_TYPE_PD_LEADER_CHANGE = 4;
}

View File

@ -24,83 +24,83 @@ import "metaTask.proto";
option java_package = "org.apache.hugegraph.pd.grpc";
service PD {
// storestore_id store_id是store唯一标识
// Register store, the first registration will generate a new store_id, store_id is the unique identifier of the store
rpc RegisterStore(RegisterStoreRequest) returns (RegisterStoreResponse) {}
rpc GetStore(GetStoreRequest) returns (GetStoreResponse) {}
// Store状态等信息.
// Modify Store status and other information.
rpc SetStore(SetStoreRequest) returns (SetStoreResponse) {}
//
// Look up the partition based on the key
rpc DelStore(DetStoreRequest) returns (DetStoreResponse) {}
rpc GetAllStores(GetAllStoresRequest) returns (GetAllStoresResponse) {}
rpc StoreHeartbeat(StoreHeartbeatRequest) returns (StoreHeartbeatResponse) {}
//
// Look up the partition based on the key
rpc GetPartition(GetPartitionRequest) returns (GetPartitionResponse) {}
// HashCode查找所属分区
// Look up the partition based on HashCode
rpc GetPartitionByCode(GetPartitionByCodeRequest) returns (GetPartitionResponse) {}
// PartitionID返回分区
// Return partition by PartitionID
rpc GetPartitionByID(GetPartitionByIDRequest) returns (GetPartitionResponse) {}
rpc ScanPartitions(ScanPartitionsRequest) returns (ScanPartitionsResponse) {}
// key范围
// Update partition information, mainly used to update partition key range, call this interface carefully, otherwise data loss will occur.
rpc UpdatePartition(UpdatePartitionRequest) returns (UpdatePartitionResponse) {}
//
// Look up the partition based on the key
rpc DelPartition(DelPartitionRequest) returns (DelPartitionResponse) {}
// , StoreGraph等条件
// Query partition information based on conditions, including Store, Graph and other conditions
rpc QueryPartitions(QueryPartitionsRequest) returns (QueryPartitionsResponse){}
//
// Read graph information
rpc GetGraph(GetGraphRequest) returns (GetGraphResponse){}
//
// Modify graph information
rpc SetGraph(SetGraphRequest) returns (SetGraphResponse){}
rpc DelGraph(DelGraphRequest) returns (DelGraphResponse){}
// ID
// Global unique incremental ID
rpc GetId(GetIdRequest) returns (GetIdResponse){}
rpc ResetId(ResetIdRequest) returns (ResetIdResponse){}
// PD的集群列表
// PD cluster list
rpc GetMembers(GetMembersRequest) returns (GetMembersResponse) {}
rpc GetStoreStatus(GetAllStoresRequest) returns (GetAllStoresResponse) {}
rpc GetPDConfig(GetPDConfigRequest) returns (GetPDConfigResponse){}
rpc SetPDConfig(SetPDConfigRequest) returns (SetPDConfigResponse){}
rpc GetGraphSpace(GetGraphSpaceRequest) returns (GetGraphSpaceResponse){}
rpc SetGraphSpace(SetGraphSpaceRequest) returns (SetGraphSpaceResponse){}
//
// Get cluster health status
rpc GetClusterStats(GetClusterStatsRequest) returns (GetClusterStatsResponse){}
// PD的集群节点
// Replace PD cluster nodes
rpc ChangePeerList(ChangePeerListRequest) returns (getChangePeerListResponse) {}
//
// Data splitting
rpc SplitData(SplitDataRequest) returns (SplitDataResponse){}
rpc SplitGraphData(SplitGraphDataRequest) returns (SplitDataResponse) {}
//
// Data migration
rpc MovePartition(MovePartitionRequest) returns (MovePartitionResponse){}
//
// Report partition splitting and other task execution results
rpc ReportTask(ReportTaskRequest) returns (ReportTaskResponse){}
rpc GetPartitionStats(GetPartitionStatsRequest) returns (GetPartitionStatsResponse){}
//store中分区leader的数量
// Balance the number of partition leaders in the store
rpc BalanceLeaders(BalanceLeadersRequest) returns (BalanceLeadersResponse){}
// license文件
// Replace license file
rpc PutLicense(PutLicenseRequest) returns (PutLicenseResponse){}
// rocksdb进行compaction
// Notify rocksdb to perform compaction
rpc DbCompaction(DbCompactionRequest) returns (DbCompactionResponse){}
//
// Merge partitions
rpc CombineCluster(CombineClusterRequest) returns (CombineClusterResponse){}
//
// Shrink a single graph
rpc CombineGraph(CombineGraphRequest) returns (CombineGraphResponse) {}
// shard group
rpc GetShardGroup(GetShardGroupRequest) returns (GetShardGroupResponse){}
rpc UpdateShardGroup(UpdateShardGroupRequest) returns (UpdateShardGroupResponse){}
// shard group
// Delete shard group
rpc DeleteShardGroup(DeleteShardGroupRequest) returns (DeleteShardGroupResponse) {}
// shard group
// shard group operation related to operation
rpc UpdateShardGroupOp(ChangeShardRequest) returns (ChangeShardResponse){}
// change shard
// Change shard
rpc ChangeShard(ChangeShardRequest) returns (ChangeShardResponse) {}
// pd raft
// Update pd raft
rpc updatePdRaft(UpdatePdRaftRequest) returns (UpdatePdRaftResponse) {}
rpc getCache(GetGraphRequest) returns (CacheResponse) {}
@ -108,9 +108,7 @@ service PD {
}
message RequestHeader {
// ID.
uint64 cluster_id = 1;
// ID.
uint64 sender_id = 2;
}
@ -141,21 +139,21 @@ enum ErrorType {
ROCKSDB_SAVE_SNAPSHOT_ERROR = 1005;
ROCKSDB_LOAD_SNAPSHOT_ERROR = 1006;
//
// Current cluster state prohibits splitting
Cluster_State_Forbid_Splitting = 1007;
//
// Currently splitting
Split_Partition_Doing = 1008;
// store上分区数量超过上限
// The number of partitions on the store exceeds the limit
Too_Many_Partitions_Per_Store = 1009;
// license
// License error
LICENSE_ERROR = 107;
// license
// License authentication error
LICENSE_VERIFY_ERROR = 108;
//线
// Partition offline is in progress
Store_Tombstone_Doing = 1010;
//
// Invalid number of splits
Invalid_Split_Partition_Count = 1011;
}
@ -193,7 +191,7 @@ message RegisterStoreRequest {
message RegisterStoreResponse {
ResponseHeader header = 1;
// store_id
// Upon initial registration, returns the new store_id
uint64 store_id = 2;
}
@ -204,16 +202,15 @@ message SetStoreRequest {
message SetStoreResponse {
ResponseHeader header = 1;
// Store
// Returns the modified Store
metapb.Store store = 2;
}
// graph_name所在的所有storegraph_name为空值store
// Returns all stores where graph_name is located. If graph_name is empty, returns all system stores.
message GetAllStoresRequest {
RequestHeader header = 1;
string graph_name = 2;
// 线store
// Whether to exclude offline stores
bool exclude_offline_stores = 3;
}
@ -254,7 +251,7 @@ message GetPartitionResponse {
ResponseHeader header = 1;
metapb.Partition partition = 2;
metapb.Shard leader = 3;
// 线Shard
// Offline Shards
repeated metapb.Shard offline_shards = 4;
}
@ -435,65 +432,65 @@ enum OperationMode {
Expert = 1;
}
message SplitDataParam{
// ID
message SplitDataParam {
// ID of the source partition being split
uint32 partition_id = 1;
//
// Number of target partitions
uint32 count = 2;
}
message SplitDataRequest{
message SplitDataRequest {
RequestHeader header = 1;
//
// AutoStore上分区数达到最大值
// Expert:splitParams
// Operation mode
// Auto: Automatic splitting, when the number of partitions on each Store reaches the maximum value
// Expert: Expert mode, requires specifying splitParams
OperationMode mode = 2;
repeated SplitDataParam param = 3;
}
message SplitGraphDataRequest{
message SplitGraphDataRequest {
RequestHeader header = 1;
//
// Operation mode
string graph_name = 2;
uint32 to_count = 3;
}
message SplitDataResponse{
message SplitDataResponse {
ResponseHeader header = 1;
}
message MovePartitionParam{
message MovePartitionParam {
uint32 partition_id = 1;
uint64 src_store_id = 2;
uint64 dst_store_id = 3;
}
message MovePartitionRequest{
message MovePartitionRequest {
RequestHeader header = 1;
//
// AutoStore上分区数量相同
// Expert:transferParams
// Operation mode
// Auto: Automatic transfer, aiming for equal number of partitions on each Store
// Expert: Expert mode, requires specifying transferParams
OperationMode mode = 2;
repeated MovePartitionParam param = 3;
}
message MovePartitionResponse{
message MovePartitionResponse {
ResponseHeader header = 1;
}
message ReportTaskRequest{
message ReportTaskRequest {
RequestHeader header = 1;
metaTask.Task task = 2;
}
message ReportTaskResponse{
message ReportTaskResponse {
ResponseHeader header = 1;
}
message GetPartitionStatsRequest{
message GetPartitionStatsRequest {
RequestHeader header = 1;
uint32 partition_id = 2;
// ID
// If empty, returns the same partition ID for all graphs
string graph_name = 4;
}
@ -596,7 +593,7 @@ message UpdatePdRaftResponse{
}
message CacheResponse {
ResponseHeader header = 1;
// Store
// Returns the modified Store
repeated metapb.Store stores = 2;
repeated metapb.ShardGroup shards = 3;
repeated metapb.Graph graphs = 4;

View File

@ -24,7 +24,7 @@ import org.springframework.context.annotation.ComponentScan;
import com.alipay.remoting.util.StringUtils;
/**
* PD 服务启动类
* PD service startup class
*/
@ComponentScan(basePackages = {"org.apache.hugegraph.pd"})
@SpringBootApplication

View File

@ -38,7 +38,7 @@ public class PdInstructionSubject extends AbstractObserverSubject {
}
/**
* pd单纯的向pulse发送的指令不接收对应的notice
* Simply send a command to pulse, and do not receive the corresponding notice
*
* @return null
*/

View File

@ -107,7 +107,7 @@ public class API {
}
builder.append(",");
});
builder.deleteCharAt(builder.length() - 1); //删除最后一个逗号
builder.deleteCharAt(builder.length() - 1);
}
builder.append("]").append(COMMA);
}

View File

@ -143,7 +143,7 @@ public class GraphAPI extends API {
statistics = new GraphStatistics(graph);
response.setData(statistics);
} else {
response.setData(new HashMap<String, Object>()); //没有该图
response.setData(new HashMap<String, Object>());
}
response.setStatus(Pdpb.ErrorType.OK.getNumber());
response.setMessage(Pdpb.ErrorType.OK.name());
@ -176,7 +176,7 @@ public class GraphAPI extends API {
public Shard(Metapb.Shard shard, long partitionId) {
this.role = String.valueOf(shard.getRole());
this.storeId = shard.getStoreId();
this.state = Metapb.ShardState.SState_Normal.name(); //gshard的状态默认为normal
this.state = Metapb.ShardState.SState_Normal.name();
this.progress = 0;
this.partitionId = partitionId;
}
@ -236,7 +236,7 @@ public class GraphAPI extends API {
@Data
class GraphStatistics {
//图统计信息
// Graph statistics
String graphName;
long partitionCount;
String state;
@ -255,7 +255,7 @@ public class GraphAPI extends API {
graphName = graph.getGraphName();
partitionCount = graph.getPartitionCount();
state = String.valueOf(graph.getState());
// 数据量及key的数量
// The amount of data and the number of keys
List<Metapb.Store> stores = pdRestService.getStores(graphName);
for (Metapb.Store store : stores) {
List<Metapb.GraphStats> graphStatsList = store.getStats().getGraphStatsList();
@ -272,7 +272,7 @@ public class GraphAPI extends API {
List<Partition> resultPartitionList = new ArrayList<>();
List<Metapb.Partition> tmpPartitions = pdRestService.getPartitions(graphName);
if ((tmpPartitions != null) && (!tmpPartitions.isEmpty())) {
// 需要返回的分区信息
// The partition information to be returned
for (Metapb.Partition partition : tmpPartitions) {
Metapb.PartitionStats partitionStats = pdRestService
.getPartitionStats(graphName, partition.getId());
@ -282,7 +282,7 @@ public class GraphAPI extends API {
}
}
partitions = resultPartitionList;
// 隐去图名后面的 /g /m /s
// Hide /g /m /s after the title of the graph
final int postfixLength = 2;
graphName = graphName.substring(0, graphName.length() - postfixLength);
}

View File

@ -98,7 +98,6 @@ public class IndexAPI extends API {
statistics.onlineStoreSize = pdService.getStoreNodeService().getActiveStores().size();
statistics.offlineStoreSize = statistics.storeSize - statistics.onlineStoreSize;
List<Metapb.Graph> graphs = pdRestService.getGraphs();
// 图的数量只统计/g
statistics.graphSize = graphs.stream().filter((g) -> (g.getGraphName() != null)
&&
(g.getGraphName().endsWith("/g")))
@ -112,11 +111,15 @@ public class IndexAPI extends API {
statistics.dataSize += graphStats.getApproximateSize();
}
}
// 数据状态根据图的状态推出数据状态,枚举值越大问题越严重 默认为正常状态
// Data status: The data status is deduced based on the state of the graph, the
// larger the enumeration value, the more serious the problem, and the default is the
// normal state
Metapb.PartitionState dataState = Metapb.PartitionState.PState_Normal;
for (Metapb.Graph graph : pdRestService.getGraphs()) {
if (graph.getState() == Metapb.PartitionState.UNRECOGNIZED) {
continue; // 未识别不参与对比不然会抛出异常
// If it is not recognized, it will not participate in the
// comparison, otherwise an exception will be thrown
continue;
}
if ((graph.getState() != null) &&
(graph.getState().getNumber() > dataState.getNumber())) {
@ -174,9 +177,9 @@ public class IndexAPI extends API {
String state;
String dataPath;
String role;
String serviceName; //服务名称自定义属性
String serviceVersion; //静态定义
long startTimeStamp; //进程启动时间
String serviceName; // Service name, custom attributes
String serviceVersion; // Static definitions
long startTimeStamp; // The time when the process started
public Member(Metapb.Member member) {
if (member != null) {
@ -200,31 +203,31 @@ public class IndexAPI extends API {
class Statistics {
/**
* 集群状态
* Cluster status, default of the cluster
*/
String state;
/**
* 数据状态
* Data status
*/
String dataState;
/**
* pd集群成员
* pd Cluster members
*/
List<Member> pdList;
/**
* pd集群的leader
* pd The leader of the cluster
*/
Member pdLeader;
/**
* pd集群的大小
* pd The size of the cluster
*/
int memberSize;
/**
* stores列表
* stores list
*/
List<Store> stores;
/**
* store的数量
* store quantity
*/
int storeSize;
/**
@ -232,27 +235,27 @@ public class IndexAPI extends API {
*/
int onlineStoreSize;
/**
* 离线的store的数量
* The number of stores that are offline
*/
int offlineStoreSize;
/**
* 图的数量
* The number of graphs
*/
long graphSize;
/**
* 分区的数量
* The number of partitions
*/
int partitionSize;
/**
* 分区副本数
* Number of partition replicas
*/
int shardCount;
/**
* key的数量
* The number of keys
*/
long keyCount;
/**
* 数据量
* Amount of data
*/
long dataSize;

View File

@ -216,9 +216,9 @@ public class MemberAPI extends API {
String dataPath;
String role;
String replicateState;
String serviceName; //服务名称自定义属性
String serviceVersion; //静态定义
long startTimeStamp; //启动时间暂时取进程的启动时间
String serviceName; // Service name, custom attributes
String serviceVersion; // Static definitions
long startTimeStamp; // Startup time: temporarily takes the startup time of the process
public Member(Metapb.Member member) {
if (member != null) {
@ -236,6 +236,7 @@ public class MemberAPI extends API {
}
@Useless("delete later")
public Member() {}
public Member() {
}
}
}

View File

@ -58,12 +58,12 @@ public class PartitionAPI extends API {
@GetMapping(value = "/highLevelPartitions", produces = MediaType.APPLICATION_JSON_VALUE)
public RestApiResponse getHighLevelPartitions() {
// 分区下多个图的信息
// Information about multiple graphs under the partition
Map<Integer, Map<String, GraphStats>> partitions2GraphsMap = new HashMap<>();
Map<Integer, HighLevelPartition> resultPartitionsMap = new HashMap<>();
// 每一个分区的keyCount 只从leader处取出
// The keyCount of each partition is only taken from the leader
Map<Integer, Long> partition2KeyCount = new HashMap<>();
// 每一个分区的dataSize 只从leader处取出
// The dataSize of each partition is only taken from the leader
Map<Integer, Long> partition2DataSize = new HashMap<>();
List<Metapb.Store> stores;
Map<Long, Metapb.Store> storesMap = new HashMap<>();
@ -77,20 +77,19 @@ public class PartitionAPI extends API {
storesMap.put(store.getId(), store);
List<Metapb.GraphStats> graphStatsList = store.getStats().getGraphStatsList();
for (Metapb.GraphStats graphStats : graphStatsList) {
// 获取分区保存的图信息只从leader处取出来
// Obtaining Graph Information Saved by a Partition (Only from the Leader)
if (Metapb.ShardRole.Leader != graphStats.getRole()) {
continue;
}
// 计算分区的keyCount不区分图
// Calculating the key count of partitions (indiscriminate graphs)
partition2KeyCount.put(graphStats.getPartitionId(),
partition2KeyCount.getOrDefault(graphStats.getPartitionId(),
graphStats.getApproximateKeys()));
// 计算分区的dataSize, 通过累加图的大小实现
// The dataSize of the partition is calculated by adding the size of the graph
partition2DataSize.put(graphStats.getPartitionId(),
partition2DataSize.getOrDefault(graphStats.getPartitionId(),
0L)
+ graphStats.getApproximateSize());
// 构造分区下的图信息
if (partitions2GraphsMap.get(graphStats.getPartitionId()) == null) {
partitions2GraphsMap.put(graphStats.getPartitionId(),
new HashMap<String, GraphStats>());
@ -100,10 +99,10 @@ public class PartitionAPI extends API {
partitionGraphsMap.put(graphStats.getGraphName(), new GraphStats(graphStats));
}
}
// 构造分区的所有需返回的信息
// Construct all the information that needs to be returned for the partition
List<Metapb.Partition> partitionList = pdRestService.getPartitions("");
for (Metapb.Partition partition : partitionList) {
// 补充分区内图信息的startKey, endKey
// Supplement the startKey and endKey of the partition image
if (partitions2GraphsMap.get(partition.getId()) != null) {
GraphStats graphStats =
partitions2GraphsMap.get(partition.getId()).get(partition.getGraphName());
@ -112,7 +111,7 @@ public class PartitionAPI extends API {
graphStats.endKey = partition.getEndKey();
}
}
// 构造分区整体信息不区分图
// Construct the overall information of the partition (regardless of the diagram)
if ((resultPartitionsMap.get(partition.getId()) == null)
&& (!partition.getGraphName().endsWith("/s"))
) {
@ -124,7 +123,7 @@ public class PartitionAPI extends API {
log.error("getPartitionStats error", e);
partitionStats = null;
}
// 初始化分区信息
// Initialize the partition information
HighLevelPartition resultPartition =
new HighLevelPartition(partition, partitionStats);
resultPartition.keyCount =
@ -132,28 +131,30 @@ public class PartitionAPI extends API {
resultPartition.dataSize =
partition2DataSize.getOrDefault(resultPartition.partitionId, 0L);
for (ShardStats shard : resultPartition.shards) {
// 对副本的地址分区信息赋值
// Assign values to the address and partition information of the replica
shard.address = storesMap.get(shard.storeId).getAddress();
shard.partitionId = partition.getId();
}
if ((partitionStats != null) && (partitionStats.getLeader() != null)) {
long storeId = partitionStats.getLeader().getStoreId(); // 获取leader的storeId
long storeId = partitionStats.getLeader().getStoreId();
resultPartition.leaderAddress =
storesMap.get(storeId).getAddress(); // 获取leader的address
storesMap.get(storeId).getAddress();
}
resultPartitionsMap.put(partition.getId(), resultPartition);
}
}
// 构造需返回的分区下的图列表只返回/g, 且按名称排序
// Construct a list of graphs under the partitions to be returned, return only /g, and
// sort by name
for (Map.Entry<Integer, HighLevelPartition> entry : resultPartitionsMap.entrySet()) {
Integer partitionId = entry.getKey();
HighLevelPartition currentPartition = resultPartitionsMap.get(partitionId);
Map<String, GraphStats> graphsMap = partitions2GraphsMap
.getOrDefault(partitionId, new HashMap<>()); // 避免后面出现空指针异常
.getOrDefault(partitionId,
new HashMap<>()); // Avoid null pointer exceptions at the back
ArrayList<GraphStats> graphsList = new ArrayList<>();
for (Map.Entry<String, GraphStats> entry1 : graphsMap.entrySet()) {
if (!entry1.getKey().endsWith("/g")) {
continue; // 只保留/g的图
continue; // Only the graph of /g is kept
}
String graphName = entry1.getKey();
GraphStats tmpGraph = graphsMap.get(graphName);
@ -181,10 +182,10 @@ public class PartitionAPI extends API {
@GetMapping(value = "/partitions", produces = MediaType.APPLICATION_JSON_VALUE)
public RestApiResponse getPartitions() {
try {
List<Partition> partitions = new ArrayList<>();//需返回的分区对象
List<Partition> partitions = new ArrayList<>();
List<Metapb.Partition> partitionList = pdRestService.getPartitions("");
List<Metapb.Store> stores = pdRestService.getStoreStats(false);
//分区的raftNode的状态
// The status of the raft node of the partition
HashMap<Long, HashMap<Integer, Metapb.RaftStats>> raftMap = new HashMap<>();
HashMap<Long, HashMap<String, Metapb.GraphStats>> shardIndexMap = new HashMap<>();
@ -392,7 +393,7 @@ public class PartitionAPI extends API {
long dataSize;
String shardState;
int progress;
long raftTerm; //任期
long raftTerm;
List<GraphStats> graphs;
List<ShardStats> shards;
String failureCause = "";
@ -424,7 +425,7 @@ public class PartitionAPI extends API {
log.error("get shard list failed, {}", e.getMessage());
}
}
// 综合所有副本的状态给shardState赋值
// Synthesize the state of all replicas and assign a value to shardState
shardState = tmpShardState.name();
}
}
@ -456,7 +457,7 @@ public class PartitionAPI extends API {
String role;
String state;
int progress;
//额外属性
// Extra attributes
long partitionId;
String address;
@ -468,7 +469,7 @@ public class PartitionAPI extends API {
}
ShardStats(Metapb.Shard shard) {
//当没有shardStats的初始化方法
// When there is no initialization method for shardStats
storeId = shard.getStoreId();
role = String.valueOf(shard.getRole());
state = Metapb.ShardState.SState_Normal.name();

View File

@ -50,8 +50,6 @@ public class ShardAPI extends API {
@GetMapping(value = "/shards", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public RestApiResponse getShards() {
//对shards信息的统计
try {
List<Shard> resultShardList = new ArrayList<>();
List<Metapb.Graph> graphs = pdRestService.getGraphs();

View File

@ -81,7 +81,7 @@ public class StoreAPI extends API {
}
}
// 仅支持通过该接口修改 storeState
// Only storeState can be modified through this API
@PostMapping(value = "/store/{storeId}", consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@ -113,7 +113,7 @@ public class StoreAPI extends API {
}
/**
* 返回每个store上的leader
* Returns the leader on each store
*
* @return
*/
@ -184,7 +184,7 @@ public class StoreAPI extends API {
@GetMapping(value = "store/{storeId}", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public RestApiResponse getStore(@PathVariable long storeId) {
//获取store的统计信息
// Get the statistics of the store
Metapb.Store store = null;
try {
store = pdRestService.getStore(storeId);
@ -238,12 +238,11 @@ public class StoreAPI extends API {
@Data
class Partition {
//分区信息
int partitionId;
String graphName;
String role; // shard role
String workState;
long dataSize; // 占用的存储空间
long dataSize; // The amount of storage space occupied
Partition() {
}
@ -262,26 +261,27 @@ public class StoreAPI extends API {
@Data
class StoreStatistics {
//store的统计信息
// store statistics
long storeId;
String address;
String raftAddress;
String version;
String state;
String deployPath;
String dataPath; // 数据存储路径
String dataPath; // The path where the data is stored
long startTimeStamp;
long registedTimeStamp; // 暂时取第一次心跳时间作为注册时间
long lastHeartBeat; // 上一次心跳时间
// For the time being, the time of the first heartbeat is taken as the registration time
long registedTimeStamp;
long lastHeartBeat; // Last heartbeat time
long capacity;
long available;
int partitionCount;
int graphSize;
long keyCount;
long leaderCount; // shard role = 'Leader'的分区数量
long leaderCount; // shard role = 'Leader' The number of partitions
String serviceName;
String serviceVersion;
long serviceCreatedTimeStamp; // 服务创建时间
long serviceCreatedTimeStamp; // The time when the service was created
List<Partition> partitions;
StoreStatistics(Metapb.Store store) {
@ -294,25 +294,26 @@ public class StoreAPI extends API {
deployPath = store.getDeployPath();
final String prefix = "file:";
if ((deployPath != null) && (deployPath.startsWith(prefix))) {
// 去掉前缀
// Remove the prefix
deployPath = deployPath.substring(prefix.length());
}
if ((deployPath != null) && (deployPath.contains(".jar"))) {
// 去掉jar包之后的信息
// Remove the information after the jar package
deployPath = deployPath.substring(0, deployPath.indexOf(".jar") + 4);
}
dataPath = store.getDataPath();
startTimeStamp = store.getStartTimestamp();
try {
serviceCreatedTimeStamp = pdRestService.getStore(store.getId())
.getStats().getStartTime(); // 实例时间
.getStats()
.getStartTime(); // Instance time
final int base = 1000;
serviceCreatedTimeStamp *= base; // 转化为毫秒
serviceCreatedTimeStamp *= base; // Translates to milliseconds
} catch (PDException e) {
e.printStackTrace();
serviceCreatedTimeStamp = store.getStartTimestamp();
}
registedTimeStamp = store.getStartTimestamp(); // 注册时间
registedTimeStamp = store.getStartTimestamp(); // Time of registration
lastHeartBeat = store.getLastHeartbeat();
capacity = store.getStats().getCapacity();
available = store.getStats().getAvailable();
@ -320,14 +321,17 @@ public class StoreAPI extends API {
serviceName = address + "-store";
serviceVersion = store.getVersion();
List<Metapb.GraphStats> graphStatsList = store.getStats().getGraphStatsList();
List<Partition> partitionStatsList = new ArrayList<>(); // 保存分区信息
HashSet<String> graphNameSet = new HashSet<>(); // 用于统计图的数量
HashSet<Integer> leaderPartitionIds = new HashSet<Integer>(); // 统计leader的分区数量
// 构造分区信息(store中存储的图信息)
// Save the partition information
List<Partition> partitionStatsList = new ArrayList<>();
// The number used for the chart
HashSet<String> graphNameSet = new HashSet<>();
// Statistics on the number of partitions of the leader
HashSet<Integer> leaderPartitionIds = new HashSet<Integer>();
// Construct partition information (graph information stored in the store)
Map<Integer, Long> partition2KeyCount = new HashMap<>();
for (Metapb.GraphStats graphStats : graphStatsList) {
String graphName = graphStats.getGraphName();
// 图名只保留/g /m /s前面的部分
// Only the part in front of /g /m /s is retained in the title
final int postfixLength = 2;
graphNameSet.add(graphName.substring(0, graphName.length() - postfixLength));
if ((graphStats.getGraphName() != null) &&
@ -335,7 +339,7 @@ public class StoreAPI extends API {
Partition pt = new Partition(graphStats);
partitionStatsList.add(pt);
}
// 统计每个分区的keyCount
// Count the keyCount of each partition
partition2KeyCount.put(graphStats.getPartitionId(),
graphStats.getApproximateKeys());
if (graphStats.getRole() == Metapb.ShardRole.Leader) {

View File

@ -56,7 +56,7 @@ import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
/**
* kv 存储的核心实现类
* The core implementation class of KV storage
*/
@Slf4j
@GRpcService
@ -87,7 +87,7 @@ public class KvServiceGrpcImpl extends KvServiceGrpc.KvServiceImplBase implement
}
/**
* 普通的 put
* Ordinary put
*
* @param request
* @param responseObserver
@ -119,7 +119,7 @@ public class KvServiceGrpcImpl extends KvServiceGrpc.KvServiceImplBase implement
}
/**
* 普通的 get
* Ordinary get
*
* @param request
* @param responseObserver
@ -151,7 +151,7 @@ public class KvServiceGrpcImpl extends KvServiceGrpc.KvServiceImplBase implement
}
/**
* 普通的 delete
* Ordinary delete
*
* @param request
* @param responseObserver
@ -185,7 +185,7 @@ public class KvServiceGrpcImpl extends KvServiceGrpc.KvServiceImplBase implement
}
/**
* 按前缀删除
* Delete by prefix
*
* @param request
* @param responseObserver
@ -223,7 +223,7 @@ public class KvServiceGrpcImpl extends KvServiceGrpc.KvServiceImplBase implement
}
/**
* 按前缀查询
* Search by prefix
*
* @param request
* @param responseObserver
@ -253,7 +253,7 @@ public class KvServiceGrpcImpl extends KvServiceGrpc.KvServiceImplBase implement
}
/**
* 获取随机非 0 字符串做 Id
* Obtain a random non-0 string as an Id
*
* @return
*/
@ -268,7 +268,7 @@ public class KvServiceGrpcImpl extends KvServiceGrpc.KvServiceImplBase implement
}
/**
* 普通的 watch
* Ordinary watch
*
* @param request
* @param responseObserver
@ -295,7 +295,7 @@ public class KvServiceGrpcImpl extends KvServiceGrpc.KvServiceImplBase implement
}
/**
* 普通的前缀 watch
* Ordinary prefix watch
*
* @param request
* @param responseObserver
@ -322,7 +322,7 @@ public class KvServiceGrpcImpl extends KvServiceGrpc.KvServiceImplBase implement
}
/**
* 上面两个方法的通用方式
* A generic approach to the above two methods
*
* @param request
* @param responseObserver
@ -358,7 +358,7 @@ public class KvServiceGrpcImpl extends KvServiceGrpc.KvServiceImplBase implement
}
/**
* 加锁
* Locking
*
* @param request
* @param responseObserver
@ -450,7 +450,7 @@ public class KvServiceGrpcImpl extends KvServiceGrpc.KvServiceImplBase implement
}
/**
* 解锁
* Unlock
*
* @param request
* @param responseObserver
@ -484,7 +484,7 @@ public class KvServiceGrpcImpl extends KvServiceGrpc.KvServiceImplBase implement
}
/**
* 锁续活
* Lock renewal
*
* @param request
* @param responseObserver
@ -520,7 +520,7 @@ public class KvServiceGrpcImpl extends KvServiceGrpc.KvServiceImplBase implement
}
/**
* 带超时时间的 put
* PUT with timeout
*
* @param request
* @param responseObserver
@ -549,7 +549,7 @@ public class KvServiceGrpcImpl extends KvServiceGrpc.KvServiceImplBase implement
}
/**
* 续活带有超时时间的 key
* Reactivate the key with a timeout period
*
* @param request
* @param responseObserver

View File

@ -64,7 +64,7 @@ public class PDRestService implements InitializingBean {
private StoreMonitorDataService storeMonitorDataService;
/**
* 初始化
* initialize
*
* @throws Exception
*/

View File

@ -150,7 +150,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
//}
/**
* 初始化
* initialize
*/
@PostConstruct
public void init() throws PDException {
@ -160,7 +160,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
RaftEngine.getInstance().addStateListener(this);
RaftEngine.getInstance().addStateListener(configService);
RaftEngine.getInstance().init(pdConfig.getRaft());
//pdConfig = configService.loadConfig(); onLeaderChanged 中加载
//pdConfig = configService.loadConfig(); onLeaderChanged
storeNodeService = new StoreNodeService(pdConfig);
partitionService = new PartitionService(pdConfig, storeNodeService);
taskService = new TaskScheduleService(pdConfig, storeNodeService, partitionService);
@ -173,7 +173,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
RaftEngine.getInstance().addStateListener(partitionService);
pdConfig.setIdService(idService);
// 接收心跳消息
// Receive a heartbeat message
PDPulseSubject.listenPartitionHeartbeat(new PulseListener<PartitionHeartbeatRequest>() {
@Override
public void onNext(PartitionHeartbeatRequest request) throws Exception {
@ -192,7 +192,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
});
/**
* 监听分区指令并转发给 Store
// Listen for partition commands and forward them to Store
*/
partitionService.addInstructionListener(new PartitionInstructionListener() {
private PartitionHeartbeatResponse.Builder getBuilder(Metapb.Partition partition) throws
@ -254,7 +254,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
});
/**
* 监听分区状态改变消息并转发给 Client
// Listen for partition status change messages and forward them to Client
*/
partitionService.addStatusListener(new PartitionStatusListener() {
@Override
@ -295,7 +295,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
});
/**
* 监听 store 状态改变消息并转发给 Client
// Listen for store status change messages and forward them to Client
*/
storeNodeService.addStatusListener(new StoreStatusListener() {
@ -343,7 +343,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
/**
* <pre>
* 注册 store首次注册会生成新的 store_idstore_id store 唯一标识
* Register a store, and the first registration generates a new store_id, store_id is the unique identifier of the store
* </pre>
*/
@Override
@ -363,14 +363,13 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
response = Pdpb.RegisterStoreResponse.newBuilder().setHeader(newErrorHeader(e)).build();
log.error("registerStore exception: ", e);
}
// 拉取所有分区信息并返回
observer.onNext(response);
observer.onCompleted();
}
/**
* 根据 store_id 查找 store
* Find the store based on store_id
*/
@Override
public void getStore(Pdpb.GetStoreRequest request,
@ -395,7 +394,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
/**
* <pre>
* 修改 Store 状态等信息
* Modify information such as the status of the store.
* </pre>
*/
@Override
@ -409,10 +408,10 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
try {
Metapb.StoreState state = request.getStore().getState();
Long storeId = request.getStore().getId();
// 处于 Pending 状态才可以上线
// In the Pending state, you can go online
Metapb.Store lastStore = storeNodeService.getStore(request.getStore().getId());
if (lastStore == null) {
// storeId 不存在抛出异常
// storeId does not exist, an exception is thrown
throw new PDException(Pdpb.ErrorType.STORE_ID_NOT_EXIST_VALUE,
String.format("Store id %d does not exist!", storeId));
}
@ -437,7 +436,8 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
}
logService.insertLog(LogService.NODE_CHANGE, LogService.GRPC, request.getStore());
// 检查失败状态改为 Pending把错误原因返回去
// If the check fails, the status will be changed to Pending, and the reason for the
// error will be returned
if (state.equals(Metapb.StoreState.Up)) {
int cores = 0;
long id = request.getStore().getId();
@ -445,7 +445,8 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
int nodeCount = 0;
for (Metapb.Store store : stores) {
if (store.getId() == id) {
// 获取之前注册的 store 中的 cores 作为验证参数
// Get the cores from the previously registered store as a validation
// parameter
cores = store.getCores();
}
if (store.getState().equals(Metapb.StoreState.Up)) {
@ -465,7 +466,8 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
}
Metapb.Store store = request.getStore();
// 下线之前先判断一下活跃机器数是否大于最小阈值
// Before going offline, check whether the number of active machines is greater than
// the minimum threshold
if (state.equals(Metapb.StoreState.Tombstone)) {
List<Metapb.Store> activeStores = storeNodeService.getActiveStores();
if (lastStore.getState() == Metapb.StoreState.Up
@ -479,7 +481,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
"check activeStores or online shardsList size");
}
if (lastStore.getState() == Metapb.StoreState.Exiting) {
// 如果已经是下线中的状态则不作进一步处理
// If it is already in the offline state, no further processing will be made
throw new PDException(Pdpb.ErrorType.Store_Tombstone_Doing_VALUE,
"Downline is in progress, do not resubmit");
}
@ -488,15 +490,16 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
if (resultMap.get("current_store_is_online") != null
&& (boolean) resultMap.get("current_store_is_online")) {
log.info("updateStore removeActiveStores store {}", store.getId());
// 将在线的 store 的状态设置为下线中等待副本迁移
// Set the status of the online store to Offline and wait for the replica
// to be migrated
store = Metapb.Store.newBuilder(lastStore)
.setState(Metapb.StoreState.Exiting).build();
// 进行分区迁移操作
// Perform partition migration operations
taskService.movePartitions((Map<Integer, KVPair<Long, Long>>) resultMap.get(
"movedPartitions"));
} else {
// store 已经离线的不做副本迁移
// 将状态改为 Tombstone
// If the store is offline, the replica is not migrated
// Change the status to Tombstone
}
} else {
throw new PDException(Pdpb.ErrorType.UPDATE_STORE_STATE_ERROR_VALUE,
@ -505,7 +508,6 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
"the partitions of current store!");
}
}
// 替换 license 都走 grpc
store = storeNodeService.updateStore(store);
response =
Pdpb.SetStoreResponse.newBuilder().setHeader(okHeader).setStore(store).build();
@ -518,9 +520,6 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
observer.onCompleted();
}
/**
* 返回所有的 store,exclude_offline_stores=true返回活跃的 stores
*/
@Override
public void getAllStores(Pdpb.GetAllStoresRequest request,
io.grpc.stub.StreamObserver<Pdpb.GetAllStoresResponse> observer) {
@ -548,7 +547,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
/**
* 处理 store 心跳
* Handle store heartbeats
*/
@Override
public void storeHeartbeat(Pdpb.StoreHeartbeatRequest request,
@ -595,7 +594,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
/**
* <pre>
* 查找 key 所属的分区
* Find the partition to which the key belongs
* </pre>
*/
@Override
@ -624,7 +623,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
/**
* <pre>
* 查找 HashCode 所属的分区
* Find the partition to which the HashCode belongs
* </pre>
*/
@Override
@ -651,7 +650,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
/**
* 根据 partition_id 查找 partition
* Find partition based on partition_id
*/
@Override
public void getPartitionByID(Pdpb.GetPartitionByIDRequest request,
@ -684,7 +683,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
/**
* <pre>
* 更新分区信息主要用来更新分区 key 范围调用此接口需谨慎否则会造成数据丢失
* Update partition information, mainly used to update the partition key range, call this API with caution, otherwise it will cause data loss.
* </pre>
*/
@Override
@ -709,7 +708,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
/**
* 根据 partition_id 查找 partition
* Find partition based on partition_id
*/
@Override
public void delPartition(Pdpb.DelPartitionRequest request,
@ -740,7 +739,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
/**
* 给定 key 范围查找所属的 partition 集合
* The set of partitions to which a given key range looks
*/
@Override
public void scanPartitions(Pdpb.ScanPartitionsRequest request,
@ -769,7 +768,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
/**
* 获得图信息
* Get graph information
*/
@Override
public void getGraph(GetGraphRequest request,
@ -800,7 +799,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
/**
* 修改图信息
* Modify the diagram information
*/
@Override
public void setGraph(Pdpb.SetGraphRequest request,
@ -824,7 +823,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
/**
* 获得图信息
* Get graph information
*/
@Override
public void delGraph(Pdpb.DelGraphRequest request,
@ -852,7 +851,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
/**
* <pre>
* 根据条件查询分区信息包括 StoreGraph 等条件
* Query partition information based on conditions, such as Store and Graph
* </pre>
*/
@Override
@ -862,7 +861,8 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
redirectToLeader(PDGrpc.getQueryPartitionsMethod(), request, observer);
return;
}
//TODO 临时采用遍历方案后续使用 rocksdb 存储时通过 kv 索引实现
// The traversal scheme is used temporarily, and when the rocksdb storage is used in
// the future, it is implemented through KV indexes
Metapb.PartitionQuery query = request.getQuery();
List<Metapb.Partition> partitions = partitionService.getPartitions(query.getGraphName());
List<Metapb.Partition> result = new ArrayList<>();
@ -943,7 +943,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
/**
* 获取集群成员信息
* Obtain cluster member information
*/
@Override
public void getMembers(Pdpb.GetMembersRequest request,
@ -992,7 +992,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
/**
* 读取 PD 配置
* Read the PD configuration
*/
@Override
public void getPDConfig(Pdpb.GetPDConfigRequest request,
@ -1016,7 +1016,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
/**
* 修改 PD 配置
* Modify the PD configuration
*/
@Override
public void setPDConfig(Pdpb.SetPDConfigRequest request,
@ -1028,13 +1028,13 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
Pdpb.SetPDConfigResponse response = null;
try {
if (request.getPdConfig().getShardCount() % 2 != 1) {
// 副本数奇偶校验
// Parity of the number of replicas
throw new PDException(Pdpb.ErrorType.SET_CONFIG_SHARD_COUNT_ERROR_VALUE,
"shard count must be an odd number!");
}
if (request.getPdConfig().getShardCount() >
storeNodeService.getActiveStores().size()) {
// 不能大于活跃的 store 数量
// It can't be greater than the number of active stores
throw new PDException(Pdpb.ErrorType.SET_CONFIG_SHARD_COUNT_ERROR_VALUE,
"shard count can't be greater than the number of active " +
"stores!");
@ -1042,7 +1042,8 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
int oldShardCount = configService.getPDConfig().getShardCount();
int newShardCount = request.getPdConfig().getShardCount();
if (newShardCount > oldShardCount) {
// 如果副本数增大则检查 store 内部的资源是否够用
// If the number of replicas increases, check whether the resources inside the
// store are sufficient
if (!isResourceEnough(oldShardCount, newShardCount)) {
throw new PDException(Pdpb.ErrorType.SET_CONFIG_SHARD_COUNT_ERROR_VALUE,
"There is not enough disk space left!");
@ -1063,7 +1064,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
/**
* 读取图空间配置
* Read the graph space configuration
*/
@Override
public void getGraphSpace(Pdpb.GetGraphSpaceRequest request,
@ -1086,7 +1087,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
/**
* 修改图空间配置
* Modify the graph space configuration
*/
@Override
public void setGraphSpace(Pdpb.SetGraphSpaceRequest request,
@ -1108,7 +1109,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
/**
* <pre>
* 数据分裂
* Data fragmentation
* </pre>
*/
@Override
@ -1154,7 +1155,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
/**
* store 之间平衡数据
* Balance data between stores
*/
@Override
public void movePartition(Pdpb.MovePartitionRequest request,
@ -1179,7 +1180,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
/**
* <pre>
* 获取集群健康状态
* Obtain the cluster health status
* </pre>
*/
@Override
@ -1199,7 +1200,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
/**
* <pre>
* 汇报分区分裂等任务执行结果
* Report the results of tasks such as partition splitting
* </pre>
*/
@Override
@ -1280,7 +1281,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
//}
/**
* 更新 peerList
* Renewal peerList
*/
@Override
public void changePeerList(Pdpb.ChangePeerListRequest request,
@ -1395,7 +1396,6 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
try {
Metapb.Store store = storeNodeService.getStore(storeId);
if (Metapb.StoreState.Tombstone == store.getState()) {
// 只有已经被下线 (Tombstone) store 可以被删除
storeNodeService.removeStore(storeId);
response = Pdpb.DetStoreResponse.newBuilder()
.setHeader(okHeader)
@ -1438,35 +1438,35 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
}
/**
* 检查 store 资源是否够用
* Check that the store resources are sufficient
*/
public boolean isResourceEnough(int oldShardCount, int newShardCount) {
// 活跃的 store 的资源是否够用
// Whether the resources of the active store are sufficient
try {
float expansionRatio = newShardCount / oldShardCount; // 占用的存储空间膨胀的倍数
// 当前占用的空间
// The multiple of the storage space occupied
float expansionRatio = newShardCount / oldShardCount;
// The space currently occupied
long currentDataSize = 0L;
// 数据膨胀后占用的空间
// The space occupied after data bloat
long newDataSize = 0L;
// 总的可用空间
// Total free space
long totalAvaible = 0L;
// 统计当前占用的存储空间
// Statistics on the current storage space
for (Metapb.Store store : storeNodeService.getStores()) {
List<Metapb.GraphStats> graphStatsList = store.getStats().getGraphStatsList();
for (Metapb.GraphStats graphStats : graphStatsList) {
currentDataSize += graphStats.getApproximateSize();
}
}
// 估计数据膨胀后占用的存储空间
// Estimate the storage space consumed after data bloat
newDataSize = (long) Math.ceil(currentDataSize * expansionRatio);
// 统计所有活跃的 store 里面可用的空间
// Count the available space in all active stores
List<Metapb.Store> activeStores = storeNodeService.getActiveStores();
for (Metapb.Store store : activeStores) {
Metapb.StoreStats storeStats = store.getStats();
totalAvaible += storeStats.getAvailable();
}
// 考虑当分区均匀分配的情况下资源是否可用
// Consider whether resources are available when partitions are evenly distributed
return totalAvaible > newDataSize - currentDataSize;
} catch (PDException e) {
e.printStackTrace();
@ -1476,7 +1476,7 @@ public class PDService extends PDGrpc.PDImplBase implements ServiceGrpc, RaftSta
/**
* <pre>
* rocksdb 进行 compaction
* Compaction on rocksdb
* </pre>
*/
@Override

View File

@ -51,13 +51,13 @@ public class UpgradeService {
var dataVersion = getDataVersion();
log.info("now db data version : {}", dataVersion);
for (VersionUpgradeScript script : factory.getScripts()) {
// 执行过run once的跳过
// Executed, run once skipped
if (isExecuted(script.getClass().getName()) && script.isRunOnce()) {
log.info("Script {} is Executed and is run once", script.getClass().getName());
continue;
}
// 判断跳过的条件
// Determine the conditions for skipping
if (dataVersion == null && !script.isRunWithoutDataVersion() || dataVersion != null &&
!versionCompare(
dataVersion,

View File

@ -40,7 +40,8 @@ public interface VersionUpgradeScript {
String getLowVersion();
/**
* pd中没有data version的时候是否执行. 一般是对应362之前的版本
* If there is no data version in the PD, whether to execute the . Generally, it corresponds
* to 3.6.2 previous versions
*
* @return run when pd has no data version
*/

View File

@ -41,7 +41,7 @@ import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
/**
* watch订阅响应处理类
* Watch subscription and response processing classes
**/
@Slf4j
public class KvWatchSubject {
@ -57,7 +57,7 @@ public class KvWatchSubject {
BiPredicate<String, String> startWith = String::startsWith;
/**
* 会使用以下三组key:
* The following three sets of keys will be used:
* clients -> W@KW@key@clientId
* rocksdb key1 ->W@KW@key@clientId
* rocksdb key2 ->W@clientId@KW@key@clientId
@ -86,12 +86,13 @@ public class KvWatchSubject {
}
/**
* 增加观察者
* Increase observers
*
* @param key 观察的key
* @param clientId 客户端标识
* @param key The key of the observation
* @param clientId Client identity
* @param observer
* @param delimiter 观察类型标识符对前缀监听或者对key的监听可以通过此参数区分
* @param delimiter Observe the type identifier, listen to the prefix or listen to the key
* can be distinguished by this parameter
* @throws PDException
*/
public void addObserver(String key, long clientId, StreamObserver<WatchResponse> observer,
@ -111,11 +112,13 @@ public class KvWatchSubject {
}
/**
* 通知观察者方法key和prefix都使用此方法predicate不同
* The notification observer method, which is used by both key and prefix, is different from
* predicate
*
* @param key
* @param watchType 观察类型一般是增加和删除
* @param predicate 判断等于或者是前匹配用来适配key或prefix观察
* @param watchType Observation types, generally additions and deletions
* @param predicate Determine whether it is equal or pre-matched, and use it to adapt to the
* key or prefix observation
* @param kvs
* @throws PDException
*/
@ -177,10 +180,10 @@ public class KvWatchSubject {
}
/**
* 续活客户端
* 1.往客户端发一个alive的消息带重试哈
* 2.如果有响应则续活之前保存的那两组key
* 3.如果多次都失败则删除内存和rocksdb的数据
* Renew the client
* 1. Send an alive message to the client with a retry
* 2. If there is a response, the two sets of keys saved before will be reactivated
* 3. If it fails multiple times, delete the data of memory and rocksdb
*/
public void keepClientAlive() {
WatchResponse testAlive = WatchResponse.newBuilder().setState(WatchState.Alive).build();
@ -256,7 +259,7 @@ public class KvWatchSubject {
}
/**
* 通知客户端leader切换了重连
* Notify the client that the leader has switched and reconnect
*/
public void notifyClientChangeLeader() {
WatchResponse response =

View File

@ -31,7 +31,7 @@ management:
grpc:
port: 8686
# grpc的服务地址
# GRPC's service address
host: 127.0.0.1
netty-server:
max-inbound-message-size: 100MB
@ -44,37 +44,38 @@ server:
port: 8620
pd:
# 定期检查集群是否健康的时间间隔,单位秒
# Periodically check whether the cluster is healthy at intervals, in seconds
patrol-interval: 300
# 存储路径
# Storage path
data-path: tmp/pd/8610
# 最少节点数,少于该数字,集群停止入库
# If the minimum number of nodes is less than this number, the cluster will stop being stored
initial-store-count: 1
# 初始store列表在列表内的store自动激活
# The initial store list is automatically activated in the store
initial-store-list: 127.0.0.1:8502
raft:
# 本机raft服务地址
# The address of the local raft service
address: 127.0.0.1:8610
# PD集群服务地址
# The service address of the PD cluster
peers-list: 127.0.0.1:8610,127.0.0.1:8611,127.0.0.1:8612
# raft rpc读写超时时间,单位毫秒
# The read and write timeout period of the raft rpc, in milliseconds
rpc-timeout: 10000
# 快照生成时间间隔,单位秒
# The interval between snapshot generation, in seconds
snapshotInterval: 300
metrics: true
store:
# store心跳超时时间超过该时间认为store临时不可用转移Leader到其他副本,单位秒
# If the store heartbeat timeout period exceeds this time, the store is temporarily unavailable and the leader is transferred to another replica in seconds
keepAlive-timeout: 300
# store下线时间。超过该时间认为store永久不可用分配副本到其他机器单位秒
# The time when the store went offline. After that time, the store is considered permanently unavailable, and the replica is allocated to another machine, in seconds
max-down-time: 86400
partition:
# 默认每个分区副本数
# Default number of replicas per partition
default-shard-count: 3
# 默认每机器最大副本数,初始分区数= store-max-shard-count * store-number / default-shard-count
# The default maximum number of replicas per machine, the initial number of partitions= store-max-shard-count * store-number / default-shard-count
store-max-shard-count: 12
discovery:
#客户端注册后,无心跳最长次数,超过后,之前的注册信息会被删除
# After the client registers, the maximum number of heartbeats is not reached, the previous
# registration information will be deleted
heartbeat-try-count: 3

View File

@ -41,31 +41,21 @@ pd:
patrol-interval: 3000000
data-path: tmp/8686
# 最少节点数,少于该数字,集群停止入库
initial-store-count: 1
# 初始store列表在列表内的store自动激活
initial-store-list: 127.0.0.1:8500
raft:
address: 127.0.0.1:8610
# raft集群
peers-list: 127.0.0.1:8610
# raft rpc读写超时时间,单位毫秒
rpc-timeout: 10000
# 快照生成时间间隔,单位秒
snapshotInterval: 30000
metrics: true
store:
# store心跳超时时间超过该时间认为store临时不可用转移Leader到其他副本,单位秒
keepAlive-timeout: 300
# store下线时间。超过该时间认为store永久不可用分配副本到其他机器单位秒
max-down-time: 180000
partition:
# 默认每个分区副本数
default-shard-count: 3
# 默认每机器最大副本数,初始分区数= store-max-shard-count * store-number / default-shard-count
store-max-shard-count: 12
discovery:
#客户端注册后,无心跳最长次数,超过后,之前的注册信息会被删除
heartbeat-try-count: 3

View File

@ -41,31 +41,20 @@ pd:
patrol-interval: 3000000
data-path: tmp/8686
# 最少节点数,少于该数字,集群停止入库
initial-store-count: 1
# 初始store列表在列表内的store自动激活
initial-store-list: 127.0.0.1:8501,127.0.0.1:8502,127.0.0.1:8503
#initial-store-list: 127.0.0.1:8501
raft:
address: 127.0.0.1:8610
# raft集群
peers-list: 127.0.0.1:8610
# raft rpc读写超时时间,单位毫秒
rpc-timeout: 10000
# 快照生成时间间隔,单位秒
snapshotInterval: 30000
metrics: true
store:
# store心跳超时时间超过该时间认为store临时不可用转移Leader到其他副本,单位秒
keepAlive-timeout: 300
# store下线时间。超过该时间认为store永久不可用分配副本到其他机器单位秒
max-down-time: 180000
partition:
# 默认每个分区副本数
default-shard-count: 3
# 默认每机器最大副本数,初始分区数= store-max-shard-count * store-number / default-shard-count
store-max-shard-count: 6
discovery:
#客户端注册后,无心跳最长次数,超过后,之前的注册信息会被删除
heartbeat-try-count: 3

View File

@ -39,7 +39,6 @@ server:
port: 8621
pd:
# 集群ID区分不同的PD集群
cluster_id: 1
patrol-interval: 300000
data-path: tmp/8687
@ -48,26 +47,17 @@ pd:
raft:
enable: true
address: 127.0.0.1:8611
# raft集群
peers-list: 127.0.0.1:8610,127.0.0.1:8611,127.0.0.1:8612
# raft rpc读写超时时间,单位毫秒
rpc-timeout: 10000
# 快照生成时间间隔,单位秒
snapshotInterval: 300
metrics: true
# 初始store列表在列表内的store自动激活
initial-store-list: 127.0.0.1:8501,127.0.0.1:8502,127.0.0.1:8503
store:
# store心跳超时时间超过该时间认为store临时不可用转移Leader到其他副本,单位秒
keepAlive-timeout: 300
# store下线时间。超过该时间认为store永久不可用分配副本到其他机器单位秒
max-down-time: 1800
partition:
# 默认每个分区副本数
default-shard-count: 3
# 默认每机器最大副本数,初始分区数= store-max-shard-count * store-number / default-shard-count
store-max-shard-count: 3
discovery:
#客户端注册后,无心跳最长次数,超过后,之前的注册信息会被删除
heartbeat-try-count: 3

View File

@ -39,7 +39,6 @@ server:
port: 8622
pd:
# 集群ID区分不同的PD集群
cluster_id: 1
patrol-interval: 300000
data-path: tmp/8688
@ -48,26 +47,17 @@ pd:
raft:
enable: true
address: 127.0.0.1:8612
# raft集群
peers-list: 127.0.0.1:8610,127.0.0.1:8611,127.0.0.1:8612
# raft rpc读写超时时间,单位毫秒
rpc-timeout: 10000
# 快照生成时间间隔,单位秒
snapshotInterval: 300
metrics: true
# 初始store列表在列表内的store自动激活
initial-store-list: 127.0.0.1:8501,127.0.0.1:8502,127.0.0.1:8503
store:
# store心跳超时时间超过该时间认为store临时不可用转移Leader到其他副本,单位秒
keepAlive-timeout: 300
# store下线时间。超过该时间认为store永久不可用分配副本到其他机器单位秒
max-down-time: 1800
partition:
# 默认每个分区副本数
default-shard-count: 3
# 默认每机器最大副本数,初始分区数= store-max-shard-count * store-number / default-shard-count
store-max-shard-count: 3
discovery:
#客户端注册后,无心跳最长次数,超过后,之前的注册信息会被删除
heartbeat-try-count: 3

View File

@ -318,8 +318,6 @@ public class PDClientTest extends BaseClientTest {
Metapb.PDConfig config = pdClient.getPDConfig();
pdClient.setPDConfig(config.toBuilder().setMaxShardsPerStore(12).build());
System.out.println(pdClient.getPDConfig());
// 开始分区分裂
pdClient.splitData();
} catch (Exception e) {
e.printStackTrace();

View File

@ -244,7 +244,6 @@ public class PartitionCacheTest {
this.cache.updatePartition(partition2);
System.out.println(this.cache.debugCacheByGraphName("graph0"));
// 中间有缺失
var partition3 = createPartition(1, "graph0", 2, 3);
this.cache.updatePartition(partition3);
System.out.println(this.cache.debugCacheByGraphName("graph0"));