日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

基于 DDD 的互聯網“贊&踩”系統

來源: 責編: 時間:2023-10-30 09:07:06 326觀看
導讀該文是系統的用戶手冊,主要體現系統功能和所支持的高級特性,關于系統的核心設計正在整理中,請稍安勿躁1. 背景隨著社交媒體的普及,用戶生成的內容數量急劇增加。為了幫助用戶更好地發現和分享內容,許多社交媒體平臺都提供

該文是系統的用戶手冊,主要體現系統功能和所支持的高級特性,關于系統的核心設計正在整理中,請稍安勿躁dEe28資訊網——每日最新資訊28at.com

1. 背景

隨著社交媒體的普及,用戶生成的內容數量急劇增加。為了幫助用戶更好地發現和分享內容,許多社交媒體平臺都提供了贊/踩服務。dEe28資訊網——每日最新資訊28at.com

2. 目標

贊/踩服務是一種用戶反饋機制。隨著社交媒體的普及和發展,人們越來越喜歡在一種平臺上分享自己的觀點和生活,這時就需要一種形式化的反饋機制來快速評價這些信息的好壞。贊/踩服務的目標是為了提高用戶互動性,增加內容的社會影響力,從而增加活躍用戶數量。dEe28資訊網——每日最新資訊28at.com

3. 快速入門

系統所涉及的功能包括:dEe28資訊網——每日最新資訊28at.com

功能dEe28資訊網——每日最新資訊28at.com

描述dEe28資訊網——每日最新資訊28at.com

贊/踩dEe28資訊網——每日最新資訊28at.com

用戶可以點擊對應的贊或踩按鈕,以表達自己的喜好或不喜好dEe28資訊網——每日最新資訊28at.com

取消贊/踩dEe28資訊網——每日最新資訊28at.com

用戶可以取消之前的贊/踩,以更正自己的想法dEe28資訊網——每日最新資訊28at.com

計數器dEe28資訊網——每日最新資訊28at.com

贊和踩的數量都需要計數器,用于顯示文章或評論的受歡迎程度和社交影響力等dEe28資訊網——每日最新資訊28at.com

贊/踩歷史dEe28資訊網——每日最新資訊28at.com

用戶可以查看自己贊/踩的歷史記錄,以查看自己對文章或評論的態度dEe28資訊網——每日最新資訊28at.com

3.1. 開發環境

基于 Spring Boot 框架進行開發,以 DDD 作為業務邏輯承載模型。dEe28資訊網——每日最新資訊28at.com

框架dEe28資訊網——每日最新資訊28at.com

版本dEe28資訊網——每日最新資訊28at.com

依賴說明dEe28資訊網——每日最新資訊28at.com

JDKdEe28資訊網——每日最新資訊28at.com

1.8+dEe28資訊網——每日最新資訊28at.com

運行環境dEe28資訊網——每日最新資訊28at.com

Spring BootdEe28資訊網——每日最新資訊28at.com

2.3.12.RELEASEdEe28資訊網——每日最新資訊28at.com


dEe28資訊網——每日最新資訊28at.com

Spring DatadEe28資訊網——每日最新資訊28at.com

2.3.9.RELEASEdEe28資訊網——每日最新資訊28at.com

基于 JPA 實現持久化;基于 Redis 完成緩存加速(可選)dEe28資訊網——每日最新資訊28at.com

LegodEe28資訊網——每日最新資訊28at.com

0.1.22dEe28資訊網——每日最新資訊28at.com

DDD 模型落地dEe28資訊網——每日最新資訊28at.com

springfoxdEe28資訊網——每日最新資訊28at.com

3.0.0dEe28資訊網——每日最新資訊28at.com

文檔管理dEe28資訊網——每日最新資訊28at.com

RocketMQdEe28資訊網——每日最新資訊28at.com

2.2.1dEe28資訊網——每日最新資訊28at.com

領域事件,異步處理(可選)dEe28資訊網——每日最新資訊28at.com

Sharding SpheredEe28資訊網——每日最新資訊28at.com

4.4.1dEe28資訊網——每日最新資訊28at.com

分庫分表(可選)dEe28資訊網——每日最新資訊28at.com

3.2. 模塊介紹

該項目使用標準的 “六邊形架構”,對業務和技術進行分離,所以模塊較多,但層次更為清晰。dEe28資訊網——每日最新資訊28at.com

模塊dEe28資訊網——每日最新資訊28at.com

作用dEe28資訊網——每日最新資訊28at.com

domaindEe28資訊網——每日最新資訊28at.com

核心邏輯層,DDD 中核心組件,包括實體、值對象、聚合根、領域服務等dEe28資訊網——每日最新資訊28at.com

appdEe28資訊網——每日最新資訊28at.com

應用服務層,DDD 中的應用服務,主要負責流程編排dEe28資訊網——每日最新資訊28at.com

infrastructuredEe28資訊網——每日最新資訊28at.com

基礎設施層,主要負責與 DB 或其他服務進行通訊dEe28資訊網——每日最新資訊28at.com

apidEe28資訊網——每日最新資訊28at.com

RPC 服務中的接口定義,被 FeignClient 和 FeignService 依賴dEe28資訊網——每日最新資訊28at.com

FeignServicedEe28資訊網——每日最新資訊28at.com

