沒想到,這麼簡單的線程池用法,深藏這麼多坑!

又又又踩坑了

生產有個對賬系統,每天需要從渠道端下載對賬文件,然後開始日終對賬。這個系統已經運行了很久,前两天突然收到短信預警,沒有獲取渠道端對賬文件。

ps:對賬系統詳細實現方式:對賬系統設計與實現

本以為又是渠道端搞事情,上去一排查才發現,所有下載任務都被阻塞了。再進一步排查源碼,才發現自己一直用錯了線程池某個方法。

由於線程創建比較昂貴,正式項目中我們都會使用線程池執行異步任務。線程池,使用池化技術保存線程對象,使用的時候直接取出來,用完歸還以便使用。

雖然線程池的使用非常方法非常簡單,但是越簡單,越容易踩坑。細數一下,這些年來因為線程池導致生產事故也有好幾起。

所以今天,小黑哥就針對線程池的話題,給大家演示一下怎麼使用線程池才會踩坑。

希望大家看完,可以完美避開這些坑~

先贊后看,養成習慣。微信搜索「程序通事」,關注就完事了!

慎用 Executors 組件

Java 從 JDK1.5 開始提供線程池的實現類,我們只需要在構造函數內傳入相關參數,就可以創建一個線程池。

不過線程池的構造函數可以說非常複雜,就算最簡單的那個構造函數,也需要傳入 5 個參數。這對於新手來說,非常不方便哇。

也許 JDK 開發者也考慮到這個問題,所以非常貼心給我們提供一個工具類 Executors,用來快捷創建創建線程池。

雖然這個工具類使用真的非常方便,可以少寫很多代碼,但是小黑哥還是建議生產系統還是老老實實手動創建線程池,慎用Executors,尤其是工具類中兩個方法 Executors#newFixedThreadPool與 Executors#newCachedThreadPool。

如果你圖了方便使用上述方法創建了線程池,那就是一顆定時炸彈,說不準那一天生產系統就會。

我們來看兩個,看下這個這兩個方法會有什麼問題。

假設我們有個應用有個批量接口,每次請求將會下載 100w 個文件,這裏我們使用 Executors#newFixedThreadPool批量下載。

下面方法中,我們隨機休眠,模擬真實下載耗時。

為了快速復現問題,調整 JVM 參數為 -Xmx128m -Xms128m 。

private ExecutorService threadPool = Executors.newFixedThreadPool(10);

/**
 * 批量下載對賬文件
 *
 * @return
 */
