分類
發燒車訊

瑞士國會選舉初步預測 綠黨可望竄升成第4大黨

摘錄自2019年10月21日中央社報導

士國會大選投票20日落幕,初步預測顯示,瑞士人民黨可望拿下25.8%得票率蟬聯第一大黨。

瑞士廣播電視台(SRF)公布民調機構GFS Bern的預測結果,顯示綠黨(Green Party)有望在下議院選舉獲得13%選票,並從上屆選舉第5大黨竄升成為第4大黨。另一小黨綠色自由黨(Green Liberal Party,GLP)得票率則有7.9%。

路透社報導,如果綠黨與綠色自由黨克服政策分歧並決定團結合作,兩黨的得票率將逼近21%,甚至有望在最高行政機關聯邦委員會(Federal Council)7名委員中奪下一席。

根據政治研究機構索托莫研究所(Sotomo),氣候變遷取代移民政策,成為瑞士選民最關心的議題。這是瑞士近代政治史上,最顯著的轉變之一。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

分類
發燒車訊

中國高新汽車國際峰會 – 汽車行業思想領袖的國際峰會

第二屆中國高新汽車國際峰會由法蘭克福展覽(上海)公司和中國國家發展改革委員會國際合作中心聯合主辦,是真正國際化的高端會議,匯聚來自汽車行業的企業高管、中國政府高層官員和海外專家。    高峰會議程中將探討的關鍵主題包括:   ‧
促進中國國有和民營汽車企業的競爭力轉型:朝著真正合作、技術轉讓和全球市場渠道邁進   ‧
合併路線圖:如何盡可能擴大未來汽車行業的商業優勢
  ‧
混合動力機會評估:與電動汽車和輕量化ICE相比較
  ‧
通往電氣化的關鍵步驟:實現電動汽車和電動交通的真正發展
  ‧
汽車智聯技術創新實現新機會

  ‧
具備高增長潛力的未來配件市場機會:盈利發展   ‧
新型汽車市場定位:中西部地區與新興城市
 

數字營銷與社交媒體:OEM廠商和經銷商的最佳實踐
  ‧
有效減排:實現更加高效的商業車隊
  ‧
促進節能以及輕量化ICE的影響
  ‧
通過主動和被動方式,實現前所未有的駕駛者和車輛安全目標   ‧
輕量化實現更加節能、高性能的車型
  ‧
經銷商和分銷商在新維修市場中的新興機會   ‧
汽車融資和保險選項的演化和潛在新方向   ‧
展望未來:個人交通戰略與中國的未來生態城市相匹配   峰會誠邀候選演講嘉賓與主講嘉賓在2013年10月18日星期五之前提交演講提案。 峰會可提供的機會包括:思想領導力演講、企業高管訪談、互動小組討論、科技前沿和贊助活動。歡迎高層企業家參與主題演講,主題與演講機會有限,敬請報名。(請注意,演講提案並非僅限於上述主題,也歡迎您提供更多主題思路。)   提交程序   請在截止日期之前通過電子方式提交。請盡快從峰會官網下載「徵文申請表」,填寫並發回。所提交的所有申請表將由峰會議程組委會加以確認,並在評估階段提供反饋。 網址: http://www.nextgenautosummit-china.com/sc/Call_for_papers.html   Automechanika Shanghai上海汽配展毗鄰舉行 發揮絕佳的協同效應 Automechanika Shanghai上海國際汽車零部件、維修檢測診斷設備及汽車用品展覽會,將於2013年12月10至13日在毗連嘉裡大酒店的上海新國際博覽中心舉行。Automechanika Shanghai由法蘭克福展覽(上海)有限公司及中國汽車工業國際合作總公司聯合主辦,是規模僅次於德國法蘭克福母展的全球第二大Automechanika品牌展覽會,涵蓋汽車零部件、維修與保養、用 品及改裝三大行業板塊,涉及汽車原廠製造及售後市場的各 項產品及服務,整合汽車全產業鏈。預計展商數量超過4,400家,並將迎來8萬名海內外優質買家蒞臨,創歷屆展會之最。   垂詢與聯繫方式:    登記和綜合垂詢: Anna Gu 小姐 電話: +86 21 6160 8569 anna.gu@china.messefrankfurt.com   戰略合作機會: Keiann Yip 小姐 電話: +852 2230 9202 keiann.yip@hongkong.messefrankfurt.com   演講機會、贊助與檯面展示: Charlotte Chan 小姐 電話: +852 2111 3977 charlotte.chan@inspira-events.com    Michael Cherrington 先生 電話: +852 2111 3972 michael.cherrington@inspira-events.com   媒體垂詢: Rachelle Kong 電話: +852 2230 9226 rachelle.kong@hongkong.messefrankfurt.com  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

分類
發燒車訊

一個線上問題的思考:Eureka註冊中心集群如何實現客戶端請求負載及故障轉移?

前言

先拋一個問題給我聰明的讀者,如果你們使用微服務SpringCloud-Netflix進行業務開發,那麼線上註冊中心肯定也是用了集群部署,問題來了:

你了解Eureka註冊中心集群如何實現客戶端請求負載及故障轉移嗎?