api 中接口的實際實現者,完成接口的適配dEe28資訊網——每日最新資訊28at.com

FeignClientdEe28資訊網——每日最新資訊28at.com

api 中Proxy實現者,方便使用方直接調用dEe28資訊網——每日最新資訊28at.com

bootstrapdEe28資訊網——每日最新資訊28at.com

應用啟動入口,包括 Spring Boot 入口和所有配置dEe28資訊網——每日最新資訊28at.com

3.3. 啟動項目

3.3.1. 建庫建表

建表語句在infrastructure/src/main/resources/sql 目標下,包括單庫和分庫分表配置。單庫建表語句如下:dEe28資訊網——每日最新資訊28at.com

create table dislike_action(    id          bigint auto_increment primary key,    create_time datetime    not null,    delete_time datetime    null,    update_time datetime    null,    vsn         int         not null,    status      char(16)    not null,    target_id   bigint      not null,    target_type varchar(16) not null,    user_id     bigint      not null,    constraint unq_user_target        unique (user_id, target_type, target_id));create table dislike_target_count(    id          bigint auto_increment primary key,    create_time datetime    not null,    delete_time datetime    null,    update_time datetime    null,    vsn         int         not null,    count       bigint      not null,    target_id   bigint      not null,    target_type varchar(16) not null,    constraint unq_target        unique (target_id, target_type));create table like_action(    id          bigint auto_increment primary key,    create_time datetime    not null,    delete_time datetime    null,    update_time datetime    null,    vsn         int         not null,    status      char(16)    not null,    target_id   bigint      not null,    target_type varchar(16) not null,    user_id     bigint      not null,    constraint unq_user_target        unique (user_id, target_type, target_id));create table like_target_count(    id          bigint auto_increment primary key,    create_time datetime    not null,    delete_time datetime    null,    update_time datetime    null,    vsn         int         not null,    count       bigint      not null,    target_id   bigint      not null,    target_type varchar(16) not null,    constraint unq_target        unique (target_id, target_type));

3.3.2. 修改數據庫配置

修改bootstrap/src/main/resource/application.yml 增加數據配置,具體如下:dEe28資訊網——每日最新資訊28at.com

spring:  datasource:    driver-class-name: com.mysql.cj.jdbc.Driver    url: jdbc:mysql://127.0.0.1:3306/like    username: root    password: root

3.3.3. 啟動應用程序

直接運行 bootstrap 模塊下的 LikeApplication 類,輸入地址:http://127.0.0.1:8080/swagger-ui/dEe28資訊網——每日最新資訊28at.com

當看到如下界面證明程序啟動成功:dEe28資訊網——每日最新資訊28at.com

dEe28資訊網——每日最新資訊28at.com

3.3. 核心 API

核心接口如下:dEe28資訊網——每日最新資訊28at.com

功能dEe28資訊網——每日最新資訊28at.com

請求地址dEe28資訊網——每日最新資訊28at.com

參數類型dEe28資訊網——每日最新資訊28at.com

參數說明dEe28資訊網——每日最新資訊28at.com

返回結果dEe28資訊網——每日最新資訊28at.com

cur DemodEe28資訊網——每日最新資訊28at.com

點贊dEe28資訊網——每日最新資訊28at.com

POST /feignService/action/command/likedEe28資訊網——每日最新資訊28at.com

RequestBodydEe28資訊網——每日最新資訊28at.com

{"userId": 用戶id, "targetType": 目標對象類型,"targetId": 目標對象 id}dEe28資訊網——每日最新資訊28at.com

dEe28資訊網——每日最新資訊28at.com

curl -X POST "http://127.0.0.1:8080/feignService/action/command/like" -H "accept: /" -H "Content-Type: application/json" -d "{"targetId":1,"targetType":"TEST","userId":2}"dEe28資訊網——每日最新資訊28at.com

取消點贊dEe28資訊網——每日最新資訊28at.com

POST /feignService/action/command/unlikedEe28資訊網——每日最新資訊28at.com

RequestBodydEe28資訊網——每日最新資訊28at.com

{"userId": 用戶id, "targetType": 目標對象類型,"targetId": 目標對象 id}dEe28資訊網——每日最新資訊28at.com

dEe28資訊網——每日最新資訊28at.com

curl -X POST "http://127.0.0.1:8080/feignService/action/command/unlike" -H "accept: /" -H "Content-Type: application/json" -d "{"targetId":1,"targetType":"test","userId":2}"dEe28資訊網——每日最新資訊28at.com

獲取點贊數量dEe28資訊網——每日最新資訊28at.com

GET /feignService/targetCount/query/getLikeCountByTargetdEe28資訊網——每日最新資訊28at.com

RequestParamdEe28資訊網——每日最新資訊28at.com

type:目標類型;ids:目標id集合dEe28資訊網——每日最新資訊28at.com

