日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
對標大廠的技術派詳細方案設計

?01 整體介紹

背景

這個項目誕生的背景和企業(yè)內生的需求不太一樣,主要是某一天二哥說,“我們一起搞事吧”, 樓仔問,“搞什么”,然后這個項目的需求就來了

成都網(wǎng)站建設哪家好,找成都創(chuàng)新互聯(lián)公司!專注于網(wǎng)頁設計、網(wǎng)站建設、微信開發(fā)、微信平臺小程序開發(fā)、集團成都定制網(wǎng)站等服務項目。核心團隊均擁有互聯(lián)網(wǎng)行業(yè)多年經(jīng)驗,服務眾多知名企業(yè)客戶;涵蓋的客戶類型包括:成都辦公空間設計等眾多領域,積累了大量豐富的經(jīng)驗,同時也獲得了客戶的一致表揚!

言歸正傳,我們主要的目的是希望打造一個切實可用的項目,依托于這個項目,將java從業(yè)者所用到的技術棧真實的展現(xiàn)出來,對于經(jīng)驗不是那么足的小伙伴,可以在一個真實的系統(tǒng)上,理解到自己學習的知識點是如何落地的,同時也能真實的了解一個項目是從0到1實現(xiàn)的全過程

系統(tǒng)模塊介紹

系統(tǒng)架構

基于社區(qū)系統(tǒng)的分層特點,將整個系統(tǒng)架構劃分為展示層,應用層,服務層,如下圖

展示層

其中展示層主要為用戶直接接觸的視圖層,基于用戶角色,分別提供為面向普通用戶的前臺與面向管理員的后臺

前臺web

  • 采用Thymleaf模板引擎進行視圖渲染
  • 對于不關心前端技術棧的小伙伴相對友好,學習成本低,只用會基本的html,css,js即可

管理后臺

  • 采用成熟的前后端分離技術方案
  • 前端基于react成熟框架搭建

應用層

應用層,也可以稱為業(yè)務層,強業(yè)務相關,其中每個劃分出來的模塊有較明顯的業(yè)務邊界,雖然在上圖中區(qū)分了前臺、后臺

但是需要注意的是,后臺也是同樣有文章、評論、用戶等業(yè)務功能的,前臺與后臺可使用應用主要是權限粒度管理的差異性,對于技術派系統(tǒng)而言,我們的應用可分為:

  • 文章
  • 專欄
  • 評論
  • 用戶
  • 收藏
  • 訂閱
  • 運營
  • 審核
  • 類目標簽
  • 統(tǒng)計

服務層

我們將一些通用的、可抽離業(yè)務屬性的功能模塊,沉淀到服務層,作為一個一個的基礎服務進行設計,比如計數(shù)服務、消息服務等,通常他們最大特點就是獨立與業(yè)務之外,適用性更廣,并不局限在特定的業(yè)務領域內,可以作為通用的技術方案存在

在技術派的項目設計中,我們擬定以下基礎服務

  • 用戶權限管理 (auth)
  • 消息中心 (mq)
  • 計數(shù) (redis)
  • 搜索服務 (es)
  • 推薦 (recommend)
  • 監(jiān)控運維 (prometheus)

平臺資源層

這一層可以理解為更基礎的下層支撐

  • 服務資源:數(shù)據(jù)庫、redis、es、mq
  • 硬件資源:容器,ecs服務器

術語介紹

技術派整個系統(tǒng)中涉及到的術語并不多,也很容易理解,下面針對幾個常用的進行說明

  • 用戶:特指通過微信公眾號掃碼注冊的用戶,可以發(fā)布文章、閱讀文章等
  • 管理員:可以登錄后臺的特殊用戶
  • 文章:即博文
  • 專欄:由一系列相關的文章組成的一個合集
  • 訂閱:專指關注用戶

02 系統(tǒng)模塊設計

針對前面技術派的業(yè)務架構拆分,技術派的實際項目劃分,主要是五個模塊,相反并沒由將上面的每個應用、服務抽離為獨立的模塊,主要是為了避免過渡設計,粒度劃分太細會增加整個項目的理解維護成本