可以先思考一分鐘,我希望你能夠帶着問題來閱讀此篇文章,也希望你看完文章後會有所收穫!

背景

前段時間線上Sentry平台報警,多個業務服務在和註冊中心交互時,例如續約註冊表增量拉取等都報了Request execution failed with message : Connection refused 的警告:

緊接着又看到 Request execution succeeded on retry #2 的日誌。

看到這裏,表明我們的服務在嘗試兩次重連后和註冊中心交互正常了。

一切都顯得那麼有驚無險,這裏報Connection refused 是註冊中心網絡抖動導致的,接着觸發了我們服務的重連,重連成功后一切又恢復正常。

這次的報警雖然沒有對我們線上業務造成影響,並且也在第一時間恢復了正常,但作為一個愛思考的小火雞,我很好奇這背後的一系列邏輯:Eureka註冊中心集群如何實現客戶端請求負載及故障轉移?

註冊中心集群負載測試

線上註冊中心是由三台機器組成的集群,都是4c8g的配置,業務端配置註冊中心地址如下(這裏的peer來代替具體的ip地址):

eureka.client.serviceUrl.defaultZone=http://peer1:8080/eureka/,http://peer2:8080/eureka/,http://peer3:8080/eureka/

我們可以寫了一個Demo進行測試:

註冊中心集群負載測試

1、本地通過修改EurekaServer服務的端口號來模擬註冊中心集群部署,分別以87618762兩個端口進行啟動
2、啟動客戶端SeviceA,配置註冊中心地址為:http://localhost:8761/eureka,http://localhost:8762/eureka

3、啟動SeviceA時在發送註冊請求的地方打斷點:AbstractJerseyEurekaHttpClient.register(),如下圖所示:

這裏看到請求註冊中心時,連接的是8761這個端口的服務。

4、更改ServiceA中註冊中心的配置:http://localhost:8762/eureka,http://localhost:8761/eureka
5、重新啟動SeviceA然後查看端口,如下圖所示:

此時看到請求註冊中心是,連接的是8762這個端口的服務。

註冊中心故障轉移測試

以兩個端口分別啟動EurekaServer服務,再啟動一個客戶端ServiceA。啟動成功后,關閉一個8761端口對應的服務,查看此時客戶端是否會自動遷移請求到8762端口對應的服務:

1、以87618762兩個端口號啟動EurekaServer
2、啟動ServiceA,配置註冊中心地址為:http://localhost:8761/eureka,http://localhost:8762/eureka
3、啟動成功后,關閉8761端口的EurekaServer
4、在EurekaClient發送心跳請求的地方打上斷點:AbstractJerseyEurekaHttpClient.sendHeartBeat()
5、查看斷點處數據,第一次請求的EurekaServer8761端口的服務,因為該服務已經關閉,所以返回的responsenull

6、第二次會重新請求8762端口的服務,返回的response為狀態為200,故障轉移成功,如下圖:

思考

通過這兩個測試Demo,我以為EurekaClient每次都會取defaultZone配置的第一個host作為請求EurekaServer的請求的地址,如果該節點故障時,會自動切換配置中的下一個EurekaServer進行重新請求。

那麼疑問來了,EurekaClient每次請求真的是以配置的defaultZone配置的第一個服務節點作為請求的嗎?這似乎也太弱了!!?

EurekaServer集群不就成了偽集群!!?除了客戶端配置的第一個節點,其它註冊中心的節點都只能作為備份和故障轉移來使用!!?

真相是這樣嗎?NO!我們眼見也不一定為實,源碼面前毫無秘密!

翠花,上乾貨!

客戶端請求負載原理

原理圖解

還是先上結論,負載原理如圖所示:

這裡會以EurekaClient端的IP作為隨機的種子,然後隨機打亂serverList,例如我們在商品服務(192.168.10.56)中配置的註冊中心集群地址為:peer1,peer2,peer3,打亂后的地址可能變成peer3,peer2,peer1

用戶服務(192.168.22.31)中配置的註冊中心集群地址為:peer1,peer2,peer3,打亂后的地址可能變成peer2,peer1,peer3

EurekaClient每次請求serverList中的第一個服務,從而達到負載的目的。

代碼實現

我們直接看最底層負載代碼的實現,具體代碼在
com.netflix.discovery.shared.resolver.ResolverUtils.randomize() 中:

這裏面random 是通過我們EurekaClient端的ipv4做為隨機的種子,生成一個重新排序的serverList,也就是對應代碼中的randomList,所以每個EurekaClient獲取到的serverList順序可能不同,在使用過程中,取列表的第一個元素作為serverhost,從而達到負載的目的。

思考

原來代碼是通過EurekaClientIP進行負載的,所以剛才通過DEMO程序結果就能解釋的通了,因為我們做實驗都是用的同一個IP,所以每次都是會訪問同一個Server節點。

既然說到了負載,這裏肯定會有另一個疑問:

通過IP進行的負載均衡,每次請求都會均勻分散到每一個Server節點嗎?

比如第一次訪問Peer1,第二次訪問Peer2,第三次訪問Peer3,第四次繼續訪問Peer1等,循環往複……

我們可以繼續做個試驗,假如我們有10000個EurekaClient節點,3個EurekaServer節點。

