最近线上redshift disk时不时会有一个spike的问题, 需要调查下。
第一步 先监控问题
通过如下的java代码可以获取redshift的disk当前使用率:
/**
* Note this method will return the prod redshift disk usage.
*
* https://console.aws.amazon.com/iam/home?nc2=h_m_sc#/users/cloudwatch-metric-query
*
* @return map {key=cluster name, value = cluster disk usage}
*/
public static Map<String, Double> diskUsage() {
AmazonCloudWatchAsync client = AmazonCloudWatchAsyncClient.asyncBuilder()
.withRegion(Regions.fromName("us-west-2"))
.withCredentials(new AWSStaticCredentialsProvider(new AWSCredentials() {
@Override
public String getAWSAccessKeyId() {
return "abcd";
}
@Override
public String getAWSSecretKey() {
return "efg";
}
})).build();
GetMetricDataRequest req = new GetMetricDataRequest();
req.setStartTime(new Date(System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(10)));
req.setEndTime(new Date(System.currentTimeMillis()));
String searchExpr = "SEARCH('{AWS/Redshift,ClusterIdentifier} MetricName=\"PercentageDiskSpaceUsed\"', 'Average', 60)";
MetricDataQuery e1 = new MetricDataQuery().withId("e1").withExpression(searchExpr).withReturnData(true);
req.setMetricDataQueries(Arrays.asList(e1));
GetMetricDataResult r = client.getMetricData(req);
System.out.println(r);
Map<String, Double> cluster2Disk = new HashMap<>();
r.getMetricDataResults().forEach(m -> {
if (!m.getValues().isEmpty()) {
double v = m.getValues().get(m.getValues().size() - 1);
String name = m.getLabel();
cluster2Disk.put(name, v);
}
});
return cluster2Disk;
}
然后我们得到了图以及SPIKE:
第2步 然后就是调查问题了。
在这里有很重要的一点就是提前告警
因为可以看到 这个spike在短时间内从正常的35% 冲到了100%。
如果不提前调查的话 会出现disk满的时候已经无法执行query的情况。
A. 找到当时正在执行的query
disk占用有很多原因。 常见的原因有:参考 Troubleshoot High or Full Disk Usage in Amazon Redshift
- Distribution and sort key
- Query processing
- Tables with VARCHAR(MAX) columns
- High column compression
- Maintenance operations
- Cartesian products with cross-joins
- Minimum table size
- Tombstone blocks
- Copying a large file
select query, pid, substring, workmem, starttime, endtime, elapsed, rows, bytes
from svl_qlog join svl_query_summary using(query)
where starttime > '2021-09-16T23:06:57.574843'
and is_diskbased = 't' order by rows desc;
B. 查看这个query使用的workmem
select query, step, rows, workmem, label, is_diskbased
from svl_query_summary
where query = 170281811
order by workmem
这里diskbased=t 代表该查询过程中会缓存到disk上。
C. 查看完整的query
select * from stl_query where query=170281811
然后就是sql优化的过程了。
# 更新 新的发现
上面说到redshift可能会有很多原因导致磁盘多了很多, 最终我们发现是tombstones导致的磁盘变大。
redshift中的update insert delete 都会导致block被标记为tombstone随后被vacuum掉。
如下的sqlquery可以查询tomstones: (注意这个是内存视图 不是持久化的视图 只会保存一段时间。 大概是几个小时的样子。)
如下的这个图显示有140G的tombstones
select trim(name) as tablename, count(case when tombstone > 0 then 1 else null end) as tombstones from svv_diskusage group by 1 having count(case when tombstone > 0 then 1 else null end) > 0 order by 2 desc;
tablename | tombstones
---------------------------------+------------
data__xxxx | 140118
参考
1. Troubleshoot High or Full Disk Usage in Amazon Redshift
2.Demystifying Redshift — What's Up with My Disks? | Sisense