後臺開發java 常見工具包 netty、mq 、分佈式鎖等 乾貨~

why搞這麼一個玩意

用過vue-cli的小夥伴會很輕鬆的搭建出一個包含vue骨架的前端開發組件,而後install所須要的模塊,後臺常見springcloud框架也是如此,可是少了所須要的好多模塊,須要引入pom,還要兼容各類版本問題。前端

爲了更快進行開發,搭建了一套適合後臺的腳手架lei,先後端分離,restful風格接口開發,適合二次開發,主要包含如下模塊。

  • 常見cloud模塊 全家桶 註冊中心 熔斷 降級 網關等等
  • 集成常見java集成
  • springboot 集成kafka
  • springboot 集成es 實現全文檢索
  • springboot 初步實現zookeeper註冊發現
  • springboot 集成mongodb
  • springboot 集成redis
  • springboot 集成常見mq
  • 基於netty的websocket拓展 常見基於jsonprotobuf通信拓展、粘包拆包等功能 推送和im即時通信功能實現
  • sso單點登陸
  • 常見功能 限流、 利用aop分佈式鎖的實現、redission分佈式鎖的應用等
  • 基於client模式的分庫+分表核心jar包實現 以及分庫產生的跨庫事物等
  • 單機分佈式事物框架整合 atomikos處理多數據源分佈式事物
  • 還有其餘業務功能待整合 分表以後數據聚合 報表模塊 權限管理 等等

1. 功能清單 [Todo 列表]

  • springboot 集成kafka,zookeeper.redis,mongdb完成,初步實現緩存+全文檢索
  • 基於client 水平分表方案完成 雪花算法生成id
  • 完成分佈式鎖demo,解決重複插入問題
  • 基於netty websocket 長鏈接推送和im完成 消息記錄存儲mongodb
  • 定時任務拆解完成
  • 垂直分表 分庫以及產生的分佈式事物
  • mysql讀寫分離 主庫設置事物 同一Transcational 能夠切數據源完成
  • 權限接口+安全認證
  • 限流+高併發接口設計
  • 無狀態應用水平拓展
  • vue整合 先後端分離
  • nginx負載

2. 項目模塊介紹

  • lei-api 對外暴露接口
  • lei-app web rest接口 zookeeper kafka es等功能demo
  • lei-demo zookeeper kafka es等功能demo 線程池封裝等
  • lei-common 一些公共工具包 aop實現分佈式鎖解決重複插入 單位時間重複請求
  • lei-dao 普通mybatis配置 單庫查詢 mysql查詢
  • lei-eurake 註冊中心
  • lei-framework-istranstation 解決單機分佈式事物 支持同一Transcation 切庫操做 並支持多庫事物
  • lei-framework-notranstation 解決讀寫分離 支持主庫事物 從庫查詢不支持事物
  • lei-gateway 網關係統
  • lei-im 基於netty websocket 長鏈接 推送 im即時通信
  • lei-job 定時任務+kafka消費
  • lei-portal 門戶首頁
  • lei-service 服務邏輯層
  • lei-sso 單點登陸系統

如下一些思路分享

** elasticsearch 常見查詢

1. match match_phrase term
match 全文模糊匹配  分詞 適用於text 例如 i am ding  分詞設置 i  am  ding三個詞 當match時候  i happy 也能搜到  happy world也能搜到


match_phrase 短語匹配 i am happy  分詞成i am happy  當搜索 am happy 搜到 由於短語匹配



term 精確匹配 i am happy  分詞成i am happy  當搜索 am happy 搜不到 由於沒有分詞設置


2.bool 查詢  高級查詢


must / mustnot/filter等太簡單 本身查詢便可
複製代碼

** 基於redission分佈式鎖demo 模擬100線程同時插入

package com.lei.smart;

import com.lei.smart.mapper.UserMapper;
import com.lei.smart.mapper.WebchatSchoolMapper;
import com.lei.smart.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.awt.peer.LabelPeer;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.*;

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class WebchatServiceTests {
    @Autowired
    UserMapper userMapper;

    @Test
    public void contextLoads() {
        Config config = new Config();

        config.useSentinelServers().addSentinelAddress("****,*****,****")
                .setMasterName("mymaster");

//        CountDownLatch countDownLatch =new CountDownLatch(1);
        RedissonClient redissonClient = Redisson.create(config);

        ExecutorService executorService = Executors.newFixedThreadPool(100);
        CyclicBarrier cyclicBarrier = new CyclicBarrier(100);
        for (int i = 0; i < 100; i++) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    try {
//                        cyclicBarrier.
                        log.info(Thread.currentThread().getName() + ">>>>> block");
                        cyclicBarrier.await();
                        log.info(Thread.currentThread().getName() + ">>>>> open");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
//                    log.info("加鎖前");
                    RLock lock = redissonClient.getLock("test10");
//                    log.info("加鎖後");
                    try {
//                        log.info("嘗試獲取到分佈式鎖<<<<<");
                        boolean b = lock.tryLock(500, 2000, TimeUnit.MILLISECONDS);
                        log.info("獲取到分佈式鎖<<<<<{}", b);
                        if (b) {
                            User userSelect = userMapper.selectByPrimaryKey(1l);
                            if (userSelect == null) {
                                log.info(Thread.currentThread().getName() + ">>>>> is null");
                                User user = new User();
                                user.setId(1l);
                                user.setName("dingjainlei");
                                userMapper.insert(user);
                            } else {
                                log.info(Thread.currentThread().getName() + ">>>>> is not null");
                            }
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        lock.unlock();
                        log.info("解鎖");
//                                redissonClient.shutdown();
                    }
                }
            });
        }


    }

}

複製代碼

常規操做

通常是先去數據庫查詢,若是不存在,則進行插入。若是存在,則不進行操做vue

模擬思路

使用CyclicBarrier 100個線程同時等待await=0的時候同時併發請求查詢數據庫id=1存不存在
redission 使用tryLock 嘗試獲取鎖 設置超時 自動釋放鎖時間  防止死鎖 ,保證分佈式環境下 高併發插入重複問題
複製代碼

End

如何啓動

下載到本地以後,在msyql中建立數據庫lei,一次啓動便可java

問題反饋

在使用中有任何問題,歡迎反饋給我,能夠用如下聯繫方式跟我交流mysql

郵件(m13687672481@163.com)nginx

QQ: 1251272104web

微信: kenan13687672481redis

關於做者

下載到本地以後,在msyql中建立數據庫lei,一次啓動便可算法

var author = {spring

nickName  : "工藤新一",
複製代碼

}sql

相關文章
相關標籤/搜索