[{"targetType":目標對象類型,“targetId":目標對象id,"count":點贊數量}]dEe28資訊網——每日最新資訊28at.com

curl -X GET "http://127.0.0.1:8080/feignService/targetCount/query/getLikeCountByTarget?type=test&ids=1" -H "accept: /"dEe28資訊網——每日最新資訊28at.com

獲取點贊記錄dEe28資訊網——每日最新資訊28at.com

GET /feignService/action/query/getLikeByUserAndTypedEe28資訊網——每日最新資訊28at.com

RequestParamdEe28資訊網——每日最新資訊28at.com

type:目標類型;userId:userIddEe28資訊網——每日最新資訊28at.com

[{"targetType":目標對象類型,“targetId":目標對象id,"userId":用戶id,"valid":是否有效}]dEe28資訊網——每日最新資訊28at.com

curl -X GET "http://127.0.0.1:8080/feignService/action/query/getLikeByUserAndType?userId=2&type=test" -H "accept: /"dEe28資訊網——每日最新資訊28at.com

dEe28資訊網——每日最新資訊28at.com

POST /feignService/action/command/dislikedEe28資訊網——每日最新資訊28at.com

RequestBodydEe28資訊網——每日最新資訊28at.com

{"userId": 用戶id, "targetType": 目標對象類型,"targetId": 目標對象 id}dEe28資訊網——每日最新資訊28at.com

dEe28資訊網——每日最新資訊28at.com

curl -X POST "http://127.0.0.1:8080/feignService/action/command/dislike" -H "accept: /" -H "Content-Type: application/json" -d "{"targetId":1,"targetType":"test","userId":2}"dEe28資訊網——每日最新資訊28at.com

取消踩dEe28資訊網——每日最新資訊28at.com

POST /feignService/action/command/unDislikedEe28資訊網——每日最新資訊28at.com

RequestBodydEe28資訊網——每日最新資訊28at.com

{"userId": 用戶id, "targetType": 目標對象類型,"targetId": 目標對象 id}dEe28資訊網——每日最新資訊28at.com

dEe28資訊網——每日最新資訊28at.com

curl -X POST "http://127.0.0.1:8080/feignService/action/command/unDislike" -H "accept: /" -H "Content-Type: application/json" -d "{"targetId":1,"targetType":"test","userId":2}"dEe28資訊網——每日最新資訊28at.com

獲取踩數量dEe28資訊網——每日最新資訊28at.com

GET /feignService/targetCount/query/getDislikeCountByTypedEe28資訊網——每日最新資訊28at.com

RequestParamdEe28資訊網——每日最新資訊28at.com

type:目標類型;ids:目標id集合dEe28資訊網——每日最新資訊28at.com

[{"targetType":目標對象類型,“targetId":目標對象id,"count":點贊數量}]dEe28資訊網——每日最新資訊28at.com

curl -X GET "http://127.0.0.1:8080/feignService/targetCount/query/getDislikeCountByType?type=test&ids=1" -H "accept: /"dEe28資訊網——每日最新資訊28at.com

獲取點贊記錄dEe28資訊網——每日最新資訊28at.com

GET /feignService/action/query/getDislikeByUserAndTypedEe28資訊網——每日最新資訊28at.com

RequestParamdEe28資訊網——每日最新資訊28at.com

type:目標類型;userId:userIddEe28資訊網——每日最新資訊28at.com

[{"targetType":目標對象類型,“targetId":目標對象id,"userId":用戶id,"valid":是否有效}]dEe28資訊網——每日最新資訊28at.com

curl -X GET "http://127.0.0.1:8080/feignService/action/query/getDislikeByUserAndType?userId=2&type=test" -H "accept: /"dEe28資訊網——每日最新資訊28at.com

核心API直接在 Swagger UI 上進行測試即可?。。?span style="display:none">dEe28資訊網——每日最新資訊28at.com

4. 高級特性

4.1. 自定義業務驗證

流程中涉及兩個重要的概念:dEe28資訊網——每日最新資訊28at.com

  • ActionUser: 操作 贊或踩 的用戶;
  • ActionTarget: 贊或踩 的目的對象;

在實際業務場景,需要對這兩個對象的有效性進行驗證,比如:dEe28資訊網——每日最新資訊28at.com

  • ActionUser

用戶是否存在?dEe28資訊網——每日最新資訊28at.com

用戶狀態是否有效?dEe28資訊網——每日最新資訊28at.com

是否是黑名單用戶?dEe28資訊網——每日最新資訊28at.com

  • ActionTarget
  • 目標對象是否存在?
  • 目標對象是否已經下線/禁用?

這些功能擴展直接實現對應的 Loader 即可。dEe28資訊網——每日最新資訊28at.com

4.1.1. ActionUser 擴展

ActionUser 定義如下:dEe28資訊網——每日最新資訊28at.com

public class ActionUser {    @Column(name = "user_id", updatable = false)    private Long userId;    @Transient    private boolean valid;}

如果用戶狀態存在問題,直接將 valid 置為 false 即可。dEe28資訊網——每日最新資訊28at.com

ActionUserLoader 定義如下:dEe28資訊網——每日最新資訊28at.com

public interface ActionUserLoader {    ActionUser loadByUserId(Long userId);}

只需實現 ActionUserLoader 并注冊為 Spring 托管 Bean 即可,具體如下:dEe28資訊網——每日最新資訊28at.com

@Component(value = LoadActionUserByUserId.BEAN_NAME)public class TestActionUserLoader implements ActionUserLoader {    @Override    public ActionUser loadByUserId(Long userId) {        if (userId == null || userId.longValue() < 0){            return ActionUser.apply(userId, false);        }else {            return ActionUser.apply(userId);        }    }}

當 userId 為 null 或者 小于 0 時,表明為無效用戶,將 valid 設置為 false。dEe28資訊網——每日最新資訊28at.com

【備注】Bean 必須注冊為LoadActionUserByUserId.BEAN_NAME(actionUserLoader),否則框架將無法識別。dEe28資訊網——每日最新資訊28at.com

4.1.2. ActionTarget 擴展

ActionTarget 定義如下:dEe28資訊網——每日最新資訊28at.com

public class ActionTarget {    @Column(name = "target_type", updatable = false)    private String type;    @Column(name = "target_id", updatable = false)    private Long id;    @Transient    private boolean valid;}

如果目標對象狀態存在問題,直接將 valid 置為 false 即可。dEe28資訊網——每日最新資訊28at.com

由于系統中可以存在多種目標對象,為每個類型提供單獨的 Loader,接口如下:dEe28資訊網——每日最新資訊28at.com

public interface SingleActionTargetLoader {    /**     * 是否支持 type 類型的 Target     * @param type     * @return     */    boolean support(String type);    /**     * 加載 Target 對象     * @param type     * @param id     * @return     */    ActionTarget load(String type, Long id);}

按需要實現接口,樣例如下:dEe28資訊網——每日最新資訊28at.com

@Component@Order(0)public class TestActionTargetLoader        extends AbstractSingleActionTargetLoader        implements SingleActionTargetLoader {    public TestActionTargetLoader() {        super("Test");    }    @Override    protected ActionTarget doLoadById(String type, Long id) {        if (id == null || id.longValue() < 0){            return ActionTarget.apply(type, id, false);        }else {            return ActionTarget.apply(type, id);        }    }}

該實現對 type 為 Test 的 Target 進行加載。dEe28資訊網——每日最新資訊28at.com

4.2. 發布領域事件

領域事件是 DDD 中的重要概念,當系統發生狀態變化后,將變化結果對外進行廣播,從而實現系統間的集成。dEe28資訊網——每日最新資訊28at.com

4.2.1. 添加 RocketMQ

外部領域事件通過 RocketMQ 向外廣播,需要搭建 RocketMQ 集群并在項目中增加 RocketMQ 的支持。dEe28資訊網——每日最新資訊28at.com

在 bootstrap 模塊的 pom 中增加 rocketmq starter,具體如下:dEe28資訊網——每日最新資訊28at.com

<dependency>    <groupId>org.apache.rocketmq</groupId>    <artifactId>rocketmq-spring-boot-starter</artifactId></dependency>

在 application.yml 增加 rocketmq 的配置,具體如下:dEe28資訊網——每日最新資訊28at.com

rocketmq:  name-server: http://127.0.0.1:9876  producer:    group: like-service

至此,便完成了與 rocketmq 的集成。dEe28資訊網——每日最新資訊28at.com

4.2.2. 打開領域事件開關

在 application.yml 添加如下配置:dEe28資訊網——每日最新資訊28at.com

like:  event:    #開啟領域事件    enable: true    #指定領域事件發送的 topic    topic: like-event-topic

開啟領域事件,并指定事件發送的 topicdEe28資訊網——每日最新資訊28at.com

4.2.3. 測試領域事件

重新啟動項目,當控制臺輸出以下表明配置成功:dEe28資訊網——每日最新資訊28at.com

Use RocketMQ to Publish Like EventdEe28資訊網——每日最新資訊28at.com

使用 swagger 運行 dislike 操作,從日志中可知消息發送成功:dEe28資訊網——每日最新資訊28at.com

dEe28資訊網——每日最新資訊28at.com

4.2.4. 支持領域事件

系統支持的領域事件包括:dEe28資訊網——每日最新資訊28at.com

領域事件類型dEe28資訊網——每日最新資訊28at.com

觸發機制dEe28資訊網——每日最新資訊28at.com

tagdEe28資訊網——每日最新資訊28at.com

消息體dEe28資訊網——每日最新資訊28at.com

LikeMarkedEventdEe28資訊網——每日最新資訊28at.com

點贊成功dEe28資訊網——每日最新資訊28at.com

LikeMarkedEventdEe28資訊網——每日最新資訊28at.com

見 LikeMarkedEvent 類dEe28資訊網——每日最新資訊28at.com

LikeCancelledEventdEe28資訊網——每日最新資訊28at.com

取消點贊成功dEe28資訊網——每日最新資訊28at.com

LikeCancelledEventdEe28資訊網——每日最新資訊28at.com

見 LikeCancelledEvent 類dEe28資訊網——每日最新資訊28at.com

DislikeMarkedEventdEe28資訊網——每日最新資訊28at.com

踩成功dEe28資訊網——每日最新資訊28at.com

DislikeMarkedEventdEe28資訊網——每日最新資訊28at.com

見 DislikeMarkedEvent 類dEe28資訊網——每日最新資訊28at.com

DislikeCancelledEventdEe28資訊網——每日最新資訊28at.com

取消踩成功dEe28資訊網——每日最新資訊28at.com

DislikeCancelledEventdEe28資訊網——每日最新資訊28at.com

見 DislikeCancelledEvent 類dEe28資訊網——每日最新資訊28at.com

4.3. 緩存加速

在系統中,獲取目標對象的 贊/踩 數量接口調用量最大,會成為系統的第一個性能卡點,針對這個問題,可以通過引入 redis 緩存進行性能加速。dEe28資訊網——每日最新資訊28at.com

4.3.1. 添加 redis 依賴

首先需要引入 redis 相關依賴,在 bootstrap 的 pom 中增加如下配置:dEe28資訊網——每日最新資訊28at.com

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-data-redis</artifactId></dependency>

然后在 application.yml 中增加 redis 相關配置:dEe28資訊網——每日最新資訊28at.com

spring:  redis:    host: 127.0.0.1    port: 6379

4.3.2. 開啟緩存

完成redis配置后,需要在 application.yml 開啟對應的緩存,具體如下:dEe28資訊網——每日最新資訊28at.com

target:  count:    dislike:      cache:        # 是否開啟緩存        enable: true    like:      cache:        # 是否開啟緩存        enable: true

4.3.3. 緩存效果

未開啟緩存前,每次查詢數量都會執行一條 sql,具體如下:curl 命令如下:dEe28資訊網——每日最新資訊28at.com

curl -X GET "http://127.0.0.1:8080/feignService/targetCount/query/getDislikeCountByType?type=test&ids=1" -H "accept: */*"

輸出 sql 如下:dEe28資訊網——每日最新資訊28at.com

Hibernate: select disliketar0_.id as id1_1_, disliketar0_.create_time as create_t2_1_, disliketar0_.delete_time as delete_t3_1_, disliketar0_.update_time as update_t4_1_, disliketar0_.vsn as vsn5_1_, disliketar0_.count as count6_1_, disliketar0_.target_id as target_i7_1_, disliketar0_.target_type as target_t8_1_ from dislike_target_count disliketar0_ where disliketar0_.target_type=? and (disliketar0_.target_id in (?))

開啟緩存后,再次執行以上 curl,控制臺不會輸出sql,而是會輸出一行日志:dEe28資訊網——每日最新資訊28at.com

c.g.l.i.s.RedisBasedTargetCountCache     : load All Data From Cache for test and [1]

說明緩存已經生效。dEe28資訊網——每日最新資訊28at.com

所有的 action 操作都會與同步的對緩存進行更新。dEe28資訊網——每日最新資訊28at.com

4.4. 異步存儲

當目標對象出現熱點時,會產生高并發請求,對于 action 來說,主要以數據插入和數據的分散更新為主。但對于 count,就會產生熱點更新,從而成為系統的瓶頸。在這個場景,最適合的解決方案便是引入 MQ 對流量進行削峰填谷。dEe28資訊網——每日最新資訊28at.com

4.4.1. 增加 rocketmq

與 4.2.1. 添加 RocketMQ 內容一致,在此不再重復。dEe28資訊網——每日最新資訊28at.com

4.4.2. 開啟異步化

在 application.yml 中增加如下配置:dEe28資訊網——每日最新資訊28at.com

target:  count:    dislike:      async:        # 是否開啟異步更新        enable: true        # 異步更新所使用的 topic        topic: dislike-target-count-async-topic        # 異步更新使用的消費者組        consumerGroup: dislike-target-count-async-group    like:      async:        # 是否開啟異步更新        enable: true        # 異步更新所使用的 topic        topic: like-target-count-async-topic        # 異步更新使用的消費者組        consumerGroup: like-target-count-async-group

4.4.3. 異步效果

重啟應用程序,在 swagger 中執行 點贊 操作,從控制臺可以看到如下日志:dEe28資訊網——每日最新資訊28at.com

[nio-8080-exec-7] c.g.l.c.a.order.OrderedAsyncInterceptor  : success to send orderly async Task to RocketMQ, args is [ActionTarget(type=test, id=18, valid=true), 1], shardingKey is 18, msg is GenericMessage [payload={"0":"{/"type/":/"test/",/"id/":18,/"valid/":true}","1":"1"}, headers={id=c84e6be5-acec-27c2-3f44-6250003a56c7, timestamp=1685275901638}], result is SendResult [sendStatus=SEND_OK, msgId=7F0000014F505C8DA9628F610AC60007, offsetMsgId=C0A8032300002A9F00000000001A0AFD, messageQueue=MessageQueue [topic=dislike-target-count-async-topic, brokerName=MacdeMacBook-Pro-171.local, queueId=3], queueOffset=8][MessageThread_4] g.l.i.d.DislikeTargetCountRepositoryImpl : begin to incr for db target ActionTarget(type=test, id=18, valid=true), count 1[nio-8080-exec-7] com.geekhalo.like.app.RocketMQPublisher  : success to send msg GenericMessage [payload={"targetId":18,"targetType":"test","userId":1}, headers={id=4e8e13f9-b3cd-7b90-059f-f506f09d9948, timestamp=1685275901640}] to like-event-topic:DislikeMarkedEvent, msgId is 7F0000014F505C8DA9628F610AC80008[nio-8080-exec-7] c.g.l.c.c.s.AbstractCommandService       : success to sync AbstractCommandService.Syncer.Data(id=106, action=UPDATE, a=DislikeAction(super=AbstractAction(super=AbstractAggRoot(super=AbstractEntity(vsn=0, createAt=Sun May 28 20:11:41 CST 2023, updateAt=Sun May 28 20:11:41 CST 2023, deleteAt=null), events=[]), id=106, user=ActionUser(userId=1, valid=true), target=ActionTarget(type=test, id=18, valid=true), status=VALID)))[MessageThread_4] g.l.i.d.DislikeTargetCountRepositoryImpl : success to incr for db target ActionTarget(type=test, id=18, valid=true), count 1[MessageThread_4] .s.AbstractSingleMethodConsumerContainer : consume message 7F0000014F505C8DA9628F610AC60007, cost: 27 ms

從日志上看,可以得出:dEe28資訊網——每日最新資訊28at.com

  • nio 線程向 MQ 發送消息
  • MessageThread 線程從 MQ 中獲取數據并執行 incr 操作

4.5. 分庫分表

隨著系統的運行,數據量會逐漸增大,最終超出單個 DB 的容量上限。這種情況下,最佳實踐便是對數據庫進行分庫分表。dEe28資訊網——每日最新資訊28at.com

4.5.1. 構建數據庫和表

在 infrastructure 模塊的 sql 目錄下存在兩個 sql 文件:dEe28資訊網——每日最新資訊28at.com

  • create_table_sharding_action.sql : 贊/踩 操作分庫分表
  • create_table_sharding_count.sql : 贊/踩 計數分庫分表

示例中總共分16張表,存放在兩個數據庫中:dEe28資訊網——每日最新資訊28at.com

  • db1 存放 0-7 表
  • db2 存放 8-15 表

如圖所示:dEe28資訊網——每日最新資訊28at.com

4.5.2. 添加 ShardingSphere 支持

在 bootstrap 的pom 文件增加 ShardingSphere 的依賴,具體如下:dEe28資訊網——每日最新資訊28at.com

<dependency>    <groupId>org.apache.shardingsphere</groupId>    <artifactId>sharding-jdbc-spring-boot-starter</artifactId></dependency>

其次,增加分庫分表配置文件,為了方便新建 application.properties 存放分庫分表配置:dEe28資訊網——每日最新資訊28at.com

# 數據源配置# 總共4個數據源spring.shardingsphere.datasource.names=action-ds0, action-ds1, count-ds0, count-ds1 # action-ds0 數據源配置spring.shardingsphere.datasource.action-ds0.type=com.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.action-ds0.driver-class-name=com.mysql.cj.jdbc.Driverspring.shardingsphere.datasource.action-ds0.jdbc-url=jdbc:mysql://127.0.0.1:3306/like_action_0?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTCspring.shardingsphere.datasource.action-ds0.username=rootspring.shardingsphere.datasource.action-ds0.password=root# action-ds1 數據源配置spring.shardingsphere.datasource.action-ds1.type=com.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.action-ds1.driver-class-name=com.mysql.cj.jdbc.Driverspring.shardingsphere.datasource.action-ds1.jdbc-url=jdbc:mysql://127.0.0.1:3306/like_action_1?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTCspring.shardingsphere.datasource.action-ds1.username=rootspring.shardingsphere.datasource.action-ds1.password=root# count-ds0 數據源配置spring.shardingsphere.datasource.count-ds0.type=com.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.count-ds0.driver-class-name=com.mysql.cj.jdbc.Driverspring.shardingsphere.datasource.count-ds0.jdbc-url=jdbc:mysql://127.0.0.1:3306/like_count_0?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTCspring.shardingsphere.datasource.count-ds0.username=rootspring.shardingsphere.datasource.count-ds0.password=root# count-ds1 數據源配置spring.shardingsphere.datasource.count-ds1.type=com.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.count-ds1.driver-class-name=com.mysql.cj.jdbc.Driverspring.shardingsphere.datasource.count-ds1.jdbc-url=jdbc:mysql://127.0.0.1:3306/like_count_1?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTCspring.shardingsphere.datasource.count-ds1.username=rootspring.shardingsphere.datasource.count-ds1.password=root# 分庫分表規則配置# 使用雪花算法生成分布式主鍵id的值spring.shardingsphere.sharding.default-key-generator.column=idspring.shardingsphere.sharding.default-key-generator.column-type=BIGINTspring.shardingsphere.sharding.default-key-generator.type=SNOWFLAKEspring.shardingsphere.sharding.default-key-generator.algorithm-expression=SNOWFLAKE_HASH(id, 12)spring.shardingsphere.sharding.default-key-generator.matrix-handling-type=SHARDING_DEFAULT# 踩行為表配置spring.shardingsphere.sharding.tables.dislike_action.actual-data-nodes=action-ds0.dislike_action_$->{0..7},action-ds1.dislike_action_$->{8..15}# user_id 為分表分片鍵spring.shardingsphere.sharding.tables.dislike_action.table-strategy.inline.sharding-column=user_id# 根據 user_id 以 16 取模,進行分表spring.shardingsphere.sharding.tables.dislike_action.table-strategy.inline.algorithm-expression=dislike_action_$->{Math.abs(user_id.hashCode())  % 16}# user_id 為分庫分片鍵spring.shardingsphere.sharding.tables.dislike_action.database-strategy.inline.sharding-column=user_id# 根據 user_id 以 16 取模后除8 ,進行分庫spring.shardingsphere.sharding.tables.dislike_action.database-strategy.inline.algorithm-expression=action-ds$->{Math.floorDiv((Math.abs(user_id.hashCode())  % 16) , 8)}spring.shardingsphere.sharding.tables.like_action.actual-data-nodes=action-ds0.like_action_$->{0..7},action-ds1.like_action_$->{8..15}spring.shardingsphere.sharding.tables.like_action.table-strategy.inline.sharding-column=user_idspring.shardingsphere.sharding.tables.like_action.table-strategy.inline.algorithm-expression=like_action_$->{Math.abs(user_id.hashCode())  % 16}spring.shardingsphere.sharding.tables.like_action.database-strategy.inline.sharding-column=user_idspring.shardingsphere.sharding.tables.like_action.database-strategy.inline.algorithm-expression=action-ds$->{Math.floorDiv((Math.abs(user_id.hashCode())  % 16) , 8)}# 計數表配置spring.shardingsphere.sharding.tables.dislike_target_count.actual-data-nodes=count-ds0.dislike_target_count_$->{0..7},count-ds1.dislike_target_count_$->{8..15}# target_id 為分表分片鍵spring.shardingsphere.sharding.tables.dislike_target_count.table-strategy.inline.sharding-column=target_id# 根據 target_id 以 16 取模,進行分表spring.shardingsphere.sharding.tables.dislike_target_count.table-strategy.inline.algorithm-expression=dislike_target_count_$->{Math.abs(target_id.hashCode())  % 16}# target_id 為分庫分片鍵spring.shardingsphere.sharding.tables.dislike_target_count.database-strategy.inline.sharding-column=target_id# 根據 target_id 以 16 取模后除8 ,進行分庫spring.shardingsphere.sharding.tables.dislike_target_count.database-strategy.inline.algorithm-expression=count-ds$->{Math.floorDiv((Math.abs(target_id.hashCode()) % 16), 8)}spring.shardingsphere.sharding.tables.like_target_count.actual-data-nodes=count-ds0.like_target_count_$->{0..7},count-ds1.like_target_count_$->{8..15}spring.shardingsphere.sharding.tables.like_target_count.table-strategy.inline.sharding-column=target_idspring.shardingsphere.sharding.tables.like_target_count.table-strategy.inline.algorithm-expression=like_target_count_$->{Math.abs(target_id.hashCode()) % 16}spring.shardingsphere.sharding.tables.like_target_count.database-strategy.inline.sharding-column=target_idspring.shardingsphere.sharding.tables.like_target_count.database-strategy.inline.algorithm-expression=count-ds$->{Math.floorDiv((Math.abs(target_id.hashCode()) % 16), 8)}# 打印 SQL 配置(可選)spring.shardingsphere.props.sql.show=true

在雪花算法情況下,尾數會變的極度不均勻,所以在進行計算之前,通常先執行 hashCode 在進行取模操作。dEe28資訊網——每日最新資訊28at.com

4.5.3. 分庫分表效果

啟動應用程序,控制臺輸出 sharding 相關配置,具體如下:dEe28資訊網——每日最新資訊28at.com

defaultKeyGenerator:  column: id  type: SNOWFLAKEtables:  dislike_action:    actualDataNodes: action-ds0.dislike_action_$->{0..7},action-ds1.dislike_action_$->{8..15}    databaseStrategy:      inline:        algorithmExpression: action-ds$->{Math.floorDiv((Math.abs(user_id.hashCode())  % 16) , 8)}        shardingColumn: user_id    logicTable: dislike_action    tableStrategy:      inline:        algorithmExpression: dislike_action_$->{Math.abs(user_id.hashCode()) % 16}        shardingColumn: user_id  like_action:    actualDataNodes: action-ds0.like_action_$->{0..7},action-ds1.like_action_$->{8..15}    databaseStrategy:      inline:        algorithmExpression: action-ds$->{Math.floorDiv((Math.abs(user_id.hashCode())  % 16) , 8)}        shardingColumn: user_id    logicTable: like_action    tableStrategy:      inline:        algorithmExpression: like_action_$->{Math.abs(user_id.hashCode())  % 16}        shardingColumn: user_id  dislike_target_count:    actualDataNodes: count-ds0.dislike_target_count_$->{0..7},count-ds1.dislike_target_count_$->{8..15}    databaseStrategy:      inline:        algorithmExpression: count-ds$->{Math.floorDiv((Math.abs(target_id.hashCode()) % 16), 8)}        shardingColumn: target_id    logicTable: dislike_target_count    tableStrategy:      inline:        algorithmExpression: dislike_target_count_$->{Math.abs(target_id.hashCode())  % 16}        shardingColumn: target_id  like_target_count:    actualDataNodes: count-ds0.like_target_count_$->{0..7},count-ds1.like_target_count_$->{8..15}    databaseStrategy:      inline:        algorithmExpression: count-ds$->{Math.floorDiv((Math.abs(target_id.hashCode()) % 16), 8)}        shardingColumn: target_id    logicTable: like_target_count    tableStrategy:      inline:        algorithmExpression: like_target_count_$->{Math.abs(target_id.hashCode()) % 16}        shardingColumn: target_id

在 Swagger UI 中操作點贊,控制臺輸出如下:dEe28資訊網——每日最新資訊28at.com

Logic SQL: select dislikeact0_.id as id1_0_, dislikeact0_.create_time as create_t2_0_, dislikeact0_.delete_time as delete_t3_0_, dislikeact0_.update_time as update_t4_0_, dislikeact0_.vsn as vsn5_0_, dislikeact0_.status as status6_0_, dislikeact0_.target_id as target_i7_0_, dislikeact0_.target_type as target_t8_0_, dislikeact0_.user_id as user_id9_0_ from dislike_action dislikeact0_ where dislikeact0_.user_id=? and dislikeact0_.target_type=?Actual SQL: action-ds0 ::: select dislikeact0_.id as id1_0_, dislikeact0_.create_time as create_t2_0_, dislikeact0_.delete_time as delete_t3_0_, dislikeact0_.update_time as update_t4_0_, dislikeact0_.vsn as vsn5_0_, dislikeact0_.status as status6_0_, dislikeact0_.target_id as target_i7_0_, dislikeact0_.target_type as target_t8_0_, dislikeact0_.user_id as user_id9_0_ from dislike_action_0 dislikeact0_ where dislikeact0_.user_id=? and dislikeact0_.target_type=? ::: [2707692781417059328, Test]

其中:dEe28資訊網——每日最新資訊28at.com

  • Logic SQL:邏輯 SQL 中的表為 dislike_action
  • Actual SQL:實際執行的 SQL 表為 dislike_action_0,數據庫為 action-ds0

5. 項目信息

項目地址見:https://gitee.com/litao851025/lego/tree/master/services/likedEe28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-15763-0.html基于 DDD 的互聯網“贊&amp;踩”系統

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Spring 框架中Spring Cache緩存解決方案

下一篇: 微服務之負載均衡使用場景

標簽:
  • 熱門焦點
  • CSS單標簽實現轉轉logo

    轉轉品牌升級后更新了全新的Logo,今天我們用純CSS來實現轉轉的新Logo,為了有一定的挑戰性,這里我們只使用一個標簽實現,將最大化的使用CSS能力完成Logo的繪制與動畫效果。新logo
  • 學習JavaScript的10個理由...

    作者 | Simplilearn編譯 | 王瑞平當你決心學習一門語言的時候,很難選擇到底應該學習哪一門,常用的語言有Python、Java、JavaScript、C/CPP、PHP、Swift、C#、Ruby、Objective-
  • 如何使用JavaScript創建一只圖像放大鏡?

    譯者 | 布加迪審校 | 重樓如果您曾經瀏覽過購物網站,可能遇到過圖像放大功能。它可以讓您放大圖像的特定區域,以便瀏覽。結合這個小小的重要功能可以大大改善您網站的用戶體驗
  • 破圈是B站頭上的緊箍咒

    來源 | 光子星球撰文 | 吳坤諺編輯 | 吳先之每年的暑期檔都少不了瞄準追劇女孩們的古偶劇集,2021年有優酷的《山河令》,2022年有愛奇藝的《蒼蘭訣》,今年卻輪到小破站抓住了追
  • “又被陳思誠騙了”

    作者|張思齊 出品|眾面(ID:ZhongMian_ZM)如今的國產懸疑電影,成了陳思誠的天下。最近大爆電影《消失的她》票房突破30億斷層奪魁暑期檔,陳思誠再度風頭無兩。你可以說陳思誠的
  • 蘋果公司要求三星和LG Display生產「無邊框」OLED iPhone顯示屏

    據 The Elec 報道,蘋果已要求其供應商為未來的 iPhone 型號開發「無邊框」OLED 顯示面板。蘋果顯然已要求三星和 LG Display 開發新的 OLED 顯示面
  • 支持aptX Lossless無損傳輸 iQOO TWS 1賽道版發布限時優惠價369元

    2023年7月4日,“無損音質,聲動人心”iQOO TWS 1正式發布,支持aptX Lossless無損傳輸,限時優惠價369元。iQOO TWS 1耳機率先支持端到端aptX Lossless無
  • iQOO Neo8系列今日官宣:首發天璣9200+ 全球安卓最強芯!

    在昨日舉行的的聯發科新一代旗艦芯片天璣9200+的發布會上,iQOO官方也正式宣布,全新的iQOO Neo8系列新品將全球首發搭載這款當前性能最強大的移動平臺
  • Counterpoint :OPPO雙旗艦戰略全面落地 高端產品銷量增長22%

    2023年6月30日,全球行業分析機構Counterpoint Research發布的《中國智能手機高端市場白皮書》顯示,中國智能手機品牌正在尋求高質量發展,中國高端智能
Top 主站蜘蛛池模板: 黄山市| 平潭县| 剑川县| 刚察县| 梁山县| 呼和浩特市| 诸暨市| 仁怀市| 长沙县| 九龙坡区| 马龙县| 蒲江县| 玉环县| 长子县| 东光县| 察雅县| 新建县| 牟定县| 枞阳县| 宜宾市| 淳安县| 吉木萨尔县| 大方县| 玉田县| 全椒县| 桐城市| 田阳县| 宝鸡市| 桃园市| 克拉玛依市| 西平县| 梁河县| 沂南县| 腾冲县| 孝昌县| 嵊州市| 高台县| 麻江县| 永城市| 临西县| 高唐县|