ETCD 讀寫性能測試以及和Redis的簡單對比

這是我參與8月更文挑戰的第5天,活動詳情查看:8月更文挑戰web

  • 📢歡迎點贊 :👍 收藏 ⭐留言 📝 若有錯誤敬請指正,賜人玫瑰,手留餘香!
  • 📢本文做者:由webmote 原創,首發於 【掘金】
  • 📢做者格言: 生活在於折騰,當你不折騰生活時,生活就開始折騰你,讓咱們一塊兒加油!💪💪💪

🎏 序言

官方定義:etcd 是一個高度一致的分佈式鍵值存儲,它提供了一種可靠的方式來存儲須要由分佈式系統或機器集羣訪問的數據。它能夠優雅地處理網絡分區期間的領導者選舉,即便在領導者節點中也能夠容忍機器故障。數據庫

ETCD最經常使用的功能就是在配置中心中保存系統配置,而咱們很清楚,配置中心屬於讀多寫少的場景,而且須要配置具備強一致性,所以在這樣的場景下,ETCD在合適不過了。markdown

🎏 01.到底有多慢

官方網站放出的基準測試爲: Benchmarked at 1000s of writes/s per instance,這是什麼鬼啊?網絡

有些業務場景,最須要的是高一致性,在保證高一致性的基礎上,能提高高併發固然是更好的了。固然若是硬上ETCD,其實官方是不建議用在高性能的場景下的。架構

既然在某些特性上,已經天選爲ETCD,那麼咱們就測試下ETCD的讀寫性能吧。併發

虛擬機搭建3節點ETCD 3.3.11,配置爲 4cpu/2GB,編寫測試程序,最簡單方式,使用grpc底層通信,單線程讀、單線程寫。分佈式

代碼以下:ide

EtcdClient etcdClient = new EtcdClient("http://192.168.137.100:2379,...");  

var resp = etcdClient.Put("foo/bar", "barfoo");

WatchRequest request = new WatchRequest()
{
    CreateRequest = new WatchCreateRequest()
    {
        Key = ByteString.CopyFromUtf8("foo/a"),
        RangeEnd = ByteString.CopyFromUtf8("foo/z"),
    }
};
//print在不一樣的線程內執行
etcdClient.Watch(request, print);

Task.Run(() =>
{
    Thread.Sleep(1000);
    Stopwatch sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < 10000; i++)
    {     
        etcdClient.Put($"foo/bar{i}", $"barfoo333-{i}");       
    }
    sw.Stop();
    Console.WriteLine($"100 Key write : {sw.ElapsedMilliseconds} ms");
    Thread.Sleep(10000);
    Console.WriteLine($"100 Key Read : {_ms} ms");
});
private static void print(WatchResponse response)
        {          
           ...    
        }
複製代碼

通過幾回測試,ETCD 3節點的讀寫性能指標出爐啦:高併發

image.png

一口老血噴出,咋這麼慢~oop

通過和高手們溝通,肯定這麼慢的速度並非ETCD的真實表現,應該是在虛擬機器人的硬盤速度太慢致使的,所以須要更改成SSD磁盤才能展現ETCD的真實實力。

🎏 02.更換硬盤爲SSD

複製一個虛擬機,是分分鐘的事情,把其更改成SSD上後,再次測試,結果達到了理想狀態。

image.png

寫的QPS達到了 1333 ,在這個配置下,已經很不錯了。

額外測試了下通知事件,其執行是在不一樣的線程ID內,所以消費端若是有業務,則須要保持事務性不衝突。

另外,ETCD的優點是能夠監控1組Key的變化,

  • 同時監聽一個範圍的key(好比:我能夠監聽key=foo/a ~ foo/z 。這是ETCD一個重要的功能)
  • 消費者消費速率不一樣,不會影響消息的消費。

🎏 03.對比Redis

既然寫到這裏了,也對比下Redis的性能指標,Redis採用Pub/sub方式構建。 畢竟是內存數據庫,讀寫的性能是很是高的。 部分代碼:

var _conn = ConnectionMultiplexer.Connect("192.168.137.101");

var db = _conn.GetDatabase();
var sub = _conn.GetSubscriber();
sub.Subscribe("channel1", (channel, val) =>
{
    _sw.Restart();               
     Console.WriteLine($"{channel}: {val }");

    _sw.Stop();
    _ms += _sw.ElapsedMilliseconds;
});
複製代碼

10000 Key write : 1312 ms;
10000 Key Read : 351 ms

🎏 04. 進擊的Etcd

單線程Etcd寫速度太慢了,所以加大對線程的投入,測試100個線程對Etcd的寫,讀取仍是按照通知方式讀取。

核心代碼以下:

Parallel.ForEach(Enumerable.Range(0, 100), n =>
{
    for (int i = 0; i < 100; i++)
    {
        conn.Put($"foo/a{i}", $"hhhhhhhhhhhhhhhhhhhxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx{i}");
    }
    //Thread.Sleep(1000);
});
複製代碼

總體的性能有了質的飛躍,此次應該比較接近理論值了:

image.png

寫QPS達到了 24570;
讀QPS也提高到: 19267;

對比下官方的BenchMarks,感受仍是不錯的。

image.png

🎏 05. 小結

ETCD應該是能夠應用到業務中了,畢竟咱們的業務併發量並無那麼高,但是這個場景也適合Redis啊,性能不是瓶頸,只是業務上須要作出一致性的保障,既然有DB的託底,應該也不是問題!

因此架構永遠是在折中,各類因素在裏面,並無說必須如何如何!

養成一個好習慣,須要不停的激勵和鼓勵,寫做的能力也許就是不斷的寫中提高的,固然還有自身的額能力,在不斷的輸出過程當中,發現本身的不足以及鞏固本身的知識。

30天不停更,目標很遠大,今天是第五天,加油吧,兄弟們!

例行小結,理性看待!

結的是啥啊,結的是我想你點贊而不可得的寂寞。😳😳😳

👓都看到這了,還在意點個贊嗎?

👓都點讚了,還在意一個收藏嗎?

👓都收藏了,還在意一個評論嗎?

相關文章
相關標籤/搜索