Client節點的IP區間為:192.168.0.0 ~ 192.168.255.255,這裏面共覆蓋6w多個ip段,測試代碼如下:

/**
 * 模擬註冊中心集群負載,驗證負載散列算法
 *
 *  @author 一枝花算不算浪漫
 *  @date 2020/6/21 23:36
 */
public class EurekaClusterLoadBalanceTest {

    public static void main(String[] args) {
        testEurekaClusterBalance();
    }

    /**
     * 模擬ip段測試註冊中心負載集群
     */
    private static void testEurekaClusterBalance() {
        int ipLoopSize = 65000;
        String ipFormat = "192.168.%s.%s";
        TreeMap<String, Integer> ipMap = Maps.newTreeMap();
        int netIndex = 0;
        int lastIndex = 0;
        for (int i = 0; i < ipLoopSize; i++) {
            if (lastIndex == 256) {
                netIndex += 1;
                lastIndex = 0;
            }

            String ip = String.format(ipFormat, netIndex, lastIndex);
            randomize(ip, ipMap);
            System.out.println("IP: " + ip);
            lastIndex += 1;
        }

        printIpResult(ipMap, ipLoopSize);
    }

    /**
     * 模擬指定ip地址獲取對應註冊中心負載
     */
    private static void randomize(String eurekaClientIp, TreeMap<String, Integer> ipMap) {
        List<String> eurekaServerUrlList = Lists.newArrayList();
        eurekaServerUrlList.add("http://peer1:8080/eureka/");
        eurekaServerUrlList.add("http://peer2:8080/eureka/");
        eurekaServerUrlList.add("http://peer3:8080/eureka/");

        List<String> randomList = new ArrayList<>(eurekaServerUrlList);
        Random random = new Random(eurekaClientIp.hashCode());
        int last = randomList.size() - 1;
        for (int i = 0; i < last; i++) {
            int pos = random.nextInt(randomList.size() - i);
            if (pos != i) {
                Collections.swap(randomList, i, pos);
            }
        }

        for (String eurekaHost : randomList) {
            int ipCount = ipMap.get(eurekaHost) == null ? 0 : ipMap.get(eurekaHost);
            ipMap.put(eurekaHost, ipCount + 1);
            break;
        }
    }

    private static void printIpResult(TreeMap<String, Integer> ipMap, int totalCount) {
        for (Map.Entry<String, Integer> entry : ipMap.entrySet()) {
            Integer count = entry.getValue();
            BigDecimal rate = new BigDecimal(count).divide(new BigDecimal(totalCount), 2, BigDecimal.ROUND_HALF_UP);
            System.out.println(entry.getKey() + ":" + count + ":" + rate.multiply(new BigDecimal(100)).setScale(0, BigDecimal.ROUND_HALF_UP) + "%");
        }
    }
}

負載測試結果如下:

可以看到第二個機器會有50%的請求,最後一台機器只有17%的請求,負載的情況並不是很均勻,我認為通過IP負載並不是一個好的方案。

還記得我們之前講過Ribbon默認的輪詢算法RoundRobinRule,【一起學源碼-微服務】Ribbon 源碼四:進一步探究Ribbon的IRule和IPing 。

這種算法就是一個很好的散列算法,可以保證每次請求都很均勻,原理如下圖:

故障轉移原理

原理圖解

還是先上結論,如下圖:

我們的serverList按照client端的ip進行重排序后,每次都會請求第一個元素作為和Server端交互的host,如果請求失敗,會嘗試請求serverList列表中的第二個元素繼續請求,這次請求成功后,會將此次請求的host放到全局的一個變量中保存起來,下次client端再次請求 就會直接使用這個host

這裏最多會重試請求兩次。

代碼實現

直接看底層交互的代碼,位置在
com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute() 中:

我們來分析下這個代碼:

  1. 第101行,獲取client上次成功server端的host,如果有值則直接使用這個host
  2. 第105行,getHostCandidates()是獲取client端配置的serverList數據,且通過ip進行重排序的列表
  3. 第114行,candidateHosts.get(endpointIdx++),初始endpointIdx=0,獲取列表中第1個元素作為host請求
  4. 第120行,獲取返回的response結果,如果返回的狀態碼是200,則將此次請求的host設置到全局的delegate變量中
  5. 第133行,執行到這裏說明第120行執行的response返回的狀態碼不是200,也就是執行失敗,將全局變量delegate中的數據清空
  6. 再次循環第一步,此時endpointIdx=1,獲取列表中的第二個元素作為host請求
  7. 依次執行,第100行的循環條件numberOfRetries=3,最多重試2次就會跳出循環

我們還可以第123和129行,這也正是我們業務拋出來的日誌信息,所有的一切都對應上了。

總結

感謝你看到這裏,相信你已經清楚了開頭提問的問題。

上面已經分析完了Eureka集群下Client端請求時負載均衡的選擇以及集群故障時自動重試請求的實現原理。

如果還有不懂的問題,可以添加我的微信或者給我公眾號留言,我會單獨和你討論交流。

本文首發自:一枝花算不算浪漫 公眾號,如若轉載請在文章開頭標明出處,如需開白可直接公眾號回復即可。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

