Skip to content

Commit

Permalink
[Enhancement](config) optimize behavior of default_storage_medium (#2…
Browse files Browse the repository at this point in the history
  • Loading branch information
Centurybbx authored Jul 20, 2023
1 parent 7d48868 commit ab11dea
Show file tree
Hide file tree
Showing 15 changed files with 180 additions and 62 deletions.
2 changes: 1 addition & 1 deletion docs/en/docs/faq/install-faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ In many cases, we need to troubleshoot problems through logs. The format and vie

Doris supports one BE node to configure multiple storage paths. Usually, one storage path can be configured for each disk. At the same time, Doris supports storage media properties that specify paths, such as SSD or HDD. SSD stands for high-speed storage device and HDD stands for low-speed storage device.

If doris cluster has only one storage medium type, the practice is not specify storage medium in be.conf configuration file. ```Failed to find enough host with storage medium and tag```, generally we got this error for only config SSD medium in be.conf, but default parameter ```default_storage_medium``` in fe is HDD, so there is no HDD storage medium in cluster. There are several ways to fix this, one is modify the parameter in fe.conf and restart fe; the other way is take the SSD config in be.conf away,and the third way is add properties when create table ```{"storage_medium" = "ssd"}```
If the cluster only has one type of medium, such as all HDD or all SSD, the best practice is not to explicitly specify the medium property in be.conf. If encountering the error ```Failed to find enough host with storage medium and tag``` mentioned above, it is generally because be.conf only configures the SSD medium, while the table creation stage explicitly specifies ```properties {"storage_medium" = "hdd"}```; similarly, if be.conf only configures the HDD medium, and the table creation stage explicitly specifies ```properties {"storage_medium" = "ssd"}```, the same error will occur. The solution is to modify the properties parameter in the table creation to match the configuration; or remove the explicit configuration of SSD/HDD in be.conf.

By specifying the storage medium properties of the path, we can take advantage of Doris's hot and cold data partition storage function to store hot data in SSD at the partition level, while cold data is automatically transferred to HDD.

Expand Down
2 changes: 1 addition & 1 deletion docs/zh-CN/docs/faq/install-faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ Observer 角色和这个单词的含义一样,仅仅作为观察者来同步

Doris支持一个BE节点配置多个存储路径。通常情况下,每块盘配置一个存储路径即可。同时,Doris支持指定路径的存储介质属性,如SSD或HDD。SSD代表高速存储设备,HDD代表低速存储设备。

如果集群只有一种介质比如都是HDD或者都是SSD,最佳实践是不用在be.conf中显式指定介质属性。如果遇到上述报错```Failed to find enough host with storage medium and tag```,一般是因为be.conf中只配置了SSD的介质,而fe中参数default_storage_medium默认为HDD,因此建表时会发现没有HDD介质的存储而报错。解决方案可以修改此FE配置并重启FE生效;或者将be.conf中SSD的显式配置去掉;或者建表时增加properties参数 ```properties {"storage_medium" = "ssd"}```均可
如果集群只有一种介质比如都是HDD或者都是SSD,最佳实践是不用在be.conf中显式指定介质属性。如果遇到上述报错```Failed to find enough host with storage medium and tag```,一般是因为be.conf中只配置了SSD的介质,而建表阶段中显式指定了```properties {"storage_medium" = "hdd"}```;同理如果be.conf只配置了HDD的介质,而而建表阶段中显式指定了```properties {"storage_medium" = "ssd"}```也会出现上述错误。解决方案可以修改建表的properties参数与配置匹配;或者将be.conf中SSD/HDD的显式配置去掉即可。

通过指定路径的存储介质属性,我们可以利用Doris的冷热数据分区存储功能,在分区级别将热数据存储在SSD中,而冷数据会自动转移到HDD中。

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,7 @@ private Partition resetPartitionForRestore(OlapTable localTbl, OlapTable remoteT
// replicas
try {
Map<Tag, List<Long>> beIds = Env.getCurrentSystemInfo()
.selectBackendIdsForReplicaCreation(replicaAlloc, null);
.selectBackendIdsForReplicaCreation(replicaAlloc, null, false, false);
for (Map.Entry<Tag, List<Long>> entry : beIds.entrySet()) {
for (Long beId : entry.getValue()) {
long newReplicaId = env.getNextId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class DataProperty implements Writable, GsonPostProcessable {
private String storagePolicy;
@SerializedName(value = "isMutable")
private boolean isMutable = true;
private boolean storageMediumSpecified;

private DataProperty() {
// for persist
Expand Down Expand Up @@ -97,6 +98,10 @@ public String getStoragePolicy() {
return storagePolicy;
}

public boolean isStorageMediumSpecified() {
return storageMediumSpecified;
}

public boolean isMutable() {
return isMutable;
}
Expand All @@ -105,6 +110,10 @@ public void setMutable(boolean mutable) {
isMutable = mutable;
}

public void setStorageMediumSpecified(boolean isSpecified) {
storageMediumSpecified = isSpecified;
}

public static DataProperty read(DataInput in) throws IOException {
if (Env.getCurrentEnvJournalVersion() >= FeMetaVersion.VERSION_108) {
String json = Text.readString(in);
Expand Down Expand Up @@ -164,4 +173,5 @@ public void gsonPostProcess() throws IOException {
// storagePolicy is a newly added field, it may be null when replaying from old version.
this.storagePolicy = Strings.nullToEmpty(this.storagePolicy);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ public Status resetIdsForRestore(Env env, Database db, ReplicaAllocation restore
try {
Map<Tag, List<Long>> tag2beIds =
Env.getCurrentSystemInfo().selectBackendIdsForReplicaCreation(
replicaAlloc, null);
replicaAlloc, null, false, false);
for (Map.Entry<Tag, List<Long>> entry3 : tag2beIds.entrySet()) {
for (Long beId : entry3.getValue()) {
long newReplicaId = env.getNextId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ private static void checkReplicationNum(String val, Database db) throws DdlExcep
ErrorReport.reportDdlException(ErrorCode.ERROR_DYNAMIC_PARTITION_REPLICATION_NUM_FORMAT, val);
}
ReplicaAllocation replicaAlloc = new ReplicaAllocation(Short.valueOf(val));
Env.getCurrentSystemInfo().selectBackendIdsForReplicaCreation(replicaAlloc, null);
Env.getCurrentSystemInfo().selectBackendIdsForReplicaCreation(replicaAlloc, null, false, true);
}

private static void checkReplicaAllocation(ReplicaAllocation replicaAlloc, int hotPartitionNum,
Expand All @@ -237,13 +237,14 @@ private static void checkReplicaAllocation(ReplicaAllocation replicaAlloc, int h
ErrorReport.reportDdlException(ErrorCode.ERROR_DYNAMIC_PARTITION_REPLICATION_NUM_ZERO);
}

Env.getCurrentSystemInfo().selectBackendIdsForReplicaCreation(replicaAlloc, null);
Env.getCurrentSystemInfo().selectBackendIdsForReplicaCreation(replicaAlloc, null, false, true);
if (hotPartitionNum <= 0) {
return;
}

try {
Env.getCurrentSystemInfo().selectBackendIdsForReplicaCreation(replicaAlloc, TStorageMedium.SSD);
Env.getCurrentSystemInfo().selectBackendIdsForReplicaCreation(replicaAlloc, TStorageMedium.SSD, false,
true);
} catch (DdlException e) {
throw new DdlException("Failed to find enough backend for ssd storage medium. When setting "
+ DynamicPartitionProperty.HOT_PARTITION_NUM + " > 0, the hot partitions will store "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,19 +140,17 @@ public class PropertyAnalyzer {

public static final String PROPERTIES_ENABLE_DUPLICATE_WITHOUT_KEYS_BY_DEFAULT =
"enable_duplicate_without_keys_by_default";

private static final Logger LOG = LogManager.getLogger(PropertyAnalyzer.class);
private static final String COMMA_SEPARATOR = ",";
private static final double MAX_FPP = 0.05;
private static final double MIN_FPP = 0.0001;

// For unique key data model, the feature Merge-on-Write will leverage a primary
// key index and a delete-bitmap to mark duplicate keys as deleted in load stage,
// which can avoid the merging cost in read stage, and accelerate the aggregation
// query performance significantly.
// For the detail design, see the [DISP-018](https://cwiki.apache.org/confluence/
// display/DORIS/DSIP-018%3A+Support+Merge-On-Write+implementation+for+UNIQUE+KEY+data+model)
public static final String ENABLE_UNIQUE_KEY_MERGE_ON_WRITE = "enable_unique_key_merge_on_write";
private static final Logger LOG = LogManager.getLogger(PropertyAnalyzer.class);
private static final String COMMA_SEPARATOR = ",";
private static final double MAX_FPP = 0.05;
private static final double MIN_FPP = 0.0001;

/**
* check and replace members of DataProperty by properties.
Expand All @@ -172,15 +170,18 @@ public static DataProperty analyzeDataProperty(Map<String, String> properties, f
long cooldownTimestamp = oldDataProperty.getCooldownTimeMs();
String newStoragePolicy = oldDataProperty.getStoragePolicy();
boolean hasStoragePolicy = false;
boolean storageMediumSpecified = false;

for (Map.Entry<String, String> entry : properties.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (key.equalsIgnoreCase(PROPERTIES_STORAGE_MEDIUM)) {
if (value.equalsIgnoreCase(TStorageMedium.SSD.name())) {
storageMedium = TStorageMedium.SSD;
storageMediumSpecified = true;
} else if (value.equalsIgnoreCase(TStorageMedium.HDD.name())) {
storageMedium = TStorageMedium.HDD;
storageMediumSpecified = true;
} else {
throw new AnalysisException("Invalid storage medium: " + value);
}
Expand Down Expand Up @@ -247,7 +248,12 @@ public static DataProperty analyzeDataProperty(Map<String, String> properties, f
boolean mutable = PropertyAnalyzer.analyzeBooleanProp(properties, PROPERTIES_MUTABLE, true);
properties.remove(PROPERTIES_MUTABLE);

return new DataProperty(storageMedium, cooldownTimestamp, newStoragePolicy, mutable);
DataProperty dataProperty = new DataProperty(storageMedium, cooldownTimestamp, newStoragePolicy, mutable);
// check the state of data property
if (storageMediumSpecified) {
dataProperty.setStorageMediumSpecified(true);
}
return dataProperty;
}

public static short analyzeShortKeyColumnCount(Map<String, String> properties) throws AnalysisException {
Expand Down
Loading

0 comments on commit ab11dea

Please sign in to comment.