@RequestMapping("/batchDownload")
public String batchDownload() {
    
    // 模擬下載 100w 個文件
    for (int i = 0; i < 1000000; i++) {
        threadPool.execute(() -> {
            // 隨機休眠,模擬下載耗時
            Random random = new Random();
            try {
                TimeUnit.SECONDS.sleep(random.nextInt(100));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }

    return "process";
}

程序運行之後,多請求幾次這個批量下載方法,程序很快就會 OOM 。

查看 Executors#newFixedThreadPool源碼,我們可以看到這個方法創建了一個默認的 LinkedBlockingQueue 當做任務隊列。

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

這個問題槽點就在於 LinkedBlockingQueue,這個隊列的默認構造方法如下:

/**
 * Creates a {@code LinkedBlockingQueue} with a capacity of
 * {@link Integer#MAX_VALUE}.
 */
public LinkedBlockingQueue() {
    this(Integer.MAX_VALUE);
}

創建 LinkedBlockingQueue 隊列時,如果我們不指定隊列數量,默認數量上限為 Integer.MAX_VALUE。這麼大的數量,我們簡直可以當做無界隊列了。

上面我們使用 newFixedThreadPool,我們僅使用了固定數量的線程下載。如果線程都在執行任務,線程池將會任務加入任務隊列中。

如果線程池執行任務過慢,任務將會一直堆積在隊列中。由於我們隊列可以認為是無界的,可以無限制添加任務,這就導致內存佔用越來越高,直到 OOM 爆倉。

ps:線程池基本工作原理

下面我們將上面的例子稍微修改一下,使用 newCachedThreadPool 創建線程池。

程序運行之後,多請求幾次這個批量下載方法,程序很快就會 OOM ,不過這次報錯信息與之前信息與之前不同。

從報錯信息來看,這次 OOM 的主要原因是因為無法再創建新的線程。

這次看下一下 newCachedThreadPool 方法的源碼,可以看到這個方法將會創建最大線程數為 Integer.MAX_VALUE 的的線程池。

由於這個線程池使用 SynchronousQueue 隊列,這個隊列比較特殊,沒辦法存儲任務。所以默認情況下,線程池只要接到一個任務,就會創建一個線程。

一旦線程池收到大量任務,就會創建大量線程。Java 中的線程是會佔用一定的內存空間 ,所以創建大量的線程是必然會導致 OOM。

先贊后看,養成習慣。微信搜索「程序通事」,關注就完事了!

復用線程池

由於線程池的構造方法比較複雜,而 Executors 創建的線程池比較坑,所以我們有個項目中自己封裝了一個線程池工具類。

工具類代碼如下:

public static ThreadPoolExecutor getThreadPool() {
    // 為了快速復現問題,故將線程池 核心線程數與最大線程數設置為 100
    return new ThreadPoolExecutor(100, 100, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(200));
}

項目代碼中這樣使用這個工具類:

@RequestMapping("/batchDownload")
public String batchDownload() {
    ExecutorService threadPool = ThreadPoolUtils.getThreadPool();

    // 模擬下載 100w 個文件
    for (int i = 0; i < 100; i++) {
        threadPool.execute(() -> {
            // 隨機休眠,模擬下載耗時
            Random random = new Random();
            try {
                TimeUnit.SECONDS.sleep(random.nextInt(100));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }

    return "process";
}

使用 WRK 工具對這個接口同時發起多個請求,很快應用就會拋出 OOM。

每次請求都會創建一個新的線程池執行任務,如果短時間內有大量的請求,就會創建很多的線程池,間接導致創建很多線程。從而導致內存佔盡,發生 OOM 問題。

這個問題修復辦法很簡單,要麼工具類生成一個單例線程池,要麼項目代碼中復用創建出來的線程池。

Spring 異步任務

上面代碼中我們都是自己創建一個線程池執行異步任務,這樣還是比較麻煩。在 Spring 中, 我們可以在方法上使用 Spring 註解 @Async,然後執行異步任務。

代碼如下:

@Async
public void async() throws InterruptedException {
    log.info("async process");
    Random random = new Random();
    TimeUnit.SECONDS.sleep(random.nextInt(100));
}

不過使用 Spring 異步任務,我們需要自定義線程池,不然大量請求下,還是有可能發生 OOM 問題。

這是原因主要是 Spring 異步任務默認使用 Spring 內部線程池 SimpleAsyncTaskExecutor 。

這個線程池比較坑爹,不會復用線程。也就是說來一個請求,將會新建一個線程。

所以如果需要使用異步任務,一定要使用自定義線程池替換默認線程池。

如果使用 XML 配置,我們可以增加如下配置:

<task:executor id="myexecutor" pool-size="5"  />
<task:annotation-driven executor="myexecutor"/>

如果使用註解配置,我們需要設置一個 Bean:

@Bean(name = "threadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
    ThreadPoolTaskExecutor executor=new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(5);
    executor.setMaxPoolSize(10);
    executor.setThreadNamePrefix("test-%d");
    // 其他設置
    return new ThreadPoolTaskExecutor();
}

然後使用註解時指定線程池名稱:

@Async("threadPoolTaskExecutor")
public void xx() {
    // 業務邏輯
}

如果是 SpringBoot 項目,從本人測試情況來看,默認將會創建核心線程數為 8,最大線程數為 Integer.MAX_VALUE,隊列數也為 Integer.MAX_VALUE線程池。

ps:以下代碼基於 Spring-Boot 2.1.6-RELEASE,暫不確定 Spring-Boot 1.x 版本是否也是這種策略,熟悉的同學的,也可以留言指出一下。

雖然上面的線程池不用擔心創建過多線程的問題,不是還是有可能隊列任務過多,導致 OOM 的問題。所以還是建議使用自定義線程池嗎,或者在配置文件修改默認配置,例如:

spring.task.execution.pool.core-size=10
spring.task.execution.pool.max-size=20
spring.task.execution.pool.queue-capacity=200

Spring 相關踩坑案例: Spring 定時任務突然不執行

線程池方法使用不當

最後再來說下文章開頭的我踩到的這個坑,這個問題主要是因為理解錯這個方法。

錯誤代碼如下:

// 創建線程池
ExecutorService threadPool = ...
List<Callable<String>> tasks = new ArrayList<>();
// 批量創建任務
for (int i = 0; i < 100; i++) {
    tasks.add(() -> {
        Random random = new Random();
        try {
            TimeUnit.SECONDS.sleep(random.nextInt(100));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "success";
    });
}
// 執行所有任務
List<Future<String>> futures = threadPool.invokeAll(tasks);
// 獲取結果
for (Future<String> future : futures) {
    try {
        future.get();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
}

上面代碼中,使用 invokeAll執行所有任務。由於這個方法返回值為 List<Future<T>>,我誤以為這個方法如 submit一樣,異步執行,不會阻塞主線程。

實際上從源碼上,這個方法實際上逐個調用 Future#get獲取任務結果,而這個方法會同步阻塞主線程。

一旦某個任務被永久阻塞,比如 Socket 網絡連接位置超時時間,導致任務一直阻塞在網絡連接,間接導致這個方法一直被阻塞,從而影響後續方法執行。

如果需要使用 invokeAll 方法,最好使用其另外一個重載方法,設置超時時間。

總結

今天文章通過幾個例子,給大家展示了一下線程池使用過程一些坑。為了快速復現問題,上面的示例代碼還是比較極端,實際中可能並不會這麼用。

不過即使這樣,我們千萬不要抱着僥倖的心理,認為這些任務很快就會執行結束。我們在生產上碰到好幾次事故,正常的情況執行都很快。但是偶爾外部程序抽瘋,返回時間變長,就可能導致系統中存在大量任務,導致 OOM。

最後總結一下幾個線程池幾個最佳實踐:

第一,生產系統慎用 Executors 類提供的便捷方法,我們需要自己根據自己的業務場景,配置合理的線程數,任務隊列,拒絕策略,線程回收策略等等,並且一定記得自定義線程池的命名方式,以便於後期排查問題。

第二,線程池不要重複創建,每次都創建一個線程池可能比不用線程池還要糟糕。如果使用其他同學創建的線程池工具類,最好還是看一下實現方式,防止自己誤用。

第三,一定不要按照自己的片面理解去使用 API 方法,如果把握不準,一定要去看下方法上註釋以及相關源碼。

歡迎關注我的公眾號:程序通事,獲得日常乾貨推送。如果您對我的專題內容感興趣,也可以關注我的博客:studyidea.cn

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置,台北網頁設計,各種案例分享

※別再煩惱如何寫文案,掌握八大原則!

讀懂操作系統之虛擬內存頁表(五)

前言

在一個擁有32位的地址空間,4KB的頁面(212),並且每個PTE為4個字節,那麼頁表大小為4MB(4 * 232 / 212),但若為64位地址空間,4KB的頁面(212)且每個PTE為4字節,那麼頁表大小為16TB(4 * 264 / 212),由於頁表常駐內存,佔用內存會很大,所以必須對頁表存儲結構進行優化,這就是我們本文所要講解的內容,常見的頁表數據結構為多級頁表(兩級、三級等)、倒置頁表、哈希頁表,我們來一一進行分析。

多級頁表

首先我們講講2級頁表,然後通過2級頁表延伸到多級頁表,現假設有16KB(214)的地址空間,並且每頁大小為64(26)字節,每個PTE為4字節,那麼說明頁表為1KB(4 * 214 / 26),若我們有64字節的頁,那麼將1KB可劃分為16個64字節的頁面,每個頁面可容納16個PTE,前面我們講解到虛擬地址劃分為虛擬頁號(VPN)和虛擬頁偏移量(VPO),但虛擬頁偏移量已經固定,那麼我們只能從VPN下手將其作為索引用於索引頁表目錄,那麼我們該如何利用VPN來構建各個部分的索引呢?我們首先需要構建頁表目錄,根據上述假設,總共有256個PTE分佈在16頁上,頁目錄在頁表的每頁上需要一個條目,因此它具有16個條目, 最終我們需要VPN中的4位索引到目錄中,這也就意味着我們需要使用VPN的前4位,如下所示:

我們從VPN提取出了頁表目錄索引(PDI),那麼我們就可以計算出每個PDE(Page Directory Entry)的地址值:

PDEAddress = PageDirectoryBase + (PDIndex * sizeof(PDE))。

有了頁目錄索引后我們還需進行進一步翻譯,如果頁目錄索引為空,很顯然第2級頁表根本就不會存在,如此一來則達到了減少內存的要求,因為只有第一級頁表才會存在於主存中,虛擬內存系統會根據需要調入或調出第2級頁表,這就減少了主存的壓力,只有經常使用的2級頁表才需要緩存在主存中。如果第1級頁表即頁目錄索引有值,那麼還需根據頁目錄指向的頁表頁面去獲取PTE,要找到此PTE,我們還需要使用VPN的其餘索引映射到頁表的部分。

 通過使用如上頁表索引來索引頁表本身,從而找到PTE地址,也就找到了PFN(物理頁幀號)

PTEAddress = (PDE.PFN << SHIFT) + (PTIndex * sizeof(PTE))

從頁面目錄獲得的頁面幀號(PFN)必須先左移到適當位置,然後再與頁表索引組合以形成PTE的地址。假設如下為二級頁表扁平化的片段

 

如上第1片段為頁表目錄,在其中存在索引到第2級頁表的索引,還包括有效位,第2和第3片段分別為第1級頁表目錄索引對應的頁表(其中包含保護位,可讀?可寫?等等),假設CPU產生虛擬地址(0xFE16 = 25410 = 111111102),由於我們假設虛擬地址空間為14位,所以將轉換后的2進制不足用0填充即11111110000000,同時我們將地址空間進行虛擬頁號(VPN)和虛擬頁偏移量(VPO)劃分,然後對VPN劃分為頁表目錄和頁表索引,我們通過紅色、綠色、藍色由左至右分別代表頁表目錄索引、頁表索引、虛擬頁偏移量即1111 1110  000000,經過如此劃分后,此時前4位(11112 = 1510)為頁表目錄索引,對應上述頁表目錄最後一行,此時頁表目錄幀號為101對應第2個頁表片段,然後根據接下來的4位(11102 = 1410),最終得到索引為倒數第2行,即最終物理頁幀號為55。最後我們通過如下物理地址計算公式

 PhysAddress = (PTE.PFN << SHIFT) + offset

 即最終物理地址為:55 * 26 + 000000 = 352010 = 0XDC016。假設為32位地址空間,那麼頁目錄索引、頁表索引、虛擬頁偏移量分別對應為10、10、12位,那麼對應的2級頁表將是如下形式

簡而言之,對於32位地址空間,會將VPN中的前10位(位22..31)用於索引頁表目錄,緊接下來的10位(12 ..21)用於索引所選的頁表。換言之,對於2級頁表結構其本質是:VPN的前m位為頁表目錄索引,而接下來的n位為頁表索引,同時需要注意的是2級頁表其地址是從上往下增加。根據上述將32位地址空間中的頁表以2級結構劃分,此時第1級頁表大小為(1024 * 4) = 4KB,而第2級頁表為(1024 * 1024 * 4) = 4MB,所以頁表大小將為4KB + 4MB,這麼算來比直接使用單級頁表結構為4MB情況更糟糕了不是嗎,其實情況並不是這樣,如上算出的4KB + 4MB為最極限的情況,上述已經講解過只有經常需要用到的2級頁表才緩存在主存中,所以實際情況下頁表大小會小於4MB。

 

早期操作系統採用的是2級頁表結構,但是現如今大多數操作系統採用多級頁表結構,就像樹一樣,不過是深度或層次更深了而已。假設我們有一個30位虛擬地址空間和一個較小的頁面(512字節),因此,我們的虛擬地址具有21位的虛擬頁號和9位的偏移量,使頁表的每個部分都適合單個頁面是構建多級頁表的目標,但到目前為止,我們僅考慮了頁表本身,如果頁表目錄很大,那該怎麼辦?為了確定一個多級頁表中需要多少級才能使頁表的所有部分用一個頁面容納,我們首先確定一個頁面中可以容納多少個PTE。我們假設給定的頁面大小為512字節,並假設PTE大小為4字節,我們知道在單個頁面上可容納128個PTE。當我們索引到頁表的頁面時,可以得出結論,我們需要使用VPN的最低有效7位(log2128)作為索引

通過確定單頁面需要容納128個PTE,那麼將佔據地址空間7位,那麼還剩下14位地址空間,如果將剩下的214作為頁表目錄, 那麼將橫跨128頁而不再是1頁,那麼對於構建多級頁表的目標將無法實現,為了解決這個問題,我們需要將14位進行再次劃分,將頁表目錄進行設置為多頁,頁表目錄位於上方從而指向另一頁表目錄,因此我們可以進行如下劃分

現在,在索引上層頁表目錄時,我們使用虛擬地址的最高位(圖中PD Index:0),該索引可用於從頂級頁表目錄中獲取頁表目錄的條目,如果有效,則對來自自頂層PDE和VPN的下一部分(PD Index:1)的物理幀號組合來查詢頁表目錄的第二層,最後,如果有效,則為PTE地址通過將頁表索引與第二級PDE中的地址結合使用,可以形成一個地址。 當然這個過程需要做很多工作,所有這些都是為了在多級表中查找物理頁幀號。最終多級頁表結構如下這般

上述我們講過若為64位地址空間,4KB的頁面(212)且每個PTE為4字節,在單級頁表情況下,那麼頁表大小為16TB(4 * 264 / 212)= 16TB,若我們劃分為3級,如下:

 

那麼對於上述外部頁即頁目錄索引將需要佔內存4 * 232 = 16GB,所以我們仍需繼續劃分層級,但是每個層級都有一個額外的間接方式,因此會產生額外的開銷。比如64位地址空間在4KB頁面上將使用大地址空間,所以多級頁表成為具有小頁的大地址空間的內存消耗。 

哈希頁表

處理大於32位地址空間常用的方法是使用哈希頁表(使用稀疏的地址空間),採用虛擬頁碼作為哈希值,對於每一個PTE使用鏈表結構存儲從而解決衝突或碰撞,每個元素由三個字段組成:虛擬頁碼、映射的頁幀、指向鏈表內下一個元素的指針。通過哈希算法將虛擬頁碼映射到哈希頁表,然後將虛擬頁碼與鏈表第一個元素的第一個字段進行比較,若匹配則將第二個字段用來形成物理地址,否則遍歷鏈表查找對應匹配項。哈希頁表如下圖所示

雖然通過哈希頁表查找很快,同時採用如上划重點標記的鏈表數據結構解決衝突問題,雖說消除了條目在內存中連續的需求,但是仍然以更高的內存開銷進行存儲即消耗更多內存,特別是如果頁表是完整的,並且具有有效/無效位以使未使用的條目無效,那麼哈希頁表不再那麼適用,此時我們採用其他方案,如下倒置頁表。

倒置頁表

通過前面內容學習我們知道對於每個進程都有一個關聯的頁表,該進程中的每一個虛擬頁都在頁表中對應一項,不管是否有效,進程通過虛擬地址引用頁,操作系統通過計算虛擬地址在頁表中的位置即PTE,但這種方式有明顯的缺點,如上我們也敘述過,每個頁表可能包含數以百萬計的條目,如此一來,頁表將佔用大量的物理內存以跟蹤其他物理內存是如何使用的,為解決這個問題,我們可以使用倒置頁表(inverted page table),對於每個真正的內存頁,倒置頁表才有一個條目,每個條目包含保存在真正內存位置上的頁的虛擬地址,以及擁有該頁進程的信息,因此,整個系統中所有進程將只有一個頁表,並且每個物理內存的頁只有一個相應的條目,換言之,與知道每個進程的虛擬頁在哪裡相反,現在我們知道擁有哪個物理頁的進程與它對應的虛擬頁。IBM是最早採用倒置頁表的公司,從IBM System 38、RS/6000、到現代的IBM Power CPU。對於IBM  RT,系統的虛擬地址包含三部分:進程Id、頁碼、頁偏移量,每個倒置頁表條目包含兩部分:進程Id、頁碼,這裏的進程Id作為地址空間的標識符,當發生內存引用時,由進程Id和頁碼組成的虛擬地址被提交到內存子系統,然後搜索倒置頁表來尋址匹配,如果找到匹配條目,則生成物理地址,如果未找到匹配條目則為非法地址訪問。 倒置頁表結構如下:

雖然倒置頁表減少了存儲每個頁表所需的內存空間,但是它增加了由於引用頁而查找頁表所需要的時間,由於倒置頁表是按照物理地址排序,而查找則是根據虛擬地址,因此查找匹配可能需要搜索整個表,這種搜索需要耗費很長時間,為解決這個問題,可以使用一個哈希表結構,從而將搜索限制在一個或最多數個頁表條目,當然,每訪問哈希表就增加了一次內存引用,因此每次虛擬地址的引用至少需要兩個內存讀,一個用於哈希表條目,另一個用於頁表條目即PTE,同時結合前面所學,在搜索哈希表之前,肯定先搜索TLB,這樣可大大提高性能。對於倒置頁表還會帶來一個問題,那就是實現共享內存,共享內存需要將多個虛擬地址映射到同一物理地址,很顯然,這種標準的方式無法應用於倒置頁表,因為每一個物理頁只有一個虛擬頁條目,一個物理頁不可能有兩個或多個共享的虛擬地址,所以為解決這個問題,只能允許頁表包含一個虛擬地址到共享物理地址的映射,這也就意味着,對於未映射的虛擬地址的引用勢必會導致頁錯誤。

總結

本節我們非常詳細的討論了多級頁表結構、對於哈希頁表和倒置頁表數據結構通過看圖理解起來非常簡單,從本節內容我們可總結出:對應頁表結構可以擁有良好的時間複雜度或空間複雜度,但不能同時兼得。到此關於虛擬內存重要內容基本上都已囊括,若有遺漏,後續我會繼續進行補充。接下來我們將進入內存管理分頁和分段的學習,講完之後,會陸續進入到程序的執行、進程、死鎖、併發等,相信大家會比較感興趣,感謝您的閱讀,我們下節再見。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※南投搬家前需注意的眉眉角角,別等搬了再說!

※新北清潔公司,居家、辦公、裝潢細清專業服務

用戶畫像產品化——從零開始搭建實時用戶畫像(六)

在開發好用戶標籤以後,如何將標籤應用到實際其實是一個很重要的問題。只有做好產品的設計才能讓標籤發揮真正的價值,本文將介紹用戶畫像的產品化過程。

一、標籤展示

首先是標籤展示功能,這個主要供業務人員和研發人員使用,是為了更直觀的看見整個的用戶標籤體系。

不同的標籤體系會有不同的層級,那麼這個頁面的設計就需要我們展示成樹狀的結構,方便以後的擴展。

在最後一個層級,比如自然性別,可以設計一個統計頁面,在進入頁面后,可以展示相應的數據統計情況,

可以更直觀看見標籤中值得比例,也可以為業務提供好的建議,另外可以對標籤的具體描述進行展示,起到一個說明的作用,還可以展示標籤按天的波動情況,觀察標籤的變化情況。

這一部分的數據來源呢?之前也提到過,這些標籤的元數據信息都存在mysql中,方便我們查詢。

所以樹狀圖和標籤描述信息需要去mysql中獲取,而比例等圖表數據則是從Hbase,Hive中查詢獲取的,當然也有直接通過ES獲取的。但是每天的標籤歷史波動情況,還是要通過每天跑完標籤后存在mysql中作為歷史記錄進行展示。

二 、標籤查詢

這一功能可以提供給研發人員和業務人員使用。

標籤查詢功能其實就是對用戶進行全局畫像的過程,對於一個用戶的全量標籤信息,我們是需要對其進行展示的。

輸入用戶id后,可以查看該用戶的屬性信息、行為信息、風控屬性等信息。從多方位了解一個具體的用戶特徵。

這些已經是標籤的具體信息了,由於是對單一id的查找,從hive中獲取會造成查詢速度的問題,所以我們更建議從Hbase或者ES中查詢獲取,這樣查詢效率和實時性都能獲得極大的提升。

三、標籤管理

這一功能是提供給研發人員使用的。

對於標籤,不能每一次新增一個標籤都進行非常大改動,這樣是非常耗費人力的,所以必須要有可以對標籤進行管理的功能。

這裏定義了標籤的基本信息,開發方式,開發人員等等,在完成標籤的開發以後,直接在此頁面對標籤進行錄入,就可以完成標籤的上線工作,讓業務人員可以對標籤進行使用。

新增和編輯標籤的頁面,可以提供下拉框或者輸入框提供信息錄入的功能。

之前已經提到過,這些標籤的元數據信息都保存在了Mysql中,只要完成對其的新增和修改就可以了。

四、用戶分群

作為用戶畫像最核心的功能,用戶分群功能。是用戶畫像與業務系統建立聯繫的橋樑,也是用戶畫像的價值所在。

這項功能主要供業務人員使用。

此功能允許用戶自定義的圈定一部分人員,圈定的規則就是對於標籤的條件約束。

在圈定好人群以後,可以對這部分人群提供與業務系統的外呼系統,客服系統,廣告系統,Push系統的交互,達到真正的精細化運營的目的。

對於標籤規則的判斷,需要將記錄好的規則存儲於Mysql中,在進行人群計算時又需要將規則解析成可計算的邏輯。不管是解析成Sql或者其他的查詢語言都難度巨大,這對於研發是一個非常大的挑戰。

在此功能中,還可以增加人群對比的功能,對不同人群的不同標籤進行圈定,對比。這對於查詢性能也是一個巨大的考驗。

但是,用戶分群功能作為用戶畫像的核心是我們必須要實現的。對於技術架構,Hbase更擅長與KV形式的查詢,對於多維度查詢性能較差,所以可以採取ES索引,在ES查詢出Hbase的Rowkey,再去查詢Hbase的方式。也有很多公司選擇整體遷移到ES中完成此項工作。那麼ES可以勝任這項工作嗎?

下一章,我們來聊一聊如何用ES來實現用戶分群,未完待續~

參考文獻

《用戶畫像:方法論與工程化解決方案》

更多實時數據分析相關博文與科技資訊,歡迎關注 “實時流式計算” 獲取用戶畫像相關資料 請關注 “實時流式計算” 回復 “用戶畫像”

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師”嚨底家”!!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

瑞典環保少女啟發 泰年輕人投身氣候變遷運動

摘錄自2019年12月01日中央通訊社泰國報導

受到16歲瑞典環保少女童貝里(Greta Thunberg)啟發,一群泰國年輕人起身組織氣候變遷抗議活動,希望喚起泰國人重視環保議題,目前已有越來越多年輕人加入他們的行列。這場活動是由一群年紀約20歲的泰國年輕人發起的,沒有政黨色彩,沒有強大的組織,主要發起人是年僅22歲、剛從大學畢業的楠緹查(Nanticha Ocharoenchai)。

日前在曼谷市中心的是樂園(Lumpini Park)有一場特別的抗議活動,上百人高舉著「氣候變遷比功課還糟糕」、「如果不停止的話我們都會死」、「這是我們的未來」、「改變正在發生」等標語,並高喊「我們現在就要行動!」等口號,上百人隨後躺在是樂園的地上,代表這塊土地受到氣候變遷的衝擊,正在逐漸衰亡。

根據世界銀行在9月發布的報告,曼谷每年都在下沉,估計到2030年,曼谷有40%的土地會被水淹沒。

這個活動的目標就是希望泰國政府採取行動,也希望喚起更多泰國人關心氣候變遷的議題,因此參與這場抗議活動的除了大人,還有很多曼谷各區的大學生、中學生甚至小學生。被朋友暱稱為琳(Lynn)的楠緹查和她的團隊今年已經第4次在泰國發起這樣的抗議活動,從一開始僅50多人到這次的上百人,越來越多人注意到氣候變遷議題。

琳曾經發信給泰國自然資源和環境部(Ministry of Natural Resources and Environment),呼籲泰國政府承諾減少煤炭使用量,並且在2025年提高使用再生能源佔全部能源的比例達50%,2040年可以達到100%使用再生能源。

琳關心氣候變遷議題已經3、4年時間,但直到今年,她決定發起實際行動,希望帶來更多改變。她說,有越來越多的年輕人願意加入他們,他們也得到政府部門和大企業的正面回應。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

氣候峰會前歐亞示威者上街 籲當局對抗暖化

摘錄自2019年11月30日中央通訊社德國報導

全球有成千上萬示威者今天走上街頭,歐洲和亞洲占多數,呼籲當局採取行動對抗全球暖化,期望在聯合國(UN)氣候峰會展開的數日前,向全球領導者施壓。

抗議民眾舉著看板寫著「一個地球,一場抗爭」和「海平面在湧升,我們也湧入街頭」。數以千計的群眾聚集在柏林布蘭登堡大門(Brandenburg)參與最新一場「週五為未來而戰」(Fridays for Future)抗議行動,受16歲瑞典環保少女童貝里(Greta Thunberg)先前發起的同名運動啟發。

「週五為未來而戰」運動表示,德國各地超過500座城市,總共有約63萬人上街示威。德國警方表示,光是漢堡就聚集3萬人左右,大多是年輕人,而慕尼黑則集結1萬7000人,他們為了平均地表溫度逐漸上發出警告。

童貝里正搭乘帆船橫渡大西洋,並在推特上傳她舉著寫有「為氣候罷課」標語看板的圖片。這次示威浪潮席捲全歐洲,不過規模仍小於9月「氣候大罷課」的規模。當時籌辦方表示,全球各大城市約400萬人佔據街頭。

為期12天的聯合國氣候變化綱要公約第25次締約方會議(COP25)將於下周展開,目標是鼓勵各國政府減少溫室氣體排放和對抗氣候變遷。這次COP25主辦城市馬德里今天有約1700名示威人士參與。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

※網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師”嚨底家”!!

※新北清潔公司,居家、辦公、裝潢細清專業服務

亞馬遜經濟開發引衝突 NGO不畏強權抗爭多年

摘錄自2019年11月30日中央通訊社巴西報導

環境保護與經濟發展孰輕孰重一直是受到矚目的議題。巴西亞馬遜雨林主要觀光目的地之一Alter do Chao聚落一直受到開發商青睞,當地NGO不畏強權,守護土地,抗爭多年。

巴西北部巴拉州刑警3天前拘捕Alter do Chao社區消防隊4名志工消防員,指控他們在亞馬遜雨林故意製造火災,以獲取國際金援,引起當地社運人士、原住民和環保團體抗議。

在近百個非政府組織(NGO)聯合施壓下,巴西法院昨天(29日)傍晚下令釋放這4名協助撲滅該地區森林火災的非政府組織Alter do Chao社區消防隊成員,但當地與非政府組織的緊張關係已經持續幾10年。

桑塔林觀光局指出,2018年約19萬名遊客造訪Alter do Chao。該地區的旅遊熱潮使村莊周圍地區,房地產開發商具有強烈的開發興趣。一方面,有強大的地方家族勢力和企業家主張在以清澈的河水和白色的沙灘而聞名的塔巴鳩斯(Tapajos)河沿岸建造大型酒店和度假村。另一方面,社運人士、例如與被逮捕的Alter do Chao社區消防隊有聯繫的環保團體,則主張對環境衝擊較小的旅遊業,以保留該區域的特點,並防止傳統社區被驅逐趕離。

巴拉聯邦大學(Ufpa)社會學家托瑞斯(Mauricio Torres)指出,Alter do Chao的爭議邏輯不同於亞馬遜其他區域,當地的旅遊文化、環境保護與經濟開發衝突,才是促成逮捕志工消防員的真實背景。

托瑞斯說,這是屬於一個一直在擴大發展的城市的衝突,有傳統社區面臨被驅逐趕離的壓力,但幕後推手不是木材商或農牧場,而是聚焦於旅遊業的房地產投機與開發。

有論點指出,巴拉州刑警對志工人員進行預防性拘留,指控他們自行引發火災,之後加以撲滅,以獲取國際機構的金援。但一名不願具名、害怕遭到報復的聯邦公務員告訴巴西媒體,社運人士、大學生和原住民強烈反對,致使提案沒有取得進展,所以在當地活動的環保團體都相信逮捕志工消防員的行動含政治動機。巴拉州長巴爾巴柳(Helder Barbalho)昨天已宣布撤換負責此案的警長,並質疑行動的合法性。

聯邦檢察廳自2015年以來進行的調查指出,非法佔領土地和房地產投機,是導致Alter do Chao環境退化的因素,「由於該地區是巴西最著名的度假勝地之一,成為旅遊和房地產業的爭相競奪的目標,且經常受到公共土地入侵者的壓力。」

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※評比前十大台北網頁設計、台北網站設計公司知名案例作品心得分享

※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

人象共用44%國土 斯里蘭卡7隻大象遭毒殺 衝突待解

環境資訊中心外電;范震華 翻譯;賴慧玲 審校;稿源:Mongabay

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

※網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

蒲亭與習近平視訊連線 啟動首條俄中天然氣管

摘錄自2019年12月02日中央通訊社報導

俄羅斯總統蒲亭今天(2日)與中國國家主席習近平透過視訊連線,在電視轉播的儀式中啟動連接俄中兩國的首條天然氣管「西伯利亞力量管道」(Power of Siberia)。

習近平指出,這項計畫是「我們兩國間互利合作的典範」。根據俄國電視的翻譯,他又說:「中俄關係的發展如今是,未來也仍將是我們兩國外交政策的優先要務。」

這條3000公里長的管道從俄羅斯西伯利亞東部偏遠地區,經由邊境城市海蘭泡(Blagoveshchensk)進入中國的中俄東線天然氣管道,中國境內管道的長度超過5000公里。

俄中兩國在經歷十年的艱苦談判後,於2014年簽署了一項為期30年的4000億美元協議,以建設和營運這條管道。這是俄羅斯天然氣工業公司的最大合約。當管道於2025年完全運作時,每年將提供中國380億立方公尺的天然氣。

此外,俄羅斯也正計畫不久後啟動另外兩條天然氣管道,將繞過烏克蘭增加對歐洲的天然氣供應。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

曼谷空中動物園 環境惡劣成動物空中監獄

摘錄自2019年12月2日公視報導

泰國曼谷一間百貨商場,表面平凡無奇。低樓層賣男女服飾,但商場的頂樓,竟是一座空中動物園,裡面關了多達200隻動物,環境惡劣,是一座名符其實的「空中監獄」。裡頭有母猩猩,一關超過30年,處境孤單淒涼,被認為是全世界最悲傷的動物園之一。動保團體要求關閉動物園,還給動物們應有的生存尊嚴。

泰國曼谷的pata百貨購物中心,六樓跟七樓的頂樓,是已被判定違法的動物園。這隻被關在鐵籠子裡的母猩猩,泰國的譯名是白色小蓮花,小蓮花雖然有人餵食照顧,但生活環境惡劣,充滿惡臭。最可憐的是,牠被關在這座空中動物園已整整36年,過著完全失去自由的生活。為了解救小蓮花,動保團體本周再次出面呼籲,儘快關閉這座空中監獄。他們強調,殘忍的對待動物,決不等於提供人們娛樂的方式。善待動物組織成員奧莉維亞表示,「Pata動物園是我們在亞洲遇見過最糟糕的情況,很顯然,一座百貨公司根本不是該有動物存在的場所。」

母猩猩小蓮花,1983年起被關進這座大鐵籠,從此就沒再踏出外面的世界。她在籠子裡打滾,拔毛,流淚的畫面陸續在網路上流傳。動保人士研判,小蓮花已出現精神疾病,其他包括紅毛猩猩,跟狐猴等動物,也都出現焦躁的情緒反應,看了令人鼻酸。善待動物組織成員奧莉維亞說:「這隻猩猩從1983年起就關在這裡,還有一隻紅毛猩猩也被關這很久了,都已經出現精神疾病的症狀,意味著長期被關著心理已經受創。」

事實上,這間pata百貨公司頂樓的動物園,早已多次遭人檢舉。泰國2014年通過動保法,pata動物園2015年更被判定違反動保法,但當局依舊持續核發經營執照,法律形同虛設。至於動物園的經營者也有話要說,不僅強調當初開設動物園時都諮詢過專業意見,也把小蓮花當作自己的女兒照顧,更堅稱網路上流傳小蓮花看似悲傷的表情,其實那是猩猩原本的長相,被外界誤解。不過也坦承,目前要將裡面200多隻動物移往更大的飼養空間,在經費上確實有困難。pata動物園經營者坎尼特表示,「我們有打算將動物移走,因為我們的空間確實有限。我們也打算繼續飼養這些動物,我們有計畫將動物園移往自然的開放空間,但要這麼做的同時,我也必須承認動物園是社會企業,並非以營利投資為主,因此其他的因素(經費)是最主要的問題。」

但實際走訪過這座空中監獄的泰國動物專家強調,pata動物園的存在是泰國的恥辱,猩猩的基因有超過96%跟人類相似,也跟人類有一樣的情感,被關在籠子裡36年,對他們而言可以想像是無比的折磨與煎熬。不僅是小蓮花,其他動物被關在密不通風,底下又是空氣汙染的空間,失去自由,也磨滅了動物的天性。動保團體大聲疾呼泰國政府,拿出鐵腕手段與同理心,盡快關閉這座空中動物園,早日將動物們移往適合的環境,還給他們原本就該擁有的生存尊嚴。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

※網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師”嚨底家”!!

※新北清潔公司,居家、辦公、裝潢細清專業服務

UN氣候變化綱要公約 締約方大會登場

摘錄自2019年12月2日公視、中央通訊社報導

聯合國氣候變化綱要公約,第25次締約方大會在西班牙舉行。而聯合國秘書長古提瑞斯也在大會前夕強調,說氣候變遷的危機已經「迫在眉睫」,呼籲各國要加強行動。同時也宣布,請來即將卸任的英國央行總裁卡尼,從明年開始出任氣候行動與氣候融資的新特使。

卡尼主張氣候風險管理必須轉型,投資淨零碳排放必須成為主流,未來將會盡全力,促使氣候變遷的影響成為財務報告、風險管理和報酬計算的重點。

這場大會原訂12月2號到13號在智利登場,但因為國內動亂,改在西班牙舉行,包括國家領袖、科學家、談判人員和環保運動人士等兩萬多人參與。這也是未來一年一連串國際密集協商的開端,要為明年11月格拉斯哥舉行的全球氣候峰會鋪路,屆時各國將依照巴黎氣候協定要求,提交對抗暖化的具體減碳方案,以便達成把全球溫度控制在比工業化升高1.5度到2度之內的目標。

目前幾乎全球各國都簽署了巴黎氣候協定,但排碳大戶美國,上個月4號已經展開了為期一年的退出程序。這次會議,美國只派層級不高的外交代表團,由負責環境科學事務的首席副助理國務卿伯尼卡特率隊。民主黨籍的眾議院議長裴洛西則率國會代表團參加,當中也沒有共和黨議員。

古提瑞斯今(2日)在氣候峰會的開幕全體會議上表示,面對威脅自身文明的氣候危機,人類必須在即時行動、追求希望,或是無動於衷、舉手投降之間作出抉擇。

世界氣象組織表示,過去5年是有紀錄以來最炎熱的5年,而且大氣裡導致地球暖化的二氧化碳(CO2)濃度已達300萬至500萬年來未見的程度。

古提瑞斯說:「現在北極圈永凍層比預測早70年融化。南極洲融化速度是10年前的三倍,海平面上升速度比預期更快。而且全球超過2/3的巨型都市都靠海。」根據近期研究,到2050年以前,全球會有超過1億5000萬人身處沿海洪患區。

去年聯合國一份重要報告則指出,若要防止氣溫升幅超過攝氏1.5度,全球經濟須在世紀中以前達成碳中和(carbon neutral)。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※評比前十大台北網頁設計、台北網站設計公司知名案例作品心得分享

※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