基於 Flink 實現的商品實時推薦系統 -附源碼-
前言
之前一直給大家推薦的是關於 Flink 的介紹和知識點,可以在歷史文章搜索瞭解。總的來說,現在還挺缺這種真正實戰的項目分享出來,尤其是把源代碼分享出來的,近期我在 GitHub 觀察到一個不錯的 Flink 項目,然後也和作者交流了下,於是在這裏做一個分享。所以,那些平時問我有沒有 Flink 項目的可以看過來了。地址在 :https://github.com/CheckChe0803/flink-recommandSystem-demo 下面介紹下這個項目。
- 系統架構 v2.0
-
1.1 系統架構圖
-
1.2 模塊說明
-
a. 在日誌數據模塊 (flink-2-hbase) 中, 又主要分爲 6 個 Flink 任務:
-
用戶 - 產品瀏覽歷史 -> 實現基於協同過濾的推薦邏輯
通過 Flink 去記錄用戶瀏覽過這個類目下的哪些產品, 爲後面的基於 Item 的協同過濾做準備
實時的記錄用戶的評分到 Hbase 中, 爲後續離線處理做準備.數據存儲在 Hbase 的 p_history 表
-
用戶 - 興趣 -> 實現基於上下文的推薦邏輯
根據用戶對同一個產品的操作計算興趣度, 計算規則通過操作間隔時間 (如購物 - 瀏覽 < 100s) 則判定爲一次興趣事件
通過 Flink 的 ValueState 實現, 如果用戶的操作 Action=3(收藏), 則清除這個產品的 state, 如果超過 100s 沒有出現 Action=3 的事件, 也會清除這個 state數據存儲在 Hbase 的 u_interest 表
-
用戶畫像計算 -> 實現基於標籤的推薦邏輯
v1.0 按照三個維度去計算用戶畫像, 分別是用戶的顏色興趣, 用戶的產地興趣, 和用戶的風格興趣. 根據日誌不斷的修改用戶畫像的數據, 記錄在 Hbase 中.
數據存儲在 Hbase 的 user 表
-
產品畫像記錄 -> 實現基於標籤的推薦邏輯
用兩個維度記錄產品畫像, 一個是喜愛該產品的年齡段, 另一個是性別
數據存儲在 Hbase 的 prod 表
-
事實熱度榜 -> 實現基於熱度的推薦邏輯
通過 Flink 時間窗口機制, 統計當前時間的實時熱度, 並將數據緩存在 Redis 中.
通過 Flink 的窗口機制計算實時熱度, 使用 ListState 保存一次熱度榜
數據存儲在 redis 中, 按照時間戳存儲 list
-
日誌導入
從 Kafka 接收的數據直接導入進 Hbase 事實表, 保存完整的日誌 log, 日誌中包含了用戶 Id, 用戶操作的產品 id, 操作時間, 行爲 (如購買, 點擊, 推薦等).
數據按時間窗口統計數據大屏需要的數據, 返回前段展示
數據存儲在 Hbase 的 con 表
-
b. web 模塊
-
前臺用戶界面
該頁面返回給用戶推薦的產品 list
-
後臺監控頁面
該頁面返回給管理員指標監控
2. 推薦引擎邏輯說明
-
2.1 基於熱度的推薦邏輯
現階段推薦邏輯圖
根據用戶特徵,重新排序熱度榜,之後根據兩種推薦算法計算得到的產品相關度評分,爲每個熱度榜中的產品推薦幾個關聯的產品
-
2.2 基於產品畫像的產品相似度計算方法
基於產品畫像的推薦邏輯依賴於產品畫像和熱度榜兩個維度, 產品畫像有三個特徵, 包含 color/country/style 三個角度, 通過計算用戶對該類目產品的評分來過濾熱度榜上的產品
在已經有產品畫像的基礎上, 計算 item 與 item 之間的關聯繫, 通過餘弦相似度來計算兩兩之間的評分, 最後在已有物品選中的情況下推薦關聯性更高的產品.
-
2.3 基於協同過濾的產品相似度計算方法
根據產品用戶表(Hbase) 去計算公式得到相似度評分:
3. 前臺推薦頁面
當前推薦結果分爲 3 列, 分別是熱度榜推薦, 協同過濾推薦和產品畫像推薦
4. 後臺數據大屏
在後臺上顯示推薦系統的實時數據, 數據來自其他 Flink 計算模塊的結果. 目前包含熱度榜和 1 小時日誌接入量兩個指標.
真實數據位置在 resource/database.sql
5. 部署說明
以下的部署均使用 Docker,對於搭建一套複雜的系統,使用 docker 來部署各種服務中間件再合適不過了。這裏有一套簡單的 Docker 入門系列
需要的服務有:Mysql、Redis、Hbase 和 Kafka
Mysql
docker pull mysql:5.7
docker run --name local-mysql -p 3308:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
簡單介紹一下命令,先拉取鏡像,然後指定參數啓動容器
-
--name local-mysql
容器名爲 local-mysql -
-p 3308:3306
宿主機與容器的端口映射爲 3308:3306 即你訪問宿主機的 3308 就是訪問容器的 3306 端口,需要理解下 -
-e MYSQL_ROOT_PASSWORD=123456
容器內的變量名MYSQL_ROOT_PASSWORD
對應的值爲 123456 即 mysql 的 root 密碼爲 123456 -
-d
後臺啓動
Redis
$ docker run --name local-redis -p 6379:6379 -d redis
Hbase
docker pull harisekhon/hbase
docker run -d -h base-server \
-p 2181:2181 \
-p 8080:8080 \
-p 8085:8085 \
-p 9090:9090 \
-p 9000:9000 \
-p 9095:9095 \
-p 16000:16000 \
-p 16010:16010 \
-p 16201:16201 \
-p 16301:16301 \
-p 16020:16020\
--name hbase \
harisekhon/hbase
Hbase 用到的端口, 可以參考一下詳細教程
啓動成功之後我們可以訪問http://localhost:16010/master-status
登錄 Web 界面
:point_right: 快速實現 SpringBoot 集成 Hbase
Kafka
考慮到更好的區別這些端口,我這裏啓動了一個虛擬機,在虛擬機中在用 dokcer 安裝 Kafka,過程如下
## pull images
docker pull wurstmeister/zookeeper
docker pull wurstmeister/kafka
docker pull sheepkiller/kafka-manager
docker run -d --name zookeeper --publish 2181:2181 \
--volume /etc/localtime:/etc/localtime \
--restart=always \
wurstmeister/zookeeper
## run kafka
docker run --name kafka \
-p 9092:9092 \
--link zookeeper:zookeeper \
-e KAFKA_ADVERTISED_HOST_NAME=192.168.1.8 \
-e KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 \
-d wurstmeister/kafka
## run kafka manager
docker run -d \
--link zookeeper:zookeeper \
-p 9000:9000 \
-e ZK_HOSTS="zookeeper:2181" \
hlebalbau/kafka-manager:stable \
-Dpidfile.path=/dev/null
如果想設置 webui 的權限,可以這樣設置
KAFKA_MANAGER_AUTH_ENABLED: "true"
KAFKA_MANAGER_USERNAME: username
KAFKA_MANAGER_PASSWORD: password
容器啓動成功之後就可以在頁面訪問localhost:9000
查看 Kafkfa 的管理界面。
:point_right: 快速實現 SpringBoot 集成 Kafka
啓動服務
以下的操作是在 IDEA 下完成
1、將上述部署的幾個服務的 ip 和端口號分別配置在 flink-2-hbase 和 web 服務中;
2、在 flink-2-hbase 中的根目錄執行mvn clean install
,目的是將其打包並放置在本地倉庫中;
3、分別啓動 task 目錄下的 task(直接在 idea 中右鍵啓動就行了);
4、把 SchedulerJob 啓動起來,定時的去計算協同過濾和用戶畫像所需要的分數;
5、在 idea 中打開 web 項目,等待其自動引入 flink-2-hbase 生成的 jar 包之後,再啓動服務就 ok 了;
注意:所有的服務啓動後,因爲沒有任何的點擊記錄,所以就是隨機從數據庫取得產品,這裏需要你在推薦頁面隨便點擊,等有了一定的歷史數據之後,就能實現實時推薦的效果了
6. 下一步工作
-
添加 flink 任務監控
-
完善數據大屏, 顯示更詳細的指標
-
統計召回率 / 準確率等業務指標
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/9EZP2zxvRHk2X61Natj60w