場景
項目使用了elasticsearch
技術來進行數據搜索,而單天的數據量比較大,隨着時間的流逝,整個elasticsearch
集羣所佔的空間會越來越大。如果不進行定時的刪除,就會導致存儲滿載,進而影響系統。而elasticsearch
支持使用curl
命令調用elasticsearch
集羣命令,定時刪除某一天的索引數據。但是沒有辦法刪除某個時間點之前的數據。那麼假如有一天腳本沒有執行,那沒有執行的日期數據就沒辦法刪除,只能手動去刪除。這樣還是會存在問題的。這個時候,就需要有一個程序,可以自定義對某個索引進行掃描,刪除自定義天數的數據。這樣,不管什麼時候執行,都會將保留週期之外的索引數據給刪除掉。
環境
軟件 | 版本 |
---|---|
JDK | 8 |
spring-data-elasticsearch | 3.1.10.RELEASE |
spring-boot | 2.1.8.RELEASE |
elasticsearch | 6.2.2 |
正文
流程梳理
接下來,讓我們梳理一下整個程序的開發流程,如下:
show the code
對於程序員來說,除了理論要溜,代碼也得溜。所以,接下來會展示整個過程有用的代碼。
maven依賴
這裏只展示主要的依賴,像微服務Spring-cloud
相關的依賴就不放在裏面了。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
</parent>
<dependencies>
<!-- elasticsearch -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
</dependencies>
配置文件
配置文件主要是寫在application.properties
文件裏面,下面展示一個樣例:
# es配置
spring.data.elasticsearch.cluster-nodes=localhost:9300
spring.data.elasticsearch.cluster-name=test
# 過期索引配置,值爲天數
index.delindex.service-test=7
index.delindex.service-test2=7
主要函數
配置類
@Component
@Configuration
@PropertySource(value = {"classpath:/application.properties"}, encoding = "utf-8")
@ConfigurationProperties(prefix = "index")
@Getter
@Setter
public class ElasticsearchDelIndexConfig {
private Map delindex = new HashMap();
}
處理類
因爲功能比較簡單,所以是直接將代碼放到主類裏面,直接跑的。代碼如下,如果有需求,直接複製就可以跑起來的。
@Slf4j
@EnableEurekaClient
@SpringBootApplication
public class ElasticsearchDelApplication implements CommandLineRunner {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Autowired
private ElasticsearchDelIndexConfig delIndexConfig;
/**
* 主進程
*
* @param args
*/
public static void main(String[] args) {
SpringApplication.run(ElasticsearchDelApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
while (true) {
delIndexConfig.getDelindex().forEach((k, v) -> {
log.info("索引起始名稱爲{},保留週期爲{}天", k, v);
Set<String> allIndexes = getAllIndices();
if (allIndexes.size() > 0) {
log.info("當前索引總數爲:{}", allIndexes.size());
List<String> timeoutList = getIndicesTimeout(allIndexes, String.valueOf(k), Long.parseLong(String.valueOf(v)), TimeUnit.DAYS);
if (timeoutList.size() > 0) {
log.info("對於前綴爲 {} 的索引 過期數目爲:{}", k, timeoutList.size());
timeoutList.forEach(indexName -> {
if (elasticsearchTemplate.deleteIndex(indexName)) {
log.info("成功刪除 {} 索引", indexName);
} else {
log.error("刪除 {} 索引 失敗", indexName);
}
});
}
}
});
log.info("休眠 10 分鐘");
ThreadUtil.sleep(10, TimeUnit.MINUTES);
}
}
/**
* 獲取所有index
*/
public Set<String> getAllIndices() {
ActionFuture<IndicesStatsResponse> isr = elasticsearchTemplate.getClient().admin().indices().stats(new IndicesStatsRequest().all());
Set<String> set = isr.actionGet().getIndices().keySet();
return set;
}
/**
* 獲取指定索引的創建時間
* @param indexName 索引名稱
* @return 索引的創建時間
*/
public String getCreateTimeForIndex(String indexName) {
String createTime = elasticsearchTemplate.getClient().admin()
.indices().getSettings(new GetSettingsRequest().indices(indexName))
.actionGet().getIndexToSettings().get(indexName)
.getAsSettings("index").get("creation_date");
return createTime;
}
/**
* 獲取前綴相同的過時索引
* @param allIndices 索引列表
* @param indexName 要過濾的索引前綴
* @param time 超時時間
* @param timeUnit 時間單位
* @return 超時的索引列表
*/
public List<String> getIndicesTimeout(Set<String> allIndices, String indexName, Long time, TimeUnit timeUnit) {
List<String> list = new ArrayList<>();
allIndices.parallelStream()
.filter(name -> name.startsWith(indexName))
.forEach(one -> {
String createTime = getCreateTimeForIndex(one);
if (System.currentTimeMillis() - Long.parseLong(createTime) > timeUnit.toMillis(time)) {
log.info("索引 {} 已經過期,創建時間爲{}", one, createTime);
list.add(one);
}
});
return list;
}
}
結果
程序跑起來之後,elasticsearch
集羣的特定索引的過期數據都會被刪除。
總結
spring-boot
可以封裝了很多開發細節,減少了我們很多工作。在懂得內部原理的時候,的確很好用。不過對於初學者,在使用spring-boot
的時候,記得學習裏面內部的原理。這樣遇到問題才能快速鎖定問題,並解決。
隨緣求贊
如果我的文章對大家產生了幫忙,可以在文章底部點個贊或者收藏;
如果有好的討論,可以留言;
如果想繼續查看我以後的文章,可以點擊關注
可以掃描以下二維碼,關注我的公衆號:楓夜之求索閣,查看我最新的分享!