成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

開(kāi)發(fā) 架構(gòu)
贊/踩服務(wù)是一種用戶反饋機(jī)制。隨著社交媒體的普及和發(fā)展,人們?cè)絹?lái)越喜歡在一種平臺(tái)上分享自己的觀點(diǎn)和生活,這時(shí)就需要一種形式化的反饋機(jī)制來(lái)快速評(píng)價(jià)這些信息的好壞。贊/踩服務(wù)的目標(biāo)是為了提高用戶互動(dòng)性,增加內(nèi)容的社會(huì)影響力,從而增加活躍用戶數(shù)量。

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

1. 背景

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

2. 目標(biāo)

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

3. 快速入門(mén)

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

功能

描述

贊/踩

用戶可以點(diǎn)擊對(duì)應(yīng)的贊或踩按鈕,以表達(dá)自己的喜好或不喜好

取消贊/踩

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

計(jì)數(shù)器

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

贊/踩歷史

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

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

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

框架

版本

依賴說(shuō)明

JDK

1.8+

運(yùn)行環(huán)境

Spring Boot

2.3.12.RELEASE


Spring Data

2.3.9.RELEASE

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

Lego

0.1.22

DDD 模型落地

springfox

3.0.0

文檔管理

RocketMQ

2.2.1

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

Sharding Sphere

4.4.1

分庫(kù)分表(可選)

3.2. 模塊介紹

該項(xiàng)目使用標(biāo)準(zhǔn)的 “六邊形架構(gòu)”,對(duì)業(yè)務(wù)和技術(shù)進(jìn)行分離,所以模塊較多,但層次更為清晰。

模塊

作用

domain

核心邏輯層,DDD 中核心組件,包括實(shí)體、值對(duì)象、聚合根、領(lǐng)域服務(wù)等

app

應(yīng)用服務(wù)層,DDD 中的應(yīng)用服務(wù),主要負(fù)責(zé)流程編排

infrastructure

基礎(chǔ)設(shè)施層,主要負(fù)責(zé)與 DB 或其他服務(wù)進(jìn)行通訊

api

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

FeignService

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

FeignClient

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

bootstrap

應(yīng)用啟動(dòng)入口,包括 Spring Boot 入口和所有配置

3.3. 啟動(dòng)項(xiàng)目

3.3.1. 建庫(kù)建表

建表語(yǔ)句在infrastructure/src/main/resources/sql 目標(biāo)下,包括單庫(kù)和分庫(kù)分表配置。單庫(kù)建表語(yǔ)句如下:

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ù)庫(kù)配置

修改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. 啟動(dòng)應(yīng)用程序

直接運(yùn)行 bootstrap 模塊下的 LikeApplication 類,輸入地址:http://127.0.0.1:8080/swagger-ui/

當(dāng)看到如下界面證明程序啟動(dòng)成功:

3.3. 核心 API

核心接口如下:

功能

請(qǐng)求地址

參數(shù)類型

參數(shù)說(shuō)明

返回結(jié)果

cur Demo

點(diǎn)贊

POST /feignService/action/command/like

RequestBody

{"userId": 用戶id, "targetType": 目標(biāo)對(duì)象類型,"targetId": 目標(biāo)對(duì)象 id}

無(wú)

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

取消點(diǎn)贊

POST /feignService/action/command/unlike

RequestBody

{"userId": 用戶id, "targetType": 目標(biāo)對(duì)象類型,"targetId": 目標(biāo)對(duì)象 id}

無(wú)

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

獲取點(diǎn)贊數(shù)量

GET /feignService/targetCount/query/getLikeCountByTarget

RequestParam

type:目標(biāo)類型;ids:目標(biāo)id集合

