<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【解決方案】項目重構(gòu)之如何使用 MySQL 替換原來的 MongoDB

      前言

      在筆者 Java 后端開發(fā)的項目經(jīng)歷中,MySQL 和 MongoDB 都有使用過作為后端的數(shù)據(jù)庫來對業(yè)務(wù)數(shù)據(jù)進行持久化,兩者沒有孰優(yōu)孰劣之分,都可以在合適的場景下發(fā)揮出它們的優(yōu)勢。

      今天要分享的是一個項目重構(gòu)過程中如何將數(shù)據(jù)庫選型由原來的 MongoDB 改為 MySQL 的思考,涉及到業(yè)務(wù)當(dāng)前的痛點、選型分析、解決的核心思路,最后會給出簡單的 demo。

      本篇文章側(cè)重在于兩者在表設(shè)計思維上的轉(zhuǎn)換,而業(yè)務(wù)數(shù)據(jù)遷移同步的方案,下一篇文章將給出。


      一、痛點所在

      該項目是一個【PC端管理后臺】+【移動端h5頁面】為主業(yè)務(wù)框架的系統(tǒng),原來的預(yù)期是:在后臺配置好活動所需的參數(shù),h5 既可以放在 app 客戶端打開,也可以作為url 鏈接的形式直接在瀏覽器打開。項目一期的時候,業(yè)務(wù)方認為這樣的運營活動會帶來不少的流量和用戶。但是到后來業(yè)務(wù)重心有所調(diào)整,引流的方式發(fā)生變化,最終導(dǎo)致了項目的一個重構(gòu)。

      主要的原因有以下幾點:

      1. 總體的數(shù)據(jù)量沒有預(yù)想的那么大

        活動參與人數(shù)前期預(yù)估為30w+,經(jīng)歷過2個線上活動后的實際總參與人數(shù)為5w+,客戶端注冊用戶數(shù)為3w+,占全部參與人數(shù)的65%左右,遠不及預(yù)期規(guī)模;

      2. 核心接口的并發(fā)也沒有預(yù)想的高

        h5 端的大約 5-8 個的核心接口在實際線上活動進行的最高 QPS 只達到 200-300 左右,CPU 與 內(nèi)存占用率也未達到設(shè)置的告警線(60%);

      3. MySQL 在硬件資源成本上性價比更高

        以阿里云的 RDS for MySQL 與 云數(shù)據(jù)庫 MongoDB 做對比,都是集群部署 + 8核16GB + 100GB 存儲 + 1年時長的規(guī)格下,前者會比后者便宜7w+RMB;

      4. MySQL 的動態(tài)數(shù)據(jù)源切換方案更成熟

        當(dāng)時后端的項目已經(jīng)被全部要求接入多租戶改造,市面上開源的、成熟的動態(tài)數(shù)據(jù)源切換方案并不多,而完全專門支持 MongoDB 的是少之又少。

      綜合以上幾點原因,完全放棄該項目是沒必要的,但也需要適應(yīng)當(dāng)前業(yè)務(wù)的變化和成本控制,預(yù)計花費30人/天,即 2 個后端開發(fā)在 2-3 周內(nèi)完成對該系統(tǒng)的重構(gòu),接口和前端頁面基本無需調(diào)整。


      二、選型分析

      這里就正式進入技術(shù)部分了,首要對比的是兩者各自的特點以及適用的場景,這對于把握整個項目的走向是至為關(guān)鍵的。

      2.1特點對比

      表2-1
      對比項 MySQL MongoDB
      數(shù)據(jù)模型 關(guān)系型數(shù)據(jù)庫,采用表格(table)的形式存儲數(shù)據(jù),每一行是一條記錄 非關(guān)系型(NoSQL)、文檔型數(shù)據(jù)庫,數(shù)據(jù)以文檔(document)的非結(jié)構(gòu)化形式存儲
      查詢方式 使用標準的 SQL 進行查詢,提供了豐富的查詢條件、連接(join)、排序、分頁等功能 使用基于 JSON 結(jié)構(gòu)特點的的查詢語句,支持大量數(shù)據(jù)的聚合、統(tǒng)計、分析
      事務(wù)支持 支持 ACID 事務(wù),確保在多條操作組成的事務(wù)中數(shù)據(jù)的一致性和可靠性。特別是在InnoDB引擎中,提供了完整的事務(wù)支持 4.0 版本開始引入了多文檔事務(wù)支持,可以保證在一定范圍內(nèi)的讀寫操作具備ACID特性。但對于需要嚴格事務(wù)特性的復(fù)雜業(yè)務(wù)場景不及 MySQL 成熟
      數(shù)據(jù)處理 在處理復(fù)雜查詢和高并發(fā)寫入時,需要依賴索引來優(yōu)化性能,或者通過分區(qū)、分片等手段進行水平擴展 在水平擴展和實時數(shù)據(jù)處理方面優(yōu)勢很大,通過分片(sharding)技術(shù)可以輕松應(yīng)對海量數(shù)據(jù)存儲和高并發(fā)讀寫
      空間占用 由于數(shù)據(jù)結(jié)構(gòu)緊湊,對數(shù)據(jù)的存儲通常更為節(jié)省空間,特別是對于簡單數(shù)據(jù)結(jié)構(gòu)和關(guān)系清晰的數(shù)據(jù)集 由于文檔存儲的靈活性和包含元數(shù)據(jù)等因素,通常占用空間較大
      項目集成 已經(jīng)有成熟的第三方 ORM 框架支持,如:Mybatis、Mybatis Plus、io.mybatis、tk.mybatis等 目前集成在 Spring Boot 項目里的增刪改查都是基于 MongoRepository 和 MongoTemplate 來實現(xiàn)的

      2.2場景對比

      • MySQL
        1. Web 應(yīng)用程序:如常見的 xx 管理后臺、xx 管理系統(tǒng),電商 web 網(wǎng)站,包括一些移動端 h5 的頁面等;
        2. 企業(yè)級應(yīng)用:如常見的客戶關(guān)系管理系統(tǒng)(CRM)、人力資源管理系統(tǒng)(HRM)和供應(yīng)鏈管理系統(tǒng)(SCM)等,MySQL 提供了強大的事務(wù)支持;
        3. 嵌入式開發(fā):需要輕量級數(shù)據(jù)庫的軟件、硬件和設(shè)備,MySQL 可以作為一個嵌入式數(shù)據(jù)庫引擎集成到各種應(yīng)用程序中,提高應(yīng)用程序的可移植性;
        4. 云計算和大數(shù)據(jù):MySQL 在云數(shù)據(jù)庫服務(wù)中被廣泛使用,支持云原生應(yīng)用程序和分布式數(shù)據(jù)處理框架,如 Hadoop 和 Spark 等。
      • MongoDB
        1. 處理實時數(shù)據(jù):非常適合處理移動互聯(lián)網(wǎng)應(yīng)用常見的大部分場景,如用戶活動、社交互動、在線購物等;
        2. 內(nèi)容管理系統(tǒng)(CMS):用于處理文章、稿件、評論、圖片、視頻等富媒體內(nèi)容的存儲和增刪改查,支持全文搜索和實時更新;
        3. 數(shù)據(jù)聚合倉庫:存儲原始或半處理的業(yè)務(wù)數(shù)據(jù),利用聚合框架進行實時數(shù)據(jù)聚合、統(tǒng)計分析和數(shù)據(jù)可視化;
        4. 游戲數(shù)據(jù)管理:存儲玩家賬戶信息、游戲進度、成就、虛擬物品、社交關(guān)系等,快速計算和更新游戲排行榜數(shù)據(jù),支持實時查詢等。

      三、核心思路

      我們知道,在 MongoDB 中,一條數(shù)據(jù)的記錄(文檔)格式是 json 的 格式,即強調(diào) key-value 的關(guān)系。

      表2-2

      對于一個 MongoDB 的文檔來說,里面可以包含很多這個集合的屬性,就像一篇文章里面有很多章節(jié)一樣。

      以下面這個圖2-1為例子,activity 是一個完整的集合,里面包含了很多屬性,id、name、status等基本屬性,還有 button 和 share 等額外屬性,這些屬性共同構(gòu)成了這個集合。

      但這樣的結(jié)構(gòu)在 MySQL 里是不能實現(xiàn)的,理由很簡單,MySQL 強調(diào)關(guān)系,1:1 和 1:N 是十分常見的關(guān)系。可以看到,下面將基本屬性放在 activity 作為主表,而其它額外屬性分別放在了 button 表和 share 表里,同時將主表的主鍵 id 作為了關(guān)聯(lián)表的 ac_id 外鍵。

      圖2-1

      那要怎么替換才能實現(xiàn)呢?MongoDB 改成 MySQL 的核心在于:原有的集合關(guān)系以及嵌套關(guān)系,需要拆表成1 : N 的范式關(guān)系,用主鍵-外鍵的方式做關(guān)聯(lián)查詢,同時避免 join 連接查詢。


      四、demo 示例

      下面首先分別給出實際的表設(shè)計與實體映射,包括 MongoDB 和 MySQL 的,然后再通過簡單的查詢代碼來體現(xiàn)兩者的區(qū)別。

      4.1實體映射

      4.1.1MongoDB 實體
      @EqualsAndHashCode(callSuper = true)
      @Data
      public class Activity extends BaseEntity {
          @Id
          private String id;
          private String name;
          private ActivityStatusEnum status;
          private ReviewStatusEnum review;
          private ActivityTypeEnum type;
          private ActivityButton button;
          private ActivityShare share;
      }
      
      4.1.2MySQL 實體
      @Data
      public class Activity extends BaseEntity {
          @Id
          private Integer id;
          private String name;
          private Integer status;
          private Integer review;
          private Integer type;
      }
      
      @Data
      public class ActivityButton extends BaseEntity {
          @Id
          private Integer id;
          private Integer acId;
          private String signUp;
          private Integer status;
          private String desc;
      }
      
      @Data
      public class ActivityShare extends BaseEntity {
          @Id
          private String id;
          private Integer acId;
          private String title;
          private String iconUrl;
      }
      

      4.2查詢代碼

      下面就根據(jù)主鍵 id 和狀態(tài)這兩個條件進行活動詳情的查詢。

      4.2.1MongoDB 查詢
          /**
           * @apiNote 通過主鍵id和活動狀態(tài)查詢活動
           * @param id 主鍵id
           * @return 實體
           */
          @Override
          public Avtivity getDetailById(String id) {
              return this.repository.findById(id)
                      .filter(val -> ActivityStatusEnum.ON.equals(val.getStatus()))
                      .orElseThrow(() -> new RuntimeException("該活動不存在!"));
          }
      
      4.2.2MySQL 查詢
          @Resource
          private ActivityShareService activityShareService;
          @Resource
          private ActivityButtonService activityButtonService;
          @Override
          public ActivityVO detail(Integer id) {
              ExampleWrapper<Activity, Serializable> wrapper = this.wrapper();
              wrapper.eq(Activity::getid, id)
                      .eq(Activity::getStatus(), DataStatusEnum.NORMAL.getCode());
              Activity activity = Optional.ofNullable(this.findOne(wrapper.example()))
                  .orElseThrow(() -> new RuntimeException("該活動不存在!"));
              ActivityVO vo = new ActivityVO();
              vo.setName(Optional.ofNullable(activity.getName()).orElse(StringUtils.EMPTY));
              //查兩個關(guān)聯(lián)表
              vo.setShare(this.activityShareService.getShare(activity.getId()));
              vo.setButton(this.activityButtonService.getButton(activity.getId()));
              return vo;
          }
      

      五、文章小結(jié)

      使用 MySQL 替換 MongoDB 的小結(jié)如下:

      1. 做技術(shù)選型時要充分考慮對比兩者的特點以及應(yīng)用場景,選擇最合適的
      2. 如非必要,那么還是繼續(xù)沿用原來的設(shè)計;一旦選擇重構(gòu),那么就要考慮成本
      3. 原有的集合關(guān)系以及嵌套關(guān)系,需要拆表成1 : N 的范式關(guān)系,用主鍵-外鍵的方式做關(guān)聯(lián)

      最后,如有不足和錯誤,還請大家指正?;蛘吣阌衅渌胝f的,也歡迎大家在評論區(qū)交流!

      posted @ 2024-09-02 08:17  CodeBlogMan  閱讀(1054)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 婷婷色香五月综合缴缴情香蕉| 国产极品粉嫩学生一线天| 国产精品无码不卡在线播放| 成在线人永久免费视频播放| 十八岁污网站在线观看| 精品人妻伦九区久久69| 称多县| 国产精品三级国产精品高| 日本欧美大码a在线观看| 人妻日韩人妻中文字幕| 日本免费一区二区三区日本| 一级片免费网站| 免费看黄片一区二区三区| 精品久久久久久无码专区不卡| 国产国产精品人体在线视| 中文字幕亚洲人妻一区| 成人免费A级毛片无码片2022| 亚洲国产精品久久久天堂麻豆宅男 | 女人18片毛片60分钟| 午夜福利国产盗摄久久性| 达州市| 中文字幕国产精品资源| 亚洲AV国产福利精品在现观看| 真实国产熟睡乱子伦视频| 亚洲精品国产av成人网| 亚洲一区二区三区在线| 国产精自产拍久久久久久蜜| 亚洲精品欧美综合二区| 精品人妻中文字幕av| 又大又粗又硬又爽黄毛少妇 | 五月天激情国产综合婷婷婷| 色综合久久综合久鬼色88| 99久久婷婷国产综合精品青草漫画| 在线中文一区字幕对白| 最新国产精品拍自在线观看| 成人免费无遮挡无码黄漫视频| 无码日韩人妻精品久久| 三上悠亚在线精品二区| 成人久久精品国产亚洲av| 26uuu另类亚洲欧美日本| 加勒比无码人妻东京热|