自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

基于 DDD 的互聯(lián)網(wǎng)“贊&踩”系統(tǒng)

開發(fā) 架構
贊/踩服務是一種用戶反饋機制。隨著社交媒體的普及和發(fā)展,人們越來越喜歡在一種平臺上分享自己的觀點和生活,這時就需要一種形式化的反饋機制來快速評價這些信息的好壞。贊/踩服務的目標是為了提高用戶互動性,增加內(nèi)容的社會影響力,從而增加活躍用戶數(shù)量。

該文是系統(tǒng)的用戶手冊,主要體現(xiàn)系統(tǒng)功能和所支持的高級特性,關于系統(tǒng)的核心設計正在整理中,請稍安勿躁

1. 背景

隨著社交媒體的普及,用戶生成的內(nèi)容數(shù)量急劇增加。為了幫助用戶更好地發(fā)現(xiàn)和分享內(nèi)容,許多社交媒體平臺都提供了贊/踩服務。

2. 目標

贊/踩服務是一種用戶反饋機制。隨著社交媒體的普及和發(fā)展,人們越來越喜歡在一種平臺上分享自己的觀點和生活,這時就需要一種形式化的反饋機制來快速評價這些信息的好壞。贊/踩服務的目標是為了提高用戶互動性,增加內(nèi)容的社會影響力,從而增加活躍用戶數(shù)量。

3. 快速入門

系統(tǒng)所涉及的功能包括:

功能

描述

贊/踩

用戶可以點擊對應的贊或踩按鈕,以表達自己的喜好或不喜好

取消贊/踩

用戶可以取消之前的贊/踩,以更正自己的想法

計數(shù)器

贊和踩的數(shù)量都需要計數(shù)器,用于顯示文章或評論的受歡迎程度和社交影響力等

贊/踩歷史

用戶可以查看自己贊/踩的歷史記錄,以查看自己對文章或評論的態(tài)度

3.1. 開發(fā)環(huán)境

基于 Spring Boot 框架進行開發(fā),以 DDD 作為業(yè)務邏輯承載模型。

框架

版本

依賴說明

JDK

1.8+

運行環(huán)境

Spring Boot

2.3.12.RELEASE


Spring Data

2.3.9.RELEASE

基于 JPA 實現(xiàn)持久化;基于 Redis 完成緩存加速(可選)

Lego

0.1.22

DDD 模型落地

springfox

3.0.0

文檔管理

RocketMQ

2.2.1

領域事件,異步處理(可選)

Sharding Sphere

4.4.1

分庫分表(可選)

3.2. 模塊介紹

該項目使用標準的 “六邊形架構”,對業(yè)務和技術進行分離,所以模塊較多,但層次更為清晰。

模塊

作用

domain

核心邏輯層,DDD 中核心組件,包括實體、值對象、聚合根、領域服務等

app

應用服務層,DDD 中的應用服務,主要負責流程編排

infrastructure

基礎設施層,主要負責與 DB 或其他服務進行通訊

api

RPC 服務中的接口定義,被 FeignClient 和 FeignService 依賴

FeignService

api 中接口的實際實現(xiàn)者,完成接口的適配

FeignClient

api 中Proxy實現(xiàn)者,方便使用方直接調(diào)用

bootstrap

應用啟動入口,包括 Spring Boot 入口和所有配置

3.3. 啟動項目

3.3.1. 建庫建表

建表語句在infrastructure/src/main/resources/sql 目標下,包括單庫和分庫分表配置。單庫建表語句如下:

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. 修改數(shù)據(jù)庫配置

修改bootstrap/src/main/resource/application.yml 增加數(shù)據(jù)配置,具體如下:

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/

當看到如下界面證明程序啟動成功:

3.3. 核心 API

核心接口如下:

功能

請求地址

參數(shù)類型

參數(shù)說明

返回結果

cur Demo

點贊

POST /feignService/action/command/like

RequestBody

{"userId": 用戶id, "targetType": 目標對象類型,"targetId": 目標對象 id}

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}"

取消點贊

POST /feignService/action/command/unlike

RequestBody