[{"targetType":目標(biāo)對(duì)象類型,“targetId":目標(biāo)對(duì)象id,"count":點(diǎn)贊數(shù)量}]

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

獲取點(diǎn)贊記錄

GET /feignService/action/query/getLikeByUserAndType

RequestParam

type:目標(biāo)類型;userId:userId

[{"targetType":目標(biāo)對(duì)象類型,“targetId":目標(biāo)對(duì)象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": 目標(biāo)對(duì)象類型,"targetId": 目標(biāo)對(duì)象 id}

無(wú)

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": 目標(biāo)對(duì)象類型,"targetId": 目標(biāo)對(duì)象 id}

無(wú)

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:目標(biāo)類型;ids:目標(biāo)id集合

[{"targetType":目標(biāo)對(duì)象類型,“targetId":目標(biāo)對(duì)象id,"count":點(diǎn)贊數(shù)量}]

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

獲取點(diǎn)贊記錄

GET /feignService/action/query/getDislikeByUserAndType

RequestParam

type:目標(biāo)類型;userId:userId

[{"targetType":目標(biāo)對(duì)象類型,“targetId":目標(biāo)對(duì)象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 上進(jìn)行測(cè)試即可!!!

4. 高級(jí)特性

4.1. 自定義業(yè)務(wù)驗(yàn)證

流程中涉及兩個(gè)重要的概念:

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

在實(shí)際業(yè)務(wù)場(chǎng)景,需要對(duì)這兩個(gè)對(duì)象的有效性進(jìn)行驗(yàn)證,比如:

  • ActionUser

用戶是否存在?

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

是否是黑名單用戶?

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

這些功能擴(kuò)展直接實(shí)現(xiàn)對(duì)應(yīng)的 Loader 即可。

4.1.1. ActionUser 擴(kuò)展

ActionUser 定義如下:

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

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

ActionUserLoader 定義如下:

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

只需實(shí)現(xiàn) ActionUserLoader 并注冊(cè)為 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);
        }
    }
}

當(dāng) userId 為 null 或者 小于 0 時(shí),表明為無(wú)效用戶,將 valid 設(shè)置為 false。

【備注】Bean 必須注冊(cè)為L(zhǎng)oadActionUserByUserId.BEAN_NAME(actionUserLoader),否則框架將無(wú)法識(shí)別。

4.1.2. ActionTarget 擴(kuò)展

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

如果目標(biāo)對(duì)象狀態(tài)存在問(wèn)題,直接將 valid 置為 false 即可。

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

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

按需要實(shí)現(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);
        }
    }
}

該實(shí)現(xiàn)對(duì) type 為 Test 的 Target 進(jìn)行加載。

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

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

4.2.1. 添加 RocketMQ

外部領(lǐng)域事件通過(guò) RocketMQ 向外廣播,需要搭建 RocketMQ 集群并在項(xiàng)目中增加 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. 打開(kāi)領(lǐng)域事件開(kāi)關(guān)

在 application.yml 添加如下配置:

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

開(kāi)啟領(lǐng)域事件,并指定事件發(fā)送的 topic

4.2.3. 測(cè)試領(lǐng)域事件

重新啟動(dòng)項(xiàng)目,當(dāng)控制臺(tái)輸出以下表明配置成功:

Use RocketMQ to Publish Like Event

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

4.2.4. 支持領(lǐng)域事件

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

領(lǐng)域事件類型

觸發(fā)機(jī)制

tag

消息體

LikeMarkedEvent

點(diǎn)贊成功

LikeMarkedEvent

見(jiàn) LikeMarkedEvent 類

LikeCancelledEvent

取消點(diǎn)贊成功

LikeCancelledEvent

見(jiàn) LikeCancelledEvent 類

DislikeMarkedEvent

踩成功

DislikeMarkedEvent

見(jiàn) DislikeMarkedEvent 類

DislikeCancelledEvent

取消踩成功

DislikeCancelledEvent

見(jiàn) DislikeCancelledEvent 類

4.3. 緩存加速

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

4.3.1. 添加 redis 依賴

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

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

然后在 application.yml 中增加 redis 相關(guān)配置:

spring:
  redis:
    host: 127.0.0.1
    port: 6379

4.3.2. 開(kāi)啟緩存

完成redis配置后,需要在 application.yml 開(kāi)啟對(duì)應(yīng)的緩存,具體如下:

target:
  count:
    dislike:
      cache:
        # 是否開(kāi)啟緩存
        enable: true
    like:
      cache:
        # 是否開(kāi)啟緩存
        enable: true

4.3.3. 緩存效果

未開(kāi)啟緩存前,每次查詢數(shù)量都會(huì)執(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 (?))

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

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

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

所有的 action 操作都會(huì)與同步的對(duì)緩存進(jìn)行更新。

4.4. 異步存儲(chǔ)

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

4.4.1. 增加 rocketmq

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

4.4.2. 開(kāi)啟異步化

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

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

4.4.3. 異步效果

重啟應(yīng)用程序,在 swagger 中執(zhí)行 點(diǎn)贊 操作,從控制臺(tái)可以看到如下日志:

