精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

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

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

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

1. 背景

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

2. 目標

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

3. 快速入門

系統所涉及的功能包括:

功能

描述

贊/踩

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

取消贊/踩

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

計數器

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

贊/踩歷史

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

3.1. 開發環境

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

框架

版本

依賴說明

JDK

1.8+

運行環境

Spring Boot

2.3.12.RELEASE


Spring Data

2.3.9.RELEASE

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

Lego

0.1.22

DDD 模型落地

springfox

3.0.0

文檔管理

RocketMQ

2.2.1

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

Sharding Sphere

4.4.1

分庫分表(可選)

3.2. 模塊介紹

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

模塊

作用

domain

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

app

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

infrastructure

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

api

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

FeignService

api 中接口的實際實現者,完成接口的適配

FeignClient

api 中Proxy實現者,方便使用方直接調用

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. 修改數據庫配置

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

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

核心接口如下:

功能

請求地址

參數類型

參數說明

返回結果

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

獲取點贊數量

GET /feignService/targetCount/query/getLikeCountByTarget

RequestParam

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

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

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

獲取踩數量

GET /feignService/targetCount/query/getDislikeCountByType

RequestParam

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

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

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 上進行測試即可!!!

4. 高級特性

4.1. 自定義業務驗證

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

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

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

  • ActionUser

用戶是否存在?

用戶狀態是否有效?

是否是黑名單用戶?

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

這些功能擴展直接實現對應的 Loader 即可。

4.1.1. ActionUser 擴展

ActionUser 定義如下:

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

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

ActionUserLoader 定義如下:

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

只需實現 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;
}

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

由于系統中可以存在多種目標對象,為每個類型提供單獨的 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);
}

按需要實現接口,樣例如下:

@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 進行加載。

4.2. 發布領域事件

領域事件是 DDD 中的重要概念,當系統發生狀態變化后,將變化結果對外進行廣播,從而實現系統間的集成。

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
    #指定領域事件發送的 topic
    topic: like-event-topic

開啟領域事件,并指定事件發送的 topic

4.2.3. 測試領域事件

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

Use RocketMQ to Publish Like Event

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

4.2.4. 支持領域事件

系統支持的領域事件包括:

領域事件類型

觸發機制

tag

消息體

LikeMarkedEvent

點贊成功

LikeMarkedEvent

見 LikeMarkedEvent 類

LikeCancelledEvent

取消點贊成功

LikeCancelledEvent

見 LikeCancelledEvent 類

DislikeMarkedEvent

踩成功

DislikeMarkedEvent

見 DislikeMarkedEvent 類

DislikeCancelledEvent

取消踩成功

DislikeCancelledEvent

見 DislikeCancelledEvent 類

4.3. 緩存加速

在系統中,獲取目標對象的 贊/踩 數量接口調用量最大,會成為系統的第一個性能卡點,針對這個問題,可以通過引入 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. 緩存效果

未開啟緩存前,每次查詢數量都會執行一條 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 (?))

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

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

說明緩存已經生效。

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

4.4. 異步存儲

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

4.4.1. 增加 rocketmq

與 4.2.1. 添加 RocketMQ 內容一致,在此不再重復。

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