分類
發燒車訊

mysql定時備份任務

簡介

在生產環境上,為了避免數據的丟失,通常情況下都會定時的對數據庫進行備份。而Linux的crontab指令則可以幫助我們實現對數據庫定時進行備份。首先我們來簡單了解crontab指令,如果你會了請跳到下一個內容mysql備份
本文章的mysql數據庫是安裝在docker容器當中,以此為例進行講解。沒有安裝到docker容器當中也可以參照參照。

contab定時任務

使用crontab -e來編寫我們的定時任務。

0 5 * * 1 [command]

前面的5個数字分別代表分、時、日、月、周,後面的 command為你的執行命令。
假如你需要在每天晚上8點整執行定時任務,那麼可以這麼寫

0 8 * * * [command]

擴展:
crontab -l 可以查看自己的定時任務
crontab -r 刪除當前用戶的所有定時任務

mysql備份

快速上手

這裏我的mysql數據庫是docker容器。假如你需要在每天晚上8點整執行定時任務,那麼可以這麼寫。
首先執行命令crontab -e

0 8 * * * docker exec mysql_container mysqldump -uroot -proot_password database_name > /var/backups/mysql/$(date +%Y%m%d_%H%M%S).sql

mysql_container 為你的數據庫容器名
mysqldump 是mysql數據庫導出數據的指令
-u 填寫root賬號
-p 填寫root密碼
database_name 需要備份的數據庫名
/var/backups/mysql/$(date +%Y%m%d_%H%M%S).sql 備份文件,後面是文件名的格式

如果你沒什麼要求,單純的只是想要備份,那麼上面那個命令就可以幫你進行定時備份。

小坑: mysql備份的時候我使用了docker exec -it mysqldump ... 這樣的命令去做bash腳本,因為-i參數是有互動的意思,導致在crontab中執行定時任務的時候,沒有輸出數據到sql文件當中。所以使用crontab定時的對docker容器進行備份命令的時候不要添加-i參數。

crontab優化

我不建議直接在crontab -e裏面寫要執行的命令,任務多了就把這個文件寫的亂七八招了。
建議把數據庫備份的命令寫成一個bash腳本。在crontab這裏調用就好了
如:建立一個/var/backups/mysql/mysqldump.sh文件,內容如下

docker exec mysql_container mysqldump -uroot -pmypassword database_name > /var/backups/mysql/$(date +%Y%m%d_%H%M%S).sql

然後把文件改為當前用戶可執行的:

chmod 711 /var/backups/mysql/mysqldump.sh

執行crontab -e 命令修改成如下:

0 20 * * * /var/backups/mysql/mysqldump.sh

那麼這樣就比較規範了。

mysql備份優化

因為sql文件比較大,所以一般情況下都會對sql文件進行壓縮,不然的話磁盤佔用就太大了。
假設你做了上面這一步 crontab優化,我們可以把mysqldump.sh腳本改成下面這樣:

export mysqldump_date=$(date +%Y%m%d_%H%M%S) && \
docker exec mysql_container mysqldump -uroot -pmypassword database_name> /var/backups/mysql/$mysqldump_date.sql && \
gzip /var/backups/mysql/$mysqldump_date.sql
find /var/backups/mysql/ -name "*.sql" -mtime +15 -exec rm -f {} \;

export 在系統中自定義了個變量mysqldump_date,給備份和壓縮命令使用
gzip 為壓縮命令,默認壓縮了之後會把源文件刪除,壓縮成.gz文件
find ... 這行命令的意思為,查詢 /var/backups/mysql/目錄下,創建時間15天之前(-mtime +15),文件名後綴為.sql的所有文件 執行刪除命令-exec rm -f {} \;。總的意思就是:mysql的備份文件只保留15天之內的。15天之前的都刪除掉。

數據恢復

若一不小心你執行drop database,穩住,淡定。我們首先要創建數據庫被刪除的數據庫。

>mysql create database database_name;

然後恢復最近備份的數據。恢復備份的命令:

docker exec -i mysql_container mysql -uroot -proot_password database_name < /var/backups/mysql/20200619_120012.sql

雖然恢復了備份文件的數據,但是備份時間點之後的數據我們卻沒有恢復回來。
如:晚上8點進行定時備份,但是卻在晚上9點drop database,那麼晚上8點到晚上9點這一個小時之內的數據卻沒有備份到。這時候就要使用binlog日誌了。

binlog日誌

binlog 是mysql的一個歸檔日誌,記錄的數據修改的邏輯,如:給 ID = 3 的這一行的 money 字段 + 1。
首先登錄mysql后查詢當前有多少個binlog文件:

> mysql show binary logs;
+---------------+-----------+-----------+
| Log_name      | File_size | Encrypted |
+---------------+-----------+-----------+
| binlog.000001 |       729 | No        |
| binlog.000002 |      1749 | No        |
| binlog.000003 |      1087 | No        |
+---------------+-----------+-----------+

查看當前正在寫入的binlog

mysql> show master status\G;

生成新的binlog文件,mysql的後續操作都會寫入到新的binlog文件當中,一般在恢複數據都時候都會先執行這個命令。

mysql> flush logs

查看binlog日誌