[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. 分庫(kù)分表

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

4.5.1. 構(gòu)建數(shù)據(jù)庫(kù)和表

在 infrastructure 模塊的 sql 目錄下存在兩個(gè) sql 文件:

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

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

  • 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>

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

# 數(shù)據(jù)源配置
# 總共4個(gè)數(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
# 分庫(kù)分表規(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 取模,進(jìn)行分表
spring.shardingsphere.sharding.tables.dislike_action.table-strategy.inline.algorithm-expression=dislike_action_$->{Math.abs(user_id.hashCode())  % 16}
# user_id 為分庫(kù)分片鍵
spring.shardingsphere.sharding.tables.dislike_action.database-strategy.inline.sharding-column=user_id
# 根據(jù) user_id 以 16 取模后除8 ,進(jìn)行分庫(kù)
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)}
# 計(jì)數(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 取模,進(jìn)行分表
spring.shardingsphere.sharding.tables.dislike_target_count.table-strategy.inline.algorithm-expression=dislike_target_count_$->{Math.abs(target_id.hashCode())  % 16}
# target_id 為分庫(kù)分片鍵
spring.shardingsphere.sharding.tables.dislike_target_count.database-strategy.inline.sharding-column=target_id
# 根據(jù) target_id 以 16 取模后除8 ,進(jìn)行分庫(kù)
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ù)會(huì)變的極度不均勻,所以在進(jìn)行計(jì)算之前,通常先執(zhí)行 hashCode 在進(jìn)行取模操作。

4.5.3. 分庫(kù)分表效果

啟動(dòng)應(yīng)用程序,控制臺(tái)輸出 sharding 相關(guān)配置,具體如下:

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 中操作點(diǎn)贊,控制臺(tái)輸出如下:

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:實(shí)際執(zhí)行的 SQL 表為 dislike_action_0,數(shù)據(jù)庫(kù)為 action-ds0

5. 項(xiàng)目信息

項(xiàng)目地址見(jiàn):https://gitee.com/litao851025/lego/tree/master/services/like

責(zé)任編輯:武曉燕 來(lái)源: 今日頭條
相關(guān)推薦

2015-06-24 15:35:54

2015-05-28 16:11:07

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

2022-06-09 08:01:43

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

2018-08-15 09:02:59

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

2014-01-15 14:35:35

云計(jì)算

2017-08-03 16:37:35

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

2015-10-08 15:20:34

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

2012-06-26 13:18:23

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

2011-08-19 11:33:32

2015-10-30 17:50:18

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

2014-08-12 14:01:19

SDNICNCDN

2015-09-22 09:17:33

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

2020-04-17 14:37:09

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

2019-04-04 15:01:03

2009-02-20 09:02:42

谷歌互聯(lián)網(wǎng)溫頓·瑟夫

2014-03-19 16:11:04

移動(dòng)互聯(lián)網(wǎng)的顛覆和延伸

2015-03-25 18:31:20

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

2015-12-08 09:04:00

2013-03-08 09:41:06

宜搜移動(dòng)互聯(lián)網(wǎng)洗腦

2023-07-13 15:26:27

無(wú)人機(jī)互聯(lián)網(wǎng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩一区二区黄色片 | 91精品国产高清一区二区三区 | 国产亚洲精品美女久久久久久久久久 | 亚洲高清视频一区二区 | 一区在线观看视频 | 国产精品久久久久久238 | 欧美一级毛片久久99精品蜜桃 | 亚洲国产精品久久人人爱 | 久久久精品综合 | 国产精品免费在线 | 先锋av资源网 | 亚洲视频一区在线观看 | 九九视频在线观看视频6 | 91精品国产91综合久久蜜臀 | pacopacomama在线 | 国产成人亚洲精品 | 国产精品久久久久久模特 | 久久中文免费视频 | 欧美一区二区三区在线看 | 国产精品久久久久久久久免费桃花 | 国产视频h | 精品免费av| 国产三级精品视频 | 亚洲成人精品国产 | 久久久999成人 | 国产成人综合网 | 秋霞在线一区二区 | a欧美 | 亚洲欧美国产毛片在线 | www.亚洲精品| 91精品国产综合久久婷婷香蕉 | 精品96久久久久久中文字幕无 | 国产精品中文在线 | 日韩一区中文字幕 | 国产欧美在线观看 | 国产精品久久久久久久免费观看 | 国产精品久久久久久久免费观看 | 亚洲一区二区免费 | 免费看一区二区三区 | 毛片一级黄色 | 美美女高清毛片视频免费观看 |