{"userId": 用戶id, "targetType": 目標對象類型,"targetId": 目標對象 id}

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}"

獲取點贊數(shù)量

GET /feignService/targetCount/query/getLikeCountByTarget

RequestParam

type:目標類型;ids:目標id集合

[{"targetType":目標對象類型,“targetId":目標對象id,"count":點贊數(shù)量}]

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

獲取點贊記錄

GET /feignService/action/query/getLikeByUserAndType

RequestParam

type:目標類型;userId:userId

[{"targetType":目標對象類型,“targetId":目標對象id,"userId":用戶id,"valid":是否有效}]

curl -X GET "http://127.0.0.1:8080/feignService/action/query/getLikeByUserAndType?userId=2&type=test" -H "accept: /"

POST /feignService/action/command/dislike

RequestBody

{"userId": 用戶id, "targetType": 目標對象類型,"targetId": 目標對象 id}

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}"

取消踩

POST /feignService/action/command/unDislike

RequestBody

{"userId": 用戶id, "targetType": 目標對象類型,"targetId": 目標對象 id}

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}"

獲取踩數(shù)量

GET /feignService/targetCount/query/getDislikeCountByType

RequestParam

type:目標類型;ids:目標id集合

[{"targetType":目標對象類型,“targetId":目標對象id,"count":點贊數(shù)量}]

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

獲取點贊記錄

GET /feignService/action/query/getDislikeByUserAndType

RequestParam

type:目標類型;userId:userId

[{"targetType":目標對象類型,“targetId":目標對象id,"userId":用戶id,"valid":是否有效}]

curl -X GET "http://127.0.0.1:8080/feignService/action/query/getDislikeByUserAndType?userId=2&type=test" -H "accept: /"

核心API直接在 Swagger UI 上進行測試即可?。。?/p>

4. 高級特性

4.1. 自定義業(yè)務驗證

流程中涉及兩個重要的概念:

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

在實際業(yè)務場景,需要對這兩個對象的有效性進行驗證,比如:

  • ActionUser

用戶是否存在?

用戶狀態(tài)是否有效?

是否是黑名單用戶?

  • ActionTarget
  • 目標對象是否存在?
  • 目標對象是否已經(jīng)下線/禁用?

這些功能擴展直接實現(xiàn)對應的 Loader 即可。

4.1.1. ActionUser 擴展

ActionUser 定義如下:

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

如果用戶狀態(tài)存在問題,直接將 valid 置為 false 即可。

ActionUserLoader 定義如下:

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

只需實現(xiàn) ActionUserLoader 并注冊為 Spring 托管 Bean 即可,具體如下:

@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。

【備注】Bean 必須注冊為LoadActionUserByUserId.BEAN_NAME(actionUserLoader),否則框架將無法識別。

4.1.2. ActionTarget 擴展

ActionTarget 定義如下:

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;
}

如果目標對象狀態(tài)存在問題,直接將 valid 置為 false 即可。

由于系統(tǒng)中可以存在多種目標對象,為每個類型提供單獨的 Loader,接口如下:

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

按需要實現(xiàn)接口,樣例如下:

@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);
        }
    }
}

該實現(xiàn)對 type 為 Test 的 Target 進行加載。

4.2. 發(fā)布領域事件

領域事件是 DDD 中的重要概念,當系統(tǒng)發(fā)生狀態(tài)變化后,將變化結果對外進行廣播,從而實現(xiàn)系統(tǒng)間的集成。

4.2.1. 添加 RocketMQ

外部領域事件通過 RocketMQ 向外廣播,需要搭建 RocketMQ 集群并在項目中增加 RocketMQ 的支持。

在 bootstrap 模塊的 pom 中增加 rocketmq starter,具體如下:

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

在 application.yml 增加 rocketmq 的配置,具體如下:

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

至此,便完成了與 rocketmq 的集成。

4.2.2. 打開領域事件開關

在 application.yml 添加如下配置:

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

開啟領域事件,并指定事件發(fā)送的 topic

4.2.3. 測試領域事件

重新啟動項目,當控制臺輸出以下表明配置成功:

Use RocketMQ to Publish Like Event

使用 swagger 運行 dislike 操作,從日志中可知消息發(fā)送成功:

4.2.4. 支持領域事件

系統(tǒng)支持的領域事件包括:

領域事件類型

觸發(fā)機制

tag

消息體

LikeMarkedEvent

點贊成功

LikeMarkedEvent

見 LikeMarkedEvent 類

LikeCancelledEvent

取消點贊成功

LikeCancelledEvent

見 LikeCancelledEvent 類

DislikeMarkedEvent

踩成功

DislikeMarkedEvent

見 DislikeMarkedEvent 類

DislikeCancelledEvent

取消踩成功

DislikeCancelledEvent

見 DislikeCancelledEvent 類

4.3. 緩存加速

在系統(tǒng)中,獲取目標對象的 贊/踩 數(shù)量接口調(diào)用量最大,會成為系統(tǒng)的第一個性能卡點,針對這個問題,可以通過引入 redis 緩存進行性能加速。

4.3.1. 添加 redis 依賴

首先需要引入 redis 相關依賴,在 bootstrap 的 pom 中增加如下配置:

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

然后在 application.yml 中增加 redis 相關配置:

spring:
  redis:
    host: 127.0.0.1
    port: 6379

4.3.2. 開啟緩存

完成redis配置后,需要在 application.yml 開啟對應的緩存,具體如下:

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

4.3.3. 緩存效果

未開啟緩存前,每次查詢數(shù)量都會執(zhí)行一條 sql,具體如下:curl 命令如下:

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

輸出 sql 如下:

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 (?))