mysql> show binlog events in 'binlog.000003';

小知識點:初始化mysql容器時,添加參數--binlog-rows-query-log-events=ON。或者到容器當中修改/etc/mysql/my.cnf文件,添加參數binlog_rows_query_log_events=ON,然後重啟mysql容器。這樣可以把原始的SQL添加到binlog文件當中。

恢複數據

拿回上面例子的這段話。

晚上8點進行定時備份,但是卻在晚上9點drop database,那麼晚上8點到晚上9點這一個小時之內的數據卻沒有備份到。。

首先進入到mysql容器后,切換到/var/lib/mysql目錄下,查看binlog文件的創建日期

cd /var/lib/mysql
ls -l
...
-rw-r----- 1 mysql mysql      729 Jun 19 15:54  binlog.000001
-rw-r----- 1 mysql mysql     1749 Jun 19 18:45  binlog.000002
-rw-r----- 1 mysql mysql     1087 Jun 19 20:58  binlog.000003
...

從文件日期可以看出:當天時間為2020-06-21,binlog.000002文件的最後更新時間是 18:45 分,那麼晚上8點的備份肯定包含了binlog.000002的數據;
binlog.000003的最後更新日期為 20:58 分,那麼我們需要恢復的數據 = 晚上8點的全量備份 + binlog.000003的 20:00 – 執行drop database命令時間前的數據。

恢復命令格式:

mysqlbinlog [options] file | mysql -uroot -proot_password database_name

mysqlbinlog常用參數:

–start-datetime 開始時間,格式 2020-06-19 18:00:00
–stop-datetime 結束時間,格式同上
–start-positon 開始位置,(需要查看binlog文件)
–stop-position 結束位置,同上

恢復備份數據和binlog數據前建議先登錄mysql后執行flush logs生成新的binlog日誌,這樣可以專註需要恢複數據的binlog文件。
首先我們需要查看binlog日誌,在哪個位置進行了drop database操作:

mysql> show binlog events in 'binlog.000003';
+---------------+-----+----------------+-----------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------+
| Log_name      | Pos | Event_type     | Server_id | End_log_pos | Info                                                                                                                                        |
+---------------+-----+----------------+-----------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------+
| binlog.000003 |   4 | Format_desc    |         1 |         125 | Server ver: 8.0.20, Binlog ver: 4                                                                                                           |
| binlog.000003 | 125 | Previous_gtids |         1 |         156 |                                                                                                                                             |
| binlog.000003 | 156 | Anonymous_Gtid |         1 |         235 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                                                                        |
| binlog.000003 | 235 | Query          |         1 |         318 | BEGIN                                                                                                                                       |
| binlog.000003 | 318 | Rows_query     |         1 |         479 | # INSERT INTO `product_category` SET `name` = '床上用品' , `create_time` = 1592707634 , `update_time` = 1592707634 , `lock_version` = 0      |
| binlog.000003 | 479 | Table_map      |         1 |         559 | table_id: 139 (hotel_server.product_category)                                                                                               |
| binlog.000003 | 559 | Write_rows     |         1 |         629 | table_id: 139 flags: STMT_END_F                                                                                                             |
| binlog.000003 | 629 | Xid            |         1 |         660 | COMMIT /* xid=2021 */                                                                                                                       |
| binlog.000004 | 660 | Anonymous_Gtid |         1 |         739 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                                                                        |
| binlog.000004 | 739 | Query          |         1 |         822 | drop database hotel_server /* xid=26 */                                                                                                     |
+---------------+-----+----------------+-----------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------+

根據上面的日誌,我們可以看到,在End_log_pos = 822 的位置執行了drop database操作,那麼使用binlog恢復的範圍就在2020-06-19 20:00:00 – 660 的位置。為什麼是660?因為drop database的上一個事務的提交是660的位置,命令如下:

mysqlbinlog --start-datetime=2020-06-19 20:00:00 --stop-position=660 /var/lib/mysql/binlog.000003 | mysql -uroot -proot_password datbase_name

如果你的範圍包括了822的位置,那麼就會幫你執行drop database命令了。不信你試試?
執行完上面的命令,你的數據就會恢復到drop database前啦!開不開心,激不激動!

總結

因為mysql定時備份是在生產環境上必須的任務。是很常用的。所以我就迫不及待的寫博客。當然也很感謝我同事的幫助。這篇文章已經寫了三天了,因為我也是在不斷地試錯,不斷的更新文章。避免把錯誤的知識點寫出來。如果幫到你了,關注我一波唄!謝謝。

個人博客網址: https://colablog.cn/

如果我的文章幫助到您,可以關注我的微信公眾號,第一時間分享文章給您

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

分類
發燒車訊

美國迪士尼致力環保 將停用一次用塑膠吸管

摘錄自2018年7月27日蘋果日報美國報導

美國娛樂巨頭華特迪士尼公司( Walt Disney Company)昨天(26日)宣示,明年中期以前,迪士尼樂園等將停止使用一次性塑膠吸管。鑑於塑料垃圾造成的海洋污染日益嚴重,為保護地球環境,歐美正在推廣相同的措施。

迪士尼指出,此舉將可每年減少1.75億根以上的吸管、1.3億根攪拌棒,強調本次嘗試是迪士尼履行環保責任的一環。