這里設置五個相對獨立的模塊,則主要是基于邊界特別清晰這一思考點進行,后續(xù)做微服務演進時,下面每個模塊可以作為獨立的微服務存在

用戶模塊

在技術派中,整個用戶模塊從功能角度可以分為

  • 注冊登錄
  • 權限管理(是的,權限管理也放在這里了)
  • 業(yè)務邏輯

注冊登錄

方案設計

注冊登錄除了常見的用戶名+密碼的登錄方式之外,現(xiàn)在也有流行的手機號+驗證,第三方授權登錄;我們最終選擇微信公眾號登錄方式(其最主要的目的,相信大家也知道...)

對于個人公眾號,很多權限沒有;因此這個登錄的具體實現(xiàn),有兩種實現(xiàn)策略

  • 點擊登錄,登錄頁顯示二維碼 + 輸入框 -> 用戶關注公眾號,輸入 "login" 獲取登錄驗證碼 -> 在登錄界面輸入驗證碼實現(xiàn)登錄
  • 點擊登錄,登錄頁顯示二維碼 + 驗證碼 -> 用戶關注公眾號,將登錄頁面上的驗證碼輸入到微信公眾號 -> 自動登錄

其中第一種策略,類似于手機號/驗證碼的登錄方式,主要是根據(jù)系統(tǒng)返回的驗證碼來主動登錄

優(yōu)點:

  • 代碼實現(xiàn)簡單,邏輯清晰

缺點:

  • 操作流程復雜,用戶需要輸入兩次

對于第二種策略,如果是企業(yè)公眾號,是可以省略輸入驗證碼這一步驟的,借助動態(tài)二維碼來直接實現(xiàn)掃碼登錄;對于我們這種個人公眾號,則需要多來一步,通過輸入驗證碼來將微信公眾號的用戶與需要登錄的用戶綁定起來

登錄工作流程如下:

庫表設計

基于公眾號的登錄方式,看一下用戶登錄表的設計

CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`third_account_id` varchar(128) NOT NULL DEFAULT '' COMMENT '第三方用戶ID',
`user_name` varchar(64) NOT NULL DEFAULT '' COMMENT '用戶名',
`password` varchar(128) NOT NULL DEFAULT '' COMMENT '密碼',
`login_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '登錄方式: 0-微信登錄,1-賬號密碼登錄',
`deleted` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否刪除',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新時間',
PRIMARY KEY (`id`),
KEY `key_third_account_id` (`third_account_id`),
KEY `key_user_name` (`user_name`),
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='用戶登錄表';

注意上面的表結構設計,我們冗余了 user_name?, password 用戶名密碼的登錄方式,主要是給管理員登錄后臺使用

用戶首次登錄之后,會在user表中插入一條數(shù)據(jù),主要關注 third_account_id 這個字段,它記錄的是微信開放平臺返回的唯一用戶id

權限管理

權限管理會分為兩塊:用戶身份識別 + 鑒權

方案設計

用戶身份識別:

現(xiàn)在用戶的身份識別有非常多的方案,我們現(xiàn)在采用的是最基礎、歷史最悠久的方案,cookie + session 方式(后續(xù)會迭代為分布式session + jwt)

整體流程:

  • 用戶登錄成功,服務器生成sessionId -> userId 映射關系
  • 服務器返回sessionId,寫到客戶端的瀏覽器cookie
  • 后續(xù)用戶請求,攜帶cookie
  • 服務器從cookie中獲取sessionId,然后找到uesrId

服務內部身份傳遞:

另外一個需要考慮的點則是用戶的身份如何在整個系統(tǒng)內傳遞? 對于一期我們采用的單體架構而言,借助ThreadLocal來實現(xiàn)

  • 自定義Filter,實現(xiàn)用戶身份識別(即上面的流程,從cookie中拿到SessionId,轉userId)
  • 定義全局上下文ReqInfoContext:將用戶信息,寫入全局共享的ThreadLocal中
  • 在系統(tǒng)內,需要獲取當前用戶的地方,直接通過訪問 ReqInfoContext上下文獲取用戶信息
  • 請求返回前,銷毀上下文中當前登錄用戶信息

鑒權

根據(jù)用戶角色與接口權限要求進行判定,我們設計三種權限點類型

  • ADMIN:只有管理員才能訪問的接口
  • LOGIN:只有登錄了才能訪問的接口
  • ALL:默認,沒有權限限制

我們在需要權限判定的接口上,添加上對應的權限要求,然后借助AOP來實現(xiàn)權限判斷

  • 當接口上有權限點要求時(除ALL之外)
  • 首先獲取用戶信息,如果沒有登錄,則直接報403
  • 對于ADMIN限制的接口,要求查看用戶角色,必須為admin
庫表設計

我們將用戶角色信息寫入用戶基本信息表中,沒有單獨抽出一個角色表,然后進行映射,主要是因為這個系統(tǒng)邏輯相對清晰,沒有太復雜的角色關系,因此采用了輕量級的設計方案

-- pai_coding.user_info definition

CREATE TABLE `user_info` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '用戶ID',
`user_name` varchar(50) NOT NULL DEFAULT '' COMMENT '用戶名',
`photo` varchar(128) NOT NULL DEFAULT '' COMMENT '用戶圖像',
`position` varchar(50) NOT NULL DEFAULT '' COMMENT '職位',
`company` varchar(50) NOT NULL DEFAULT '' COMMENT '公司',
`profile` varchar(225) NOT NULL DEFAULT '' COMMENT '個人簡介',
`user_role` int(4) NOT NULL DEFAULT '0' COMMENT '0 普通用戶 1 超管',
`extend` varchar(1024) NOT NULL DEFAULT '' COMMENT '擴展字段',
`ip` json NOT NULL COMMENT '用戶的ip信息',
`deleted` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否刪除',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新時間',
PRIMARY KEY (`id`),
KEY `key_user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='用戶個人信息表';