開啟緩存后,再次執(zhí)行以上 curl,控制臺不會輸出sql,而是會輸出一行日志:

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

說明緩存已經(jīng)生效。

所有的 action 操作都會與同步的對緩存進行更新。

4.4. 異步存儲

當目標對象出現(xiàn)熱點時,會產(chǎn)生高并發(fā)請求,對于 action 來說,主要以數(shù)據(jù)插入和數(shù)據(jù)的分散更新為主。但對于 count,就會產(chǎn)生熱點更新,從而成為系統(tǒng)的瓶頸。在這個場景,最適合的解決方案便是引入 MQ 對流量進行削峰填谷。

4.4.1. 增加 rocketmq

與 4.2.1. 添加 RocketMQ 內(nèi)容一致,在此不再重復。

4.4.2. 開啟異步化

在 application.yml 中增加如下配置:

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 中執(zhí)行 點贊 操作,從控制臺可以看到如下日志:

[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

從日志上看,可以得出:

  • nio 線程向 MQ 發(fā)送消息
  • MessageThread 線程從 MQ 中獲取數(shù)據(jù)并執(zhí)行 incr 操作

4.5. 分庫分表

隨著系統(tǒng)的運行,數(shù)據(jù)量會逐漸增大,最終超出單個 DB 的容量上限。這種情況下,最佳實踐便是對數(shù)據(jù)庫進行分庫分表。

4.5.1. 構建數(shù)據(jù)庫和表

在 infrastructure 模塊的 sql 目錄下存在兩個 sql 文件:

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

示例中總共分16張表,存放在兩個數(shù)據(jù)庫中:

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

如圖所示:

4.5.2. 添加 ShardingSphere 支持

在 bootstrap 的pom 文件增加 ShardingSphere 的依賴,具體如下:

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

其次,增加分庫分表配置文件,為了方便新建 application.properties 存放分庫分表配置:

# 數(shù)據(jù)源配置
# 總共4個數(shù)據(jù)源
spring.shardingsphere.datasource.names=action-ds0, action-ds1, count-ds0, count-ds1 
# action-ds0 數(shù)據(jù)源配置
spring.shardingsphere.datasource.action-ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.action-ds0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.action-ds0.jdbc-url=jdbc:mysql://127.0.0.1:3306/like_action_0?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC
spring.shardingsphere.datasource.action-ds0.username=root
spring.shardingsphere.datasource.action-ds0.password=root
# action-ds1 數(shù)據(jù)源配置
spring.shardingsphere.datasource.action-ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.action-ds1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.action-ds1.jdbc-url=jdbc:mysql://127.0.0.1:3306/like_action_1?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC
spring.shardingsphere.datasource.action-ds1.username=root
spring.shardingsphere.datasource.action-ds1.password=root
# count-ds0 數(shù)據(jù)源配置
spring.shardingsphere.datasource.count-ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.count-ds0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.count-ds0.jdbc-url=jdbc:mysql://127.0.0.1:3306/like_count_0?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC
spring.shardingsphere.datasource.count-ds0.username=root
spring.shardingsphere.datasource.count-ds0.password=root
# count-ds1 數(shù)據(jù)源配置
spring.shardingsphere.datasource.count-ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.count-ds1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.count-ds1.jdbc-url=jdbc:mysql://127.0.0.1:3306/like_count_1?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC
spring.shardingsphere.datasource.count-ds1.username=root
spring.shardingsphere.datasource.count-ds1.password=root
# 分庫分表規(guī)則配置
# 使用雪花算法生成分布式主鍵id的值
spring.shardingsphere.sharding.default-key-generator.column=id
spring.shardingsphere.sharding.default-key-generator.column-type=BIGINT
spring.shardingsphere.sharding.default-key-generator.type=SNOWFLAKE
spring.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
# 根據(jù) 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
# 根據(jù) 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_id
spring.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_id
spring.shardingsphere.sharding.tables.like_action.database-strategy.inline.algorithm-expression=action-ds$->{Math.floorDiv((Math.abs(user_id.hashCode())  % 16) , 8)}
# 計數(shù)表配置
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
# 根據(jù) 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
# 根據(jù) 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_id
spring.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_id
spring.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

在雪花算法情況下,尾數(shù)會變的極度不均勻,所以在進行計算之前,通常先執(zhí)行 hashCode 在進行取模操作。

4.5.3. 分庫分表效果

啟動應用程序,控制臺輸出 sharding 相關配置,具體如下:

defaultKeyGenerator:
  column: id
  type: SNOWFLAKE
tables:
  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 中操作點贊,控制臺輸出如下:

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]

