摘要:上一節(jié)我們分析了廣告索引的維護有種,全量索引加載和增量索引維護。因為廣告檢索是廣告系統(tǒng)中最為重要的環(huán)節(jié),大家一定要認真理解我們索引設(shè)計的思路,接下來我們來編碼實現(xiàn)索引維護功能。
上一節(jié)我們分析了廣告索引的維護有2種,全量索引加載和增量索引維護。因為廣告檢索是廣告系統(tǒng)中最為重要的環(huán)節(jié),大家一定要認真理解我們索引設(shè)計的思路,接下來我們來編碼實現(xiàn)索引維護功能。
我們來定義一個接口,來接收所有index的增刪改查操作,接口定義一個范型,來接收2個參數(shù),K代表我們索引的健值,V代表返回值。
/** * IIndexAware for 實現(xiàn)廣告索引的增刪改查 * * @author Isaac.Zhang | 若初 */ public interface IIndexAware{ /** * 通過key 獲取索引 */ V get(K key); /** * 添加索引 * @param key * @param value */ void add(K key, V value); /** * 更新索引 */ void update(K key, V value); /** * 刪除索引 */ void delete(K key, V value); }
我們一定要知道,并不是所有的數(shù)據(jù)庫表都需要創(chuàng)建索引,比如User表我們在數(shù)據(jù)檢索的時候其實是不需要的,當然也就沒必要創(chuàng)建索引,并且,也不是表中的所有字段都需要索引,這個也是根據(jù)具體的業(yè)務(wù)來確定字段信息,比如我們接下來要編寫的推廣計劃索引中,推廣計劃名稱就可以不需要。下面,我們來實現(xiàn)我們的第一個正向索引。
首先創(chuàng)建操作推廣計劃的實體對象
/** * AdPlanIndexObject for 推廣計劃索引對象 * 這個索引對象我們沒有添加 推廣計劃名稱 * @author Isaac.Zhang | 若初 */ @Data @NoArgsConstructor @AllArgsConstructor public class AdPlanIndexObject { private Long planId; private Long userId; private Integer planStatus; private Date startDate; private Date endDate; /** * 根據(jù)實際字段來更新索引 */ public void update(AdPlanIndexObject newObject) { if (null != newObject.getPlanId()) { this.planId = newObject.getPlanId(); } if (null != newObject.getUserId()) { this.userId = newObject.getUserId(); } if (null != newObject.getPlanStatus()) { this.planStatus = newObject.getPlanStatus(); } if (null != newObject.getStartDate()) { this.startDate = newObject.getStartDate(); } if (null != newObject.getEndDate()) { this.endDate = newObject.getEndDate(); } } }
然后創(chuàng)建推廣計劃索引實現(xiàn)類,并實現(xiàn)IIndexAware接口。
/** * AdPlanIndexAwareImpl for 推廣計劃索引實現(xiàn)類 * * @author Isaac.Zhang | 若初 */ @Slf4j @Component public class AdPlanIndexAwareImpl implements IIndexAware{ private static Map planIndexObjectMap; /** * 因為操作索引的過程中有可能對索引進行更新,為了防止多線程造成的線程不安全問題,我們不能使用hashmap,需要實現(xiàn)ConcurrentHashMap */ static { planIndexObjectMap = new ConcurrentHashMap<>(); } @Override public AdPlanIndexObject get(Long key) { return planIndexObjectMap.get(key); } @Override public void add(Long key, AdPlanIndexObject value) { log.info("AdPlanIndexAwareImpl before add::{}", planIndexObjectMap); planIndexObjectMap.put(key, value); log.info("AdPlanIndexAwareImpl after add::{}", planIndexObjectMap); } @Override public void update(Long key, AdPlanIndexObject value) { log.info("AdPlanIndexAwareImpl before update::{}", planIndexObjectMap); //查詢當前的索引信息,如果不存在,直接新增索引信息 AdPlanIndexObject oldObj = planIndexObjectMap.get(key); if (null == oldObj) { planIndexObjectMap.put(key, value); } else { oldObj.update(value); } log.info("AdPlanIndexAwareImpl after update::{}", planIndexObjectMap); } @Override public void delete(Long key, AdPlanIndexObject value) { log.info("AdPlanIndexAwareImpl before delete::{}", planIndexObjectMap); planIndexObjectMap.remove(key); log.info("AdPlanIndexAwareImpl after delete::{}", planIndexObjectMap); } }
至此,我們已經(jīng)完成了推廣計劃的索引對象和索引操作的代碼編寫,大家可以參考上面的示例,依次完成推廣單元、推廣創(chuàng)意、地域、興趣、關(guān)鍵詞以及推廣創(chuàng)意和推廣單元的關(guān)聯(lián)索引,或者可直接從 Github傳送門 / Gitee傳送門 下載源碼。
按照上述代碼展示,我們已經(jīng)實現(xiàn)了所有的索引操作的定義,但是實際情況中,我們需要使用這些服務(wù)的時候,需要在每一個Service中@Autowired注入,我們那么多的索引操作類,還不包含后續(xù)還有可能需要新增的索引維度,工作量實在是太大,而且不方便維護,作為一個合格的程序員來說,這是非常不友好的,也許會讓后續(xù)的開發(fā)人員罵娘。
為了防止后續(xù)被罵,我們來編寫一個索引緩存工具類com.sxzhongf.ad.index.IndexDataTableUtils,通過這個索引緩存工具類來實現(xiàn)一次注入,解決后顧之憂。要實現(xiàn)這個工具類,我們需要實現(xiàn)2個接口:org.springframework.context.ApplicationContextAware和org.springframework.core.PriorityOrdered
org.springframework.context.ApplicationContextAware, 統(tǒng)一通過實現(xiàn)該接口的類,來操作Spring容器以及其中的Bean實例。
在Spring中,以Aware為后綴結(jié)束的類,大家可以簡單的理解為應(yīng)用程序想要XXX,比如ApplicationContextAware代表應(yīng)用程序想要ApplicationContext,BeanFactoryAware 表示應(yīng)用程序想要BeanFactory...等等
org.springframework.core.PriorityOrdered組件加載順序,也可以使用org.springframework.core.Ordered
以下代碼為我們的工具類:
package com.sxzhongf.ad.index; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.PriorityOrdered; import org.springframework.stereotype.Component; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * IndexDataTableUtils for 所有索引服務(wù)需要緩存的Java Bean * * 使用方式: * 獲取{@link com.sxzhongf.ad.index.creative.CreativeIndexAwareImpl}索引服務(wù)類 * 如下: * {@code * IndexDataTableUtils.of(CreativeIndexAwareImpl.class) * } * @author Isaac.Zhang | 若初 */ @Component public class IndexDataTableUtils implements ApplicationContextAware, PriorityOrdered { //注入ApplicationContext private static ApplicationContext applicationContext; /** * 定義用于保存所有Index的Map * Class標示我們的索引類 */ private static final MapdataTableMap = new ConcurrentHashMap<>(); @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { IndexDataTableUtils.applicationContext = applicationContext; } /** * 獲取索引服務(wù)緩存 */ public static T of(Class klass) { T instance = (T) dataTableMap.get(klass); //如果獲取到索引bean,直接返回當前bean if (null != instance) { return instance; } //首次獲取索引bean為空,寫入Map dataTableMap.put(klass, bean(klass)); return (T) dataTableMap.get(klass); } /** * 獲取Spring 容器中的Bean對象 */ private static T bean(String beanName) { return (T) applicationContext.getBean(beanName); } /** * 獲取Spring 容器中的Bean對象 */ private static T bean(Class klass) { return (T) applicationContext.getBean(klass); } @Override public int getOrder() { return PriorityOrdered.HIGHEST_PRECEDENCE; } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/75918.html
摘要:各個表數(shù)據(jù)的存儲文件名定義索引對象導(dǎo)出的字段信息依然用為例。通用處理索引類索引之間存在層級劃分,也就是相互之間擁有依賴關(guān)系的劃分加載全量索引其實是增量索引添加的一種特殊實現(xiàn)若初實現(xiàn)廣告推廣計劃的第二層級索引實現(xiàn)。 上一節(jié)我們實現(xiàn)了索引基本操作的類以及索引緩存工具類,本小節(jié)我們開始實現(xiàn)加載全量索引數(shù)據(jù),在加載全量索引數(shù)據(jù)之前,我們需要先將數(shù)據(jù)庫中的表數(shù)據(jù)導(dǎo)出到一份文件中。Lets cod...
摘要:索引設(shè)計介紹在我們廣告系統(tǒng)中,為了我們能更快的拿到我們想要的廣告數(shù)據(jù),我們需要對廣告數(shù)據(jù)添加類似于數(shù)據(jù)庫一樣的索引結(jié)構(gòu),分兩大類正向索引和倒排索引。如何在廣告系統(tǒng)中使用倒排索引核心用途是對各個維度限制的整理。 索引設(shè)計介紹 在我們廣告系統(tǒng)中,為了我們能更快的拿到我們想要的廣告數(shù)據(jù),我們需要對廣告數(shù)據(jù)添加類似于數(shù)據(jù)庫index一樣的索引結(jié)構(gòu),分兩大類:正向索引和倒排索引。 正向索引 通過...
摘要:在前面的過程中,我們創(chuàng)建了個服務(wù)發(fā)現(xiàn)我們使用作為服務(wù)發(fā)現(xiàn)組件,學(xué)習(xí)了的使用。加依賴加注解改配置使用項目三部曲,我們可以快速添加一個新組件,并正常使用這個我沒有在項目中實現(xiàn),但是大家可以和一樣,三部曲搞定。 在前面的過程中,我們創(chuàng)建了4個project: 服務(wù)發(fā)現(xiàn) 我們使用Eureka 作為服務(wù)發(fā)現(xiàn)組件,學(xué)習(xí)了Eureka Server,Eureka Client的使用。 Eureka...
摘要:對的配置和行為進行定制修改匹配路由請求規(guī)則注冊自定義的和添加靜態(tài)資源處理器添加自定義視圖控制器添加自定義方法參數(shù)處理器配置消息轉(zhuǎn)換器清空所有轉(zhuǎn)換器做一個好人。博客園掘金簡書頭條知乎 一個大的系統(tǒng),在代碼的復(fù)用肯定是必不可少的,它能解決: 統(tǒng)一的響應(yīng)處理(可以對外提供統(tǒng)一的響應(yīng)對象包裝) showImg(https://segmentfault.com/img/remote/146000...
摘要:不會記錄數(shù)據(jù)表的列名在接下來的實現(xiàn)中,我們會將自己的系統(tǒng)包裝成一個假的,通過開源工具來實現(xiàn)監(jiān)聽。因為我們只需要中的內(nèi)容,那么我們也就只需要通過實現(xiàn)接口,來自定義一個監(jiān)聽器實現(xiàn)我們的業(yè)務(wù)即可。 MySQL Binlog簡介 什么是binlog? 一個二進制日志,用來記錄對數(shù)據(jù)發(fā)生或潛在發(fā)生更改的SQL語句,并以而進行的形式保存在磁盤中。 binlog 的作用? 最主要有3個用途: ...
閱讀 1767·2021-09-27 14:02
閱讀 3187·2021-09-27 13:36
閱讀 1058·2019-08-30 12:46
閱讀 1845·2019-08-30 10:51
閱讀 3585·2019-08-29 17:02
閱讀 957·2019-08-29 16:38
閱讀 1857·2019-08-29 16:37
閱讀 3041·2019-08-26 10:32