業(yè)務邏輯

在業(yè)務模塊,主要說兩塊,一個是用戶的軌跡,一個是訂閱關注

訂閱關注

訂閱關注這塊業(yè)務主要是用戶可以相互關注,核心點就在于維護用戶與用戶之間的訂閱關系

業(yè)務邏輯上沒有太復雜的東西,核心就是需要一張表來記錄關注與被關注情況

-- pai_coding.user_relation definition

CREATE TABLE `user_relation` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '作者用戶ID',
`follow_user_id` int(10) unsigned NOT NULL COMMENT '關注userId的用戶id,即粉絲userId',
`follow_state` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '閱讀狀態(tài): 0-未關注,1-已關注,2-取消關注',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新時間',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_follow` (`user_id`,`follow_user_id`),
KEY `key_follow_user_id` (`follow_user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='用戶關系表';
用戶軌跡

在技術派的整體設計中,我們希望記錄用戶的閱讀歷史、關注列表、收藏列表、評價的文章列表,對于這種用戶行為軌跡的訴求,我們采用設計一張大寬表的策略,其主要目的在于

  1. 記錄用戶的關鍵動作
  2. 便于文章的相關計數(shù)

接下來看一下表結構設計

-- pai_coding.user_foot definition

CREATE TABLE `user_foot` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '用戶ID',
`document_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '文檔ID(文章/評論)',
`document_type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '文檔類型:1-文章,2-評論',
`document_user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '發(fā)布該文檔的用戶ID',
`collection_stat` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '收藏狀態(tài): 0-未收藏,1-已收藏,2-取消收藏',
`read_stat` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '閱讀狀態(tài): 0-未讀,1-已讀',
`comment_stat` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '評論狀態(tài): 0-未評論,1-已評論,2-刪除評論',
`praise_stat` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '點贊狀態(tài): 0-未點贊,1-已點贊,2-取消點贊',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新時間',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_user_doucument` (`user_id`,`document_id`,`document_type`),
KEY `idx_doucument_id` (`document_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='用戶足跡表';

我們將用戶 + 文章設計唯一鍵,用來記錄用戶對自己閱讀過的文章的行為,因此可以直接通過這個表獲取用戶的歷史軌跡

同時也可以從文章的角度出發(fā),查看被哪些用戶點贊、收藏過

小結

用戶模塊的核心支撐在上面幾塊,請重點關注上面的示意圖與表結構;當然用戶的功能點不止于上面幾個,比如基礎的個人主頁、用戶信息等也屬于用戶模塊的業(yè)務范疇

文章模塊

我們將文章和專欄都放在一起,同樣也將類目管理、標簽管理等也都放在這個模塊中,實際上若文章模塊過于龐大,也是可以按照最開始的劃分進行繼續(xù)拆分的;這里放在一起的主要原因在于他們都是圍繞基本的文章這一業(yè)務屬性來的,可以聚合在一起

文章

文章的核心就在于發(fā)布、查看

基本的發(fā)布流程:

  1. 用戶登錄,進入發(fā)布頁面
  2. 輸入標題、文章
  3. 選擇分類、標簽,封面、簡介
  4. 提交文章,進入待審核狀態(tài),僅用戶可看詳情
  5. 管理員審核通過,所有人可看詳情

文章庫表設計

考慮到文章的內容通常較大,在很多的業(yè)務場景中,我們實際上是不需要文章內容的,如首頁、推薦列表等都只需要文章的標題等信息;此外我們也希望對文章做一個版本管理(比如上線之后,再修改則新生成一個版本)

因此我們對文章設計了兩張表

-- pai_coding.article definition

CREATE TABLE `article` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '用戶ID',
`article_type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '文章類型:1-博文,2-問答',
`title` varchar(120) NOT NULL DEFAULT '' COMMENT '文章標題',
`short_title` varchar(120) NOT NULL DEFAULT '' COMMENT '短標題',
`picture` varchar(128) NOT NULL DEFAULT '' COMMENT '文章頭圖',
`summary` varchar(300) NOT NULL DEFAULT '' COMMENT '文章摘要',
`category_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '類目ID',
`source` tinyint(4) NOT NULL DEFAULT '1' COMMENT '來源:1-轉載,2-原創(chuàng),3-翻譯',
`source_url` varchar(128) NOT NULL DEFAULT '1' COMMENT '原文鏈接',
`offical_stat` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '官方狀態(tài):0-非官方,1-官方',
`topping_stat` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '置頂狀態(tài):0-不置頂,1-置頂',
`cream_stat` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '加精狀態(tài):0-不加精,1-加精',
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '狀態(tài):0-未發(fā)布,1-已發(fā)布',
`deleted` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否刪除',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新時間',
PRIMARY KEY (`id`),
KEY `idx_category_id` (`category_id`),
KEY `idx_title` (`title`),
KEY `idx_short_title` (`short_title`)
) ENGINE=InnoDB AUTO_INCREMENT=173 DEFAULT CHARSET=utf8mb4 COMMENT='文章表';


-- pai_coding.article_detail definition

CREATE TABLE `article_detail` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`article_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '文章ID',
`version` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '版本號',
`content` longtext COMMENT '文章內容',
`deleted` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否刪除',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新時間',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_article_version` (`article_id`,`version`)
) ENGINE=InnoDB AUTO_INCREMENT=141 DEFAULT CHARSET=utf8mb4 COMMENT='文章詳情表';

文章對應的分類,我們要求一個文章只能掛在一個分類下

-- pai_coding.category definition

CREATE TABLE `category` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`category_name` varchar(64) NOT NULL DEFAULT '' COMMENT '類目名稱',
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '狀態(tài):0-未發(fā)布,1-已發(fā)布',
`rank` tinyint(4) NOT NULL DEFAULT '0' COMMENT '排序',
`deleted` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否刪除',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新時間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COMMENT='類目管理表';

文章對應的標簽屬性,一個文章可以有多個標簽

-- pai_coding.tag definition

CREATE TABLE `tag` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`tag_name` varchar(120) NOT NULL COMMENT '標簽名稱',
`tag_type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '標簽類型:1-系統(tǒng)標簽,2-自定義標簽',
`category_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '類目ID',
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '狀態(tài):0-未發(fā)布,1-已發(fā)布',
`deleted` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否刪除',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新時間',
PRIMARY KEY (`id`),
KEY `idx_category_id` (`category_id`)
) ENGINE=InnoDB AUTO_INCREMENT=147 DEFAULT CHARSET=utf8mb4 COMMENT='標簽管理表';

-- pai_coding.article_tag definition

CREATE TABLE `article_tag` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`article_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '文章ID',
`tag_id` int(11) NOT NULL DEFAULT '0' COMMENT '標簽',
`deleted` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否刪除',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新時間',
PRIMARY KEY (`id`),
KEY `idx_tag_id` (`tag_id`)
) ENGINE=InnoDB AUTO_INCREMENT=145 DEFAULT CHARSET=utf8mb4 COMMENT='文章標簽映射';

專欄

專欄主要是一系列文章的合集,基于此最簡單的設計方案就是加一個專欄表,然后再加一個專欄與文章的映射表

但是需要注意的是專欄中文章的順序,支持調整

專欄庫表設計

專欄表

-- pai_coding.column_info definition

CREATE TABLE `column_info` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '專欄ID',
`column_name` varchar(64) NOT NULL DEFAULT '' COMMENT '專欄名',
`user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '作者id',
`introduction` varchar(256) NOT NULL DEFAULT '' COMMENT '專欄簡述',
`cover` varchar(128) NOT NULL DEFAULT '' COMMENT '專欄封面',
`state` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '狀態(tài): 0-審核中,1-連載,2-完結',
`publish_time` timestamp NOT NULL DEFAULT '1970-01-02 00:00:00' COMMENT '上線時間',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新時間',
`section` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '排序',
`nums` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '專欄預計的更新的文章數(shù)',
`type` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '專欄類型 0-免費 1-登錄閱讀 2-限時免費',
`free_start_time` timestamp NOT NULL DEFAULT '1970-01-02 00:00:00' COMMENT '限時免費開始時間',
`free_end_time` timestamp NOT NULL DEFAULT '1970-01-02 00:00:00' COMMENT '限時免費結束時間',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='專欄';

專欄文章表

-- pai_coding.column_article definition

CREATE TABLE `column_article` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`column_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '專欄ID',
`article_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '文章ID',
`section` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '章節(jié)順序,越小越靠前',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新時間',
PRIMARY KEY (`id`),
KEY `idx_column_id` (`column_id`)
) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb4 COMMENT='專欄文章列表';

點贊收藏

再技術派中,對于文章提供了點贊、收藏、評論三種交互,這里重點看一下點贊與收藏;

實際上就是用戶與文章之間的操作行為,再前面的user_foot表就已經(jīng)介紹具體的表結構, 文章的統(tǒng)計計數(shù)就是根據(jù)這個表數(shù)據(jù)來的,當前用戶與文章的點贊、收藏關系,同樣是根據(jù)這個表來的

唯一需要注意的點,就是這個數(shù)據(jù)的插入、更新策略:

  • 首次閱讀文章時:插入一條數(shù)據(jù)
  • 點贊:若記錄存在,則更新狀態(tài),之前時點贊的,設置為取消點贊;若記錄不存在,則插入一條點贊的記錄
  • 收藏:同上

評論模塊

評論可以是針對文章進行,也可以是針對另外一個評論進行回復,我們將回復也當作是一個評論

評論

我們將評論和回復都當成普通的評論,只是主體不同而已,因此一篇文章的評論列表,我們需要重點關注的就是,如何構建評論與其回復之間的層級關系

對于這種評論與回復的層級關系,可以是建輔助表來處理;也可以是表內的父子關系來處理,這里我們采用第二種策略

  • 每個評論記錄它的上一級評論id(若只是針對文章的評論,那么上一級評論id = 0)
  • 我們通過父子關系,在業(yè)務層進行邏輯還原

庫表設計

針對上面的策略,核心的評論庫表設計如下

-- pai_coding.comment definition

CREATE TABLE `comment` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`article_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '文章ID',
`user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '用戶ID',
`content` varchar(300) NOT NULL DEFAULT '' COMMENT '評論內容',
`top_comment_id` int(11) NOT NULL DEFAULT '0' COMMENT '頂級評論ID',
`parent_comment_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '父評論ID',
`deleted` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否刪除',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新時間',
PRIMARY KEY (`id`),
KEY `idx_article_id` (`article_id`),
KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=75 DEFAULT CHARSET=utf8mb4 COMMENT='評論表';

注意:

  • 為什么再表中需要冗余一個頂級評論id ?
  • 主要的目的是簡化業(yè)務層評論關系還原的復雜性

通過上面的表結構,關系還原的策略:

  • 先查出文章的頂級評論(parent_comment_id = 0)
  • 接下來就是針對每個頂級評論,查詢它下面的所有回復 ( top_comment_id = comment_id)
  • 構建頂級評論下的回復父子關系(根據(jù)parent_comment_id來構建依賴關系)

拓展:如果不存在top_comment_id,那么要實現(xiàn)上面這個還原,要怎么做呢?

評論點贊

技術派中同樣支持對評論進行點贊,取消點贊;對于點贊的整體業(yè)務邏輯操作,實際上與文章的點贊一致,因此我們直接復用了文章的點贊邏輯,借助 user_foot 來實現(xiàn)的

說明

  • 上面這種實現(xiàn)并不是一種優(yōu)雅的選擇,從user_foot的設計也能看出,它實際上與評論點贊這個業(yè)務是有些隔離的
  • 采用上面這個方案的主要原因在于,點贊這種屬于通用的服務,使用mysql來維系點贊與否以及計數(shù)統(tǒng)計,再數(shù)據(jù)量大了之后,基本上玩不轉;后續(xù)會介紹如何設計一個通用的點贊服務,以此來替換技術派中當前的點贊實現(xiàn)
  • 這種設計思路也經(jīng)常體現(xiàn)在一個全新項目的設計中,最開始的設計并不會想著一蹴而就,整一個非常完美的系統(tǒng)出來,我們需要的是在最開始搭好基座、方便后續(xù)擴展;另外一點就是,如何在當前系統(tǒng)的基礎上,最小成本的支持業(yè)務需求(相信各位小伙伴在日常工作中,這些事情不會陌生)

消息模塊

消息模塊主要是記錄一些定義的事件,用于同步給用戶;我們整體采用Event/Listener的異步方案來進行

在單機應用中,借助Spring Event/Listener機制來實現(xiàn);在集群中,將借助MQ消息中間件來實現(xiàn)

消息通知

我們主要定義以下五種消息類型

  • 評論
  • 點贊
  • 收藏
  • 關注
  • 系統(tǒng)消息

當發(fā)生方面的行為之后,再相應的地方進行主動埋點,手動發(fā)送一個消息事件,然后異步消費事件,生成消息通知

需要注意一點:

  • 當用戶點贊了一個文章,產(chǎn)生一個點贊消息之后;又取消了點贊,這個消息會怎樣?
  • 撤銷還是依然保留?(技術派中選擇的方案是撤銷)

庫表設計

-- pai_coding.notify_msg definition

CREATE TABLE `notify_msg` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`related_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '關聯(lián)的主鍵',
`notify_user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '通知的用戶id',
`operate_user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '觸發(fā)這個通知的用戶id',
`msg` varchar(1024) NOT NULL DEFAULT '' COMMENT '消息內容',
`type` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '類型: 0-默認,1-評論,2-回復 3-點贊 4-收藏 5-關注 6-系統(tǒng)',
`state` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '閱讀狀態(tài): 0-未讀,1-已讀',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`update_time` timestamp NOT NULL DEFAULT CURRENT
分享題目:對標大廠的技術派詳細方案設計
鏈接分享:http://www.5511xx.com/article/dpdigjo.html