共同社則報導,據與迪士尼方面簽訂許可協議的東方樂園公司稱,由於位於千葉縣浦安市的東京迪士尼度假區,運營母體不同,因此不受此次華特迪士尼公司決定的影響。然而該公司也指,「正在研究減少塑料廢棄物」。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

分類
發燒車訊

日政府看好燃料電池車 加碼補助研發

環保意識抬頭,豐田汽車(Toyota Motor)的油電混合車Prius搖身一變成了全球暢銷車款。日本當局看好這股綠色趨勢,計畫投資新一代節能車,讓該國未來一、二十年能穩坐車壇霸主地位。

華爾街日報26 日報導,日本政府擬斥資研發燃料電池車,這種汽車靠氫燃料發動,只排放水蒸汽,不會造成空氣汙染。該國政府24 日宣布,2014 年4 月起的會計年度,將撥款72 億日圓,補助建造氫燃料站;同時也將挹注64 億日圓研發如何降低燃料電池的製造成本。

此外,當局任命東芝(Toshiba)、東京瓦斯(Tokyo Gas)等企業和學界專家共組委員會,草擬計畫,要在2030 年前協助燃料電池科技獲得採用。政府也希望運用水力、風力、地熱、太陽能發電,從水中製造氫氣,不要再從煤炭、石油、天然氣中提煉。

豐田和本田汽車(Honda)先前宣布,計畫在2015 年推出燃料電池車。不過南韓現代汽車(Hyundai Motor)搶先一步,11 月表示氫燃料電池車Tucson SUV 將於明(2014)年上市。

環保車市火熱,豐田和特斯拉(Tesla Motors)曾隔空交火。華爾街日報報導,Toyota 董事長內山田武2013 年9 月30 日受訪指出,Toyota 之所以並未推出任何一款重量級純電動車,是因為該公司不認為這種產品會有市場。

十月底報導,執行長Elon Musk 在德國慕尼黑最新開幕的特斯拉展示中心向支持者表示,很多人都說純電動車根本沒有未來,但他認為氫燃料電池才胡扯、簡直是垃圾。Musk 說,燃料電池基本上只是行銷伎倆,氫是危險性頗高的氣體,比較適合用來推動火箭。

原始來源、授權:TechNews—

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

分類
發燒車訊

對象創建與堆

這一節主要介紹對象創建時,在堆中的一些過程。

回憶下,我們之前說的,什麼時候會發生垃圾回收?

除了在一些安全點處也許會發生垃圾回收(只是也許),如果在所需內存不足的情況下,一定會發生垃圾回收。

分配堆空間

首先通過設置參數,把堆空間設置為 20M,其中 新生代 10M,老年代 10M。

參數設置:

-Xms20m -Xmx20m -Xmn10m -XX:+PrintGCDetails

結果為:

Heap
 PSYoungGen      total 9216K, used 1685K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 8192K, 20% used [0x00000007bf600000,0x00000007bf7a5580,0x00000007bfe00000)
  from space 1024K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007c0000000)
  to   space 1024K, 0% used [0x00000007bfe00000,0x00000007bfe00000,0x00000007bff00000)
 ParOldGen       total 10240K, used 0K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
  object space 10240K, 0% used [0x00000007bec00000,0x00000007bec00000,0x00000007bf600000)

創建一個新對象

我們首先創建一個對象,這個對象佔用 2M 的空間。

package heap;

public class CreateObject {
    public static void main(String[] args) {
        byte[] obj1 = new byte[1024 * 1024 * 2];
    }
}

最後的輸出:

Heap
 PSYoungGen      total 9216K, used 3733K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 8192K, 45% used [0x00000007bf600000,0x00000007bf9a5590,0x00000007bfe00000)
  from space 1024K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007c0000000)
  to   space 1024K, 0% used [0x00000007bfe00000,0x00000007bfe00000,0x00000007bff00000)
 ParOldGen       total 10240K, used 0K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
  object space 10240K, 0% used [0x00000007bec00000,0x00000007bec00000,0x00000007bf600000)

可以看到,新生代 被佔用了,老年代佔用為 0K,沒有被使用。

所以,new 的對象先放在 eden 區。

填滿 eden 區

在填滿 eden 區后,會發生什麼呢?因為 survivor 區實在太小了,很難看到。所以,這裏可以藉助 Visual VM,來觀察,更加直觀。

程序如下:

package heap;