其中:

  • Logic SQL:邏輯 SQL 中的表為 dislike_action
  • Actual SQL:實際執(zhí)行的 SQL 表為 dislike_action_0,數(shù)據(jù)庫為 action-ds0

5. 項目信息

項目地址見:https://gitee.com/litao851025/lego/tree/master/services/like

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2022-06-09 08:01:43

秒殺系統(tǒng)互聯(lián)網(wǎng)架構

2018-08-15 09:02:59

產(chǎn)業(yè)互聯(lián)網(wǎng)工業(yè)互聯(lián)網(wǎng)物聯(lián)網(wǎng)

2015-05-28 16:11:07

互聯(lián)網(wǎng)+

2015-06-24 15:35:54

2015-10-08 15:20:34

互聯(lián)網(wǎng)物聯(lián)網(wǎng)

2020-04-17 14:37:09

大數(shù)據(jù)工業(yè)互聯(lián)網(wǎng)技術

2015-10-30 17:50:18

互聯(lián)網(wǎng)金融

2017-08-03 16:37:35

互聯(lián)網(wǎng)法院司法

2015-09-22 09:17:33

互聯(lián)網(wǎng)發(fā)展史

2014-01-15 14:35:35

云計算

2014-08-12 14:01:19

SDNICNCDN

2019-04-04 15:01:03

2013-01-25 10:31:02

互聯(lián)網(wǎng)公司移動互聯(lián)網(wǎng)船票

2023-07-13 15:26:27

無人機互聯(lián)網(wǎng)

2019-12-11 15:05:27

互聯(lián)網(wǎng)IT云計算

2011-12-19 16:45:22

2016-12-02 15:23:42

銳捷互聯(lián)網(wǎng)技術核心交換機

2016-12-05 13:22:15

互聯(lián)網(wǎng)移動互聯(lián)網(wǎng)物聯(lián)網(wǎng)

2012-06-26 13:18:23

互聯(lián)網(wǎng)公社

2011-08-19 11:33:32

點贊
收藏

51CTO技術棧公眾號