[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 發送消息
  • MessageThread 線程從 MQ 中獲取數據并執行 incr 操作

4.5. 分庫分表

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

4.5.1. 構建數據庫和表

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

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

示例中總共分16張表,存放在兩個數據庫中:

  • 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 存放分庫分表配置:

# 數據源配置
# 總共4個數據源
spring.shardingsphere.datasource.names=action-ds0, action-ds1, count-ds0, count-ds1 
# action-ds0 數據源配置
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 數據源配置
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 數據源配置
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 數據源配置
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
# 分庫分表規則配置
# 使用雪花算法生成分布式主鍵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
# 根據 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_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)}
# 計數表配置
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_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

在雪花算法情況下,尾數會變的極度不均勻,所以在進行計算之前,通常先執行 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:實際執行的 SQL 表為 dislike_action_0,數據庫為 action-ds0

5. 項目信息

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

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

2015-06-24 15:35:54

2015-05-28 16:11:07

互聯網+

2022-06-09 08:01:43

秒殺系統互聯網架構

2018-08-15 09:02:59

產業互聯網工業互聯網物聯網

2014-01-15 14:35:35

云計算

2017-08-03 16:37:35

互聯網法院司法

2015-10-08 15:20:34

互聯網物聯網

2011-08-19 11:33:32

2012-06-26 13:18:23

互聯網公社

2014-08-12 14:01:19

SDNICNCDN

2020-04-17 14:37:09

大數據工業互聯網技術

2015-10-30 17:50:18

互聯網金融

2019-04-04 15:01:03

2015-09-22 09:17:33

互聯網發展史

2009-02-20 09:02:42

谷歌互聯網溫頓·瑟夫

2014-03-19 16:11:04

移動互聯網的顛覆和延伸

2015-12-08 09:04:00

2015-03-25 18:31:20

互聯網+

2013-03-08 09:41:06

宜搜移動互聯網洗腦

2023-12-05 15:49:29

點贊
收藏

51CTO技術棧公眾號

国产精品456| 欧美日韩在线二区| 欧美日韩国产精品一区| 久久riav二区三区| 国产三级理论片| 91精品亚洲| 亚洲精品电影网站| 性刺激的欧美三级视频| 色呦呦在线播放| 2021中文字幕一区亚洲| 国产成人精品国内自产拍免费看 | 在线免费观看亚洲| 亚洲第一主播视频| 五月天综合网| 色欲av永久无码精品无码蜜桃| 三级影片在线观看欧美日韩一区二区| 精品国产一区二区三区久久狼5月| 国产伦理在线观看| 久久久人成影片一区二区三区在哪下载| 亚洲人被黑人高潮完整版| 久久精品日产第一区二区三区乱码| 中文字幕一区二区三区人妻四季| 国产综合网站| 色狠狠av一区二区三区香蕉蜜桃| 一级国产黄色片| 欧美成人精品一级| 欧美亚洲综合网| 六月丁香激情网| 欧美色图天堂| 日韩理论片一区二区| 欧美一区二区在线视频观看| 亚洲AV无码精品色毛片浪潮| 久久成人免费电影| 日韩av片永久免费网站| 国产一级特黄aaa大片| 午夜精品毛片| 色诱女教师一区二区三区| 熟女高潮一区二区三区| 久久男人av| 精品国产精品一区二区夜夜嗨 | 国产aⅴ综合色| 成人a在线观看| 凹凸精品一区二区三区| 亚洲欧美高清| 欧美孕妇性xx| 国产日产精品一区二区三区| 亚洲精品乱码| 国内精品久久影院| 久久精品这里有| 欧美视频日韩| 欧美高清在线观看| 九九热精彩视频| 欧美激情麻豆| 欧美人成在线视频| 久久久久黄色片| 欧美亚韩一区| 欧美精品激情视频| 伊人国产在线观看| 一区二区三区四区五区在线| 69av在线视频| 黄色一级视频免费看| 久久一区中文字幕| 国产精品成人品| 真实新婚偷拍xxxxx| 久久综合九色| 国产精品视频不卡| av网站免费大全| 国产成都精品91一区二区三| 国产日产精品一区二区三区四区| 人妻精品一区一区三区蜜桃91| 成人久久久精品乱码一区二区三区| 成人蜜桃视频| 日本韩国欧美国产| 国产99久久久精品| 国产欧美精品在线| 国产精品视频一二区| 狠狠色综合日日| 亚洲自拍小视频| 欧美 日韩 综合| 91丨porny丨首页| 日韩欧美在线电影| 午夜激情视频在线观看| 一区二区在线观看不卡| 3d动漫一区二区三区| 精品123区| 日韩三级免费观看| 一级特级黄色片| 久久综合99| 久久久久久国产精品| 亚洲影院在线播放| 精品一区二区三区香蕉蜜桃| 国产精品入口免费| 国产高清在线| 一区二区三区日本| 乱子伦视频在线看| 日韩视频在线直播| 亚洲欧美综合v| 一区二区成人免费视频| 中文精品在线| 成人xxxxx| 无码国产精品一区二区免费16| 国产精品欧美久久久久一区二区 | 午夜av免费在线观看| 国产欧美日韩在线看| 国产人妻人伦精品| 深夜成人影院| 精品毛片乱码1区2区3区| www.99热| 亚洲福利免费| 成人在线播放av| 毛片在线免费| 亚洲一区二区三区四区五区黄| 一区二区在线播放视频| 丁香婷婷成人| 俺去啦;欧美日韩| www.久久精品视频| 成人午夜视频在线观看| 一区二区精品在线观看| 亚洲伊人av| 精品粉嫩aⅴ一区二区三区四区| 影音先锋男人在线| 亚洲精选在线| www日韩av| 久久日韩视频| 欧美亚洲一区二区在线| 精品一区二区视频在线观看| 亚洲人体av| 国产欧美日韩精品在线观看| 婷婷国产在线| 亚洲超碰精品一区二区| 先锋资源在线视频| 欧美激情777| 国产精品96久久久久久| 日本aaa在线观看| 午夜精品福利视频网站| 一区二区三区四区影院| 国产精品久久久久9999赢消| 国产精品你懂得| 国产一二三区在线视频| 日韩欧美在线字幕| 免费在线观看你懂的| 日韩视频不卡| 国产日韩在线一区二区三区| 七七成人影院| 精品久久99ma| 国产精品suv一区二区69| 国产成人8x视频一区二区| 国产日韩欧美大片| 精品国产18久久久久久二百| 不卡伊人av在线播放| 国产老女人乱淫免费| 国产精品久久久久久妇女6080 | 一区二区三区欧美在线| 国产精品伦一区二区| 综合网中文字幕| 一级黄色片在线观看| 成人欧美一区二区三区小说 | 免费高清一区二区三区| 亚洲精品v亚洲精品v日韩精品| 欧美另类交人妖| 国产综合在线播放| 五月激情六月综合| 欧美大片免费播放器| 美女精品一区| 亚洲巨乳在线观看| 亚洲午夜剧场| 欧美精品久久久久| 日本午夜在线| 欧美亚洲高清一区二区三区不卡| 俄罗斯毛片基地| 精品一区二区精品| 免费cad大片在线观看| 国产色噜噜噜91在线精品| 18性欧美xxxⅹ性满足| 九色视频成人自拍| 欧美日韩精品三区| 91porn在线视频| 99久久精品国产一区| 国产福利一区视频| 亚洲草久电影| 精品国产免费久久久久久尖叫 | 蜜臀av国内免费精品久久久夜夜| 精品成人私密视频| 无码人妻av免费一区二区三区| 国产精品成人一区二区艾草| 久久av一区二区三| 视频精品一区二区| 穿情趣内衣被c到高潮视频| 成人午夜三级| 国产精品久久久久久亚洲调教| 成人欧美在线| 亚洲三级免费看| 99久久国产热无码精品免费| 欧美日韩中文字幕| 久久国产美女视频| 91免费看片在线观看| 国产精欧美一区二区三区白种人| 激情久久五月| 亚洲欧洲一区二区在线观看| 久久精品66| 92国产精品久久久久首页 | 91国内精品野花午夜精品| 91视频综合网| 久久久久免费观看| 丰满少妇xbxb毛片日本| 蜜臀久久99精品久久久久宅男| 日韩国产成人无码av毛片| 精品视频亚洲| 精品久久中出| 日韩一区网站| 国产精品一久久香蕉国产线看观看| 牛牛精品视频在线| 日韩一中文字幕| 免费a级毛片在线观看| 精品精品国产高清a毛片牛牛| 在线观看免费中文字幕| 欧美日韩激情网| 九九在线观看视频| 中文字幕在线播放不卡一区| 亚洲一级中文字幕| 波多野结衣在线一区| 精品人妻一区二区三| 蜜桃久久av一区| 黄色av免费在线播放| 国产亚洲综合精品| 国产资源在线视频| 欧美午夜精品| 国产精品久久久影院| 99久久九九| 日韩中文字幕一区二区| 日韩av黄色在线| 国产精品久久久久久久小唯西川| 成人噜噜噜噜| 成人福利免费观看| 婷婷丁香久久| 成人国产精品久久久久久亚洲| 唐人社导航福利精品| 欧洲亚洲免费在线| 色吧亚洲日本| 热久久免费视频精品| 欧美男人天堂| 欧美有码在线视频| 欧美一区久久久| 日本高清不卡在线| 新片速递亚洲合集欧美合集| 日韩av毛片网| av一区在线| 成人黄色大片在线免费观看| 日韩欧国产精品一区综合无码| 国产精品福利小视频| 影视一区二区三区| 国产精品欧美亚洲777777 | 粉嫩高清一区二区三区精品视频| 精品成人18| 官网99热精品| 欧美a大片欧美片| 欧美精品一区二区视频| 色棕色天天综合网| 午夜精品短视频| 久久久久久久久久久妇女| 亚洲五码在线观看视频| 精品91视频| 大陆极品少妇内射aaaaa| 久久久久久色| 婷婷免费在线观看| 国产乱妇无码大片在线观看| 性欧美18—19sex性高清| 91啪亚洲精品| 妖精视频在线观看免费| 亚洲色图在线看| 久久精品美女视频| 日韩欧美国产网站| 亚洲天堂手机在线| 精品久久一区二区| 九九在线视频| 久久亚洲精品一区二区| av日韩国产| 国产精品久久久久av| 亚洲精品aaa| 国产伦精品一区二区三区高清| 日韩aaa久久蜜桃av| 日日夜夜精品网站| 欧美精品三区| www日韩视频| 国产精品 日产精品 欧美精品| 制服丝袜第一页在线观看| 国产日韩欧美激情| 久草视频免费在线| 日韩欧美在线一区| av资源免费看| 亚洲欧美中文字幕在线一区| 亚洲www色| 国产成人av在线| 亚洲欧美日本国产| 日韩精品欧美专区| 精品白丝av| 在线观看av网页| 不卡一区二区三区四区| 特黄一区二区三区| 精品欧美aⅴ在线网站| 国产精品毛片一区视频播| 亚洲国产精品系列| 国产人成网在线播放va免费| 欧美亚洲国产视频| 日本高清精品| 日韩影片在线播放| 国产亚洲精品自拍| 韩国三级与黑人| 国产精品女同互慰在线看| 国产无套内射又大又猛又粗又爽 | 国产后入清纯学生妹| 亚洲三级av在线| 一个人看的www视频在线免费观看| 91在线观看免费网站| sdde在线播放一区二区| 九色自拍视频在线观看| 国产一区二区三区四| 夫妇交换中文字幕| 日韩欧美精品在线观看| 亚洲精品综合网| 理论片在线不卡免费观看| 日韩一级二级| 欧美性xxxx69| 在线综合亚洲| 国产精品一区二区人妻喷水| 亚洲美女一区二区三区| 一级黄色a视频| 国产一区二区日韩| 国偷自产一区二区免费视频| 国产精品三区在线| 欧美福利一区| 午夜激情影院在线观看| 中文字幕免费观看一区| 久草视频一区二区| 日韩精品中文字幕久久臀| 91www在线| 国产精品视频在线免费观看| 欧美日韩mv| 性高潮免费视频| 亚洲精品国产精华液| 国内精品国产成人国产三级| 久久精品亚洲国产| 国产亚洲字幕| 成人国产一区二区三区| 成人激情免费网站| 国产午夜福利片| 欧美精品一区在线观看| 国产探花在线观看| 国产精品中出一区二区三区| 在线成人www免费观看视频| 美女扒开腿免费视频| 午夜影视日本亚洲欧洲精品| 少妇一级淫片免费看| 久久久综合av| 欧美男人操女人视频| 青青草原av在线播放| 久久精品亚洲麻豆av一区二区| 亚洲天堂男人av| 日韩中文字幕在线免费观看| 成人自拍视频| 成人网站免费观看入口| 91在线观看污| 国产精品第6页| 久久激情视频免费观看| 日韩有吗在线观看| av7777777| 国产精品色在线| 国产成人a人亚洲精品无码| 久久久久久久久久久免费| 欧美性生活一级片| 日本中文字幕高清| 亚洲色图制服丝袜| 日批视频免费播放| 国产福利精品av综合导导航| 欧美激情欧美| 日本wwww色| 日韩欧美在线中文字幕| 精品欧美色视频网站在线观看| 91青青草免费在线看| 午夜在线a亚洲v天堂网2018| 成熟人妻av无码专区| 91精品国产一区二区三区香蕉| yellow在线观看网址| 日本一区二区免费看| 国产精品亚洲一区二区三区在线 | 国产a一区二区| 久久成人国产| 国产稀缺精品盗摄盗拍| 精品999久久久| 九七影院97影院理论片久久| 亚洲精品久久久久久久蜜桃臀| 国产性色一区二区| jizz中国女人| 国产精品电影观看| 影音先锋亚洲电影| 97在线观看视频免费| 精品网站999www| 日韩免费高清视频网站| 熟女少妇精品一区二区| 亚洲午夜精品一区二区三区他趣|