public class CreateObject {
    public static void main(String[] args) {
        while(true){
            byte[] bytes = new byte[1024 * 512];
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

重點是看右邊的記錄圖。注意,這裏我們將每次創建對象的大小設置為了 0.5M。

當 Eden 滿的時候,會調用垃圾回收器,調用垃圾回收器后,Eden 出現了低谷,Survivor 出現了一個增長。老年區也出現了一個增長。

當 Eden 滿的時候,如果 Survivor 區有足夠的空間容納存活對象,那麼可以把存活對象放入 Survivor,多的對象放入老年區。

現在,我們把對象的大小調大。設置為 2M,這樣 Survivor 就無法存放下。

可以看到,在經過一次垃圾回收的時候(可以看到GC Time 上有波峰,說明執行了一次垃圾回收),但我們注意到,Survivor 區中並沒有被佔用。說明垃圾回收過程中,直接將存活對象放到了老年代中。

再來聊聊 survivor 區

對象通常在 Eden 區里誕生,如果經過第一次 MInor GC 后仍然存活,並且能夠被 Survivor 容納的話,該對象會被移動到 Survivor 區,並且將其年齡設置為 1 歲。對象在 Survivor 區每熬過一次 Minor GC,年齡就增加 1 歲,當它年齡增大到一定程度(默認是 15 歲),就會被晉陞到老年代。

特殊情況

有些時候,如果用戶創建了大對象,如很長的字符串或者元素很多的數組的時候。這種大對象都佔用大量的內存,像這種大對象,有很大概率是長時間使用的,不然為什麼要創建大對象。

如果大對象朝生夕滅,我們知道在 Java 8 中,新生代默認採用的 標記-複製 算法,那麼對於大對象而言,是非常耗時的。

所以,如果 JVM 設置了一個閾值,那麼當分配的對象大於這個閾值的時候,會直接被分配到老年代。

總結

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

分類
發燒車訊

中國電動車購買補助高於預期 特斯拉股價攀新高

據新浪財經消息,受中國財政部宣布的電動汽車補貼縮減幅度低於市場預期,可望為特斯拉下月起在中國銷售Model S創造良好環境的影響,特斯拉汽車(TSLA)昨(10)日股價漲5.38%至196.56美元的新高。特斯拉方面表示,雖然Model S不在直接補貼範圍內,但希望中國也能考慮給予直接補貼待遇。

據《新華社》報導,中國去(2013)年向電動車消費者每台車補貼約 3.5 至 6 萬元人民幣,而今年與明 (2015) 年補貼金額將分別減少至 5% 與 10%,僅為原先公布補貼縮減幅度的一半。

特斯拉上月宣布的報告指出,去年第 4 季一共售出 6900 輛 Model S 車款,銷售輛季增 25%,也比先前預期高出 20%,也帶動公司股價穩定回升。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

分類
發燒車訊

一對多分頁的SQL到底應該怎麼寫?

1. 前言

MySQL一對多的數據分頁是非常常見的需求,比如我們要查詢商品和商品的圖片信息。但是很多人會在這裏遇到分頁的誤區,得到不正確的結果。今天就來分析並解決這個問題。

2. 問題分析

我們先創建一個簡單商品表和對應的商品圖片關係表,它們之間是一對多的關係:

然後我分別寫入了一些商品和這些商品對應的圖片,通過下面的左連接查詢可以看出它們之間具有明顯的一對多關係:

SELECT P.PRODUCT_ID, P.PROD_NAME, PI.IMAGE_URL
FROM PRODUCT_INFO P
         LEFT JOIN PRODUCT_IMAGE PI
                   ON P.PRODUCT_ID = PI.PRODUCT_ID

按照傳統的思維我們的分頁語句會這麼寫:

    <resultMap id="ProductDTO" type="cn.felord.mybatis.entity.ProductDTO">
        <id property="productId" column="product_id"/>
        <result property="prodName" column="prod_name"/>
        <collection property="imageUrls"  ofType="string">
            <result column="image_url"/>
        </collection>
    </resultMap>

    <select id="page" resultMap="ProductDTO">
        SELECT P.PRODUCT_ID, P.PROD_NAME,PI.IMAGE_URL
        FROM PRODUCT_INFO P
                 LEFT JOIN PRODUCT_IMAGE PI
                           ON P.PRODUCT_ID = PI.PRODUCT_ID
        LIMIT #{current},#{size}
    </select>               

當我按照預想傳入了(0,2)想拿到前兩個產品的數據,結果並不是我期望的:

2020-06-21 23:35:54.515 DEBUG 10980 --- [main] c.f.m.mappers.ProductInfoMapper.page     : ==>  Preparing: SELECT P.PRODUCT_ID, P.PROD_NAME,PI.IMAGE_URL FROM PRODUCT_INFO P LEFT JOIN PRODUCT_IMAGE PI ON P.PRODUCT_ID = PI.PRODUCT_ID limit ?,? 
2020-06-21 23:35:54.541 DEBUG 10980 --- [main] c.f.m.mappers.ProductInfoMapper.page     : ==> Parameters: 0(Long), 2(Long)
2020-06-21 23:35:54.565 DEBUG 10980 --- [main] c.f.m.mappers.ProductInfoMapper.page     : <==      Total: 2
page = [ProductDTO{productId=1, prodName='杯子', imageUrls=[http://asset.felord.cn/cup1.png, http://asset.felord.cn/cup2.png]}]

我期望的兩條數據是杯子和筆記本,但是結果卻只有一條。原來當一對多映射時結果集會按照多的一側進行輸出(期望4條數據,實際上會有7條),而前兩條展示的只會是杯子的數據(如上圖),合併后就只有一條結果了,這樣分頁就對不上了。那麼如何才能達到我們期望的分頁效果呢?

3. 正確的方式

正確的思路是應該先對主表進行分頁,再關聯從表進行查詢。

拋開框架,我們的SQL應該先對產品表進行分頁查詢然後再左關聯圖片表進行查詢:

SELECT P.PRODUCT_ID, P.PROD_NAME, PI.IMAGE_URL
FROM (SELECT PRODUCT_ID, PROD_NAME
      FROM PRODUCT_INFO
      LIMIT #{current},#{size}) P
         LEFT JOIN PRODUCT_IMAGE PI
                   ON P.PRODUCT_ID = PI.PRODUCT_ID

這種寫法的好處就是通用性強一些。但是MyBatis提供了一個相對優雅的路子,思路依然是開頭所說的思路。只不過我們需要改造上面的Mybatis XML配置:

<resultMap id="ProductDTO" type="cn.felord.mybatis.entity.ProductDTO">
    <id property="productId" column="product_id"/>
    <result property="prodName" column="prod_name"/>
     <!-- 利用 collection 標籤提供的 select 特性 和 column   -->
    <collection property="imageUrls" ofType="string" select="selectImagesByProductId" column="product_id"/>
</resultMap>
<!-- 先查詢主表的分頁數據    -->
<select id="page" resultMap="ProductDTO">
    SELECT PRODUCT_ID, PROD_NAME
    FROM PRODUCT_INFO
    LIMIT #{current},#{size}
</select>
<!--根據productId 查詢對應的圖片-->
<select id="selectImagesByProductId" resultType="string">
    SELECT IMAGE_URL
    FROM PRODUCT_IMAGE
    WHERE PRODUCT_ID = #{productId}
</select>

4. 總結

大部分情況下分頁是很容易的,但是一對多還是有一些小小的陷阱的。一旦我們了解了其中的機制,也並不難解決。當然如果你有更好的解決方案可以留言討論,集思廣益。多多關注:碼農小胖哥,獲取更多開發技巧。

關注公眾號:Felordcn 獲取更多資訊

個人博客:https://felord.cn

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

分類
發燒車訊

2014第三屆混合動力汽車技術高峰會議

展會主題:
時間:2014年06月26日 至 2014年06月27日
地點:Sheraton Shanghai Hongqiao Hotel
主辦單位:Merisis Consulting

會議背景介紹:

在中國日益嚴重的環境污染壓力和“霧霾”陰影籠罩下,混合動力及純電動汽車的發展形成了勢在必行的趨勢。即使《節能與新能源汽車產業發展規劃》以及四部委聯合發佈的《關於繼續開展新能源汽車推廣應用工作的通知》中明確了純電動以及插電式混合動力汽車的補貼政策,第二批新能源汽車試點運行城市也出臺在即,但新能源汽車產業的前景仍然未能明朗化,標準不統一,基礎建設不健全,電池技術受到局限的電動車以及補貼政策不明確的混合動力汽車都面臨各自發展的瓶頸。在全球並未形成一種成熟應用模式的狀況下,中國應該走出怎樣的一條有自我特色的路線圖。

上海麥瑞賽公司舉辦的混合動力技術峰會將在2014年走入第三個年頭,今年的活動將以“技術驅動混合動力汽車市場化”為主題,探討更多整車廠以及關鍵零部件廠商們共同關注的電池、動力總成、變速箱等關鍵技術,也會融合更多探索純電動車,燃料電池汽車及混合動力汽車未來政策趨勢,商業模式以及標準推進方面的資訊。

我們希望本次峰會可以幫助更多業界同仁通過會議的一手資訊更好的判斷行業未來走向,並且在交換前沿及最新技術,展示領先產品的同時,汲取海外整車廠以及頂尖廠商的經驗,推動整車廠們對純電動及混合動力汽車的研發和市場化的進展。也説明技術/材料/產品提供商們展示自身最新研發和技術成果,並在此平臺上找到與整車商項目以及需求的契合點,獲得在中國本土市場上更多的推廣機會和品牌知名度。

關鍵議題:

  • 如何降低新能源汽車成本並提高市場接受度
  • 技術轉化成產業化,依靠企業還是政策
  • 未來HEV的補貼政策出臺的大致時間表
  • 不同整車廠在底盤系統及變速箱方面的新技術進展
  • 整車集成 / 電機集成的項目方案和合作資源,找到適合自身的合作夥伴
  • 探討近年鋰電池安全事故頻發,如何增加安全性。其他電池安全評估現狀如何
  • PHEV的現有技術的最新進展
  • 如何像特拉斯一樣從根本上顛覆傳統汽車設計

 

部分已確認演講嘉賓:

孟凡一    秘書長    中國機電產品進出口商會汽車分會
張銅柱    高級工程師    中國汽車技術研究中心
劉彥龍    副秘書長    中國化學與物理電源行業協會
鄧先泉    新能源汽車研究所所長    深圳市五洲龍汽車有限公司
Phil Barker    合動力及電動車輛產品總工程師    蓮花汽車科技工程公司
梁春奇    總工程師    長城汽車研究院  底盤研究院院長
徐嚴冬    總工程師    上海電驅動股份有限公司

欲瞭解更多詳情,請登錄官網:

聯繫方式:

聯繫電話:021-61808505*212
手 機:15900722272
傳 真:021-61808511
郵 件:
聯 系 人:萬小姐
網 址:

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心