帶你輕鬆了解C# Lock 關鍵字

  相信絕大多數.NET玩家和我一樣,常常使用Timer這個對象,而在WPF中使用DispatcherTimer的人也是很多,DispatcherTimer是在UI線程跑的。我們的程序中大多數都會充斥很多Timer,可以理解它是一個線程,它繼承自 System.Windows.Threading 。

  程序中也許會有一些靜態變量或是單例模式的對象來讓不同的頁面進行交互,但也就是這樣讓每個線程之間打架提供了基礎。因為資源是單獨的,就像是腳踩兩隻船的人,必定會翻車。例如一個List集合,你在一個線程中對它進行了操作,在同步瞬間的另線程中,如果不對它謹慎處理,就會造成 “集合已修改;可能無法執行枚舉操作”。當然我們說的不是關於集合的相關問題,而是關於資源分配的,當然在資源搶奪上,是在耗時的線程中才會出現的,例如下面的這張圖。

 

  這種耗時的操作,並且在同步線程中,沒有對線程進行封裝,很容易造成資源搶奪問題,假如Object是個集合,我在中間把它改了,下一秒的其它線程對它進行臟讀了,就會產生錯誤,我們可以通過Lock關鍵字。

  首先在Microsoft文檔中對Lock的說明是,lock 關鍵字可以用來確保代碼塊完成運行,而不會被其他線程中斷。這是通過在代碼塊運行期間為給定對象獲取互斥鎖來實現的。

  不過我們需要注意的是Lock本質上Monitor.Enter,Monitor.Enter會使值類型裝箱,每次Lock的是裝箱后的對象。Lock其實是類似編譯器的語法糖,因此編譯器直接限制住不能lock值類型,為啥呢,你仔細想想,每次裝箱后都是不同的對象,我怎麼判斷? object.ReferenceEquals 每次都是false…還有就是千萬不要Lock 字符串,簡單來說Lock字符串之後,只要是你以後有字符串匹配和你Lock里的內容有一樣的,那個該字符串也會被鎖定,相當於死鎖了。

  Lock和Monitor的區別不是很大,具體看以下代碼。

private static object obj = new object();
        public void LockSomething()
        {
            lock (obj)
            {
                dosomething();
            }
        }
        public void MonitorSomeThing()
        {
                Monitor.Enter(obj);
                dosomething();
                Monitor.Exit(obj);
        }
        public void dosomething()
        { 
            //做具體的事情
        }

   lock和Monitor是.NET用一個特殊結構實現的,Monitor對象是完全託管的、完全可移植的,並且在操作系統資源要求方面可能更為有效,同步速度較快,但不能跨進程同步。主要作用是鎖定臨界區,使臨界區代碼只能被獲得鎖的線程執行。Monitor.Wait和Monitor.Pulse用於線程同步,類似信號操作,個人感覺使用比較複雜,容易造成死鎖。

  lock就是封裝了Monitor.Enter和Monitor.Exit方法其實非常不難理解,只要確定Lock在啥時候用,該怎麼用就可以了,總結一句話。經常會應用於防止多線程操作導致公用變量值出現不確定的異常,用於確保操作的安全性。

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

【其他文章推薦】

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

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

工作5年,一位來自廣西測試妹子學習《自動化測試》經驗分享

本文來自一位妹子的投稿

大家好,我是黎婷,一位來自廣西南寧的測試妹子,工作5年,藉著原作者平台,今天給大家分享一下近期在學習《自動化測試實戰寶典》一書過程中的一些感想、學習心得,希望對大家有所幫助。

1. 來自大多數測試人員的困惑

在當前整個軟件行業的高速發展中,作為測試人員如何在這個急速浪潮中站穩腳跟,想必大多數人都知道需要學習更多的知識與技能,鞏固並加強自身能力,才能保證自己不被淘汰。

然而目前相當多行業內的測試人員基本都會面臨這種困惑:大體的方向是確定了,但是具體學什麼,怎麼學,落實到地的方案卻比較少有人能想明白。

2. 自己的經歷

想到自己當初在第一家公司離職選擇跳槽的時候,也是帶着這樣的迷茫進入了一家境外電商公司,初入這家公司時,正值質量管理部門大力推廣要求各種自動化測試工具使用的風潮中,基於對KPI的追求,於是開始着手查找當下各種流行的框架工具,為了KPI為了所謂的數據好看使用工具而學習測試工具,前期也是投入較多的時間,成果也是有的,但是很快也就放棄了使用:時間投入高,產出低,還不如手工測試

然而隨着公司業務的快速發展,產品迭代頻繁,重複性的回歸工作慢慢的佔據很大一部分工作時間,加班處理工作已經成了常態,鑒於這種處境,又開始重拾了測試框架與工具,這回的目的很明確:在能保障產品質量的同時也要提高自己的工作效率,這些觀點在最近學習的書上提到關於自動化測試的意義點也是不謀而合的。

因此在這種狀況下開始主動學習工具和框架時,也多了份思考:如何利用這個框架的特點和優勢契合到實際工作的使用,能夠剛好解決工作中的痛點。帶着這個目的去學習工具使用工具,搞起的自動化,成效也是有很明顯的提升,從測試環境的回歸測試效率提升,以及後續線上核心功能的持續監控落地,都給自己實際工作帶來很大的推動促進作用,自己也有更多時間投入到更有價值的專項測試中,而不是疲於日常的重複性工作不得發展。

繼續帶着這份思考,本人最近花了一兩個星期大體研讀了《自動化測試實戰寶典 Robot Framework+Python》一書,基本成功快速地掌握了用Robot Framework工具進行接口自動化測試。

在這次學習的過程中,不僅僅能掌握到技術方面的知識,同時發覺它不只是一本工具書,更是一本有着完整且與時俱進的測試理論體系知識的書籍,書中成熟的思想理論加循序漸進的實戰講解,讓我從一個之前只聞RF名不識其真實面目的RF小白,到現在只通過一兩周時間就能快速掌握RF進行自動化測試。當然,在這麼短的時間內,很難一下子消化完這麼豐富的知識點,在接下來的測試工作學習中,希望能在本書的指引下,更深入學習RF框架來推動自己的工作更高效、高質量的交付。

3. 學習后的幾點心得

接下來想分享自己在學習該書籍過程中的幾點心得:

心得之一:筆者在接口測試項目實戰章節中講到的一個點:

做好接口測試除了在‘術’上融合工程化的最佳實踐,武裝方式方法,在‘道’上更需要有一個正確的認知和決心。正確的認知和決心更加強調的是團隊成員之間的目標是否一致,大家是不是真心認同這件事,而不是被迫地或者礙於領導下達的任務指標才去做。所有流於形式或者並非發自內心而被迫做的事情,最後收效往往都是甚微的,即便給你的是一把‘屠龍刀’,也發揮不出應有的作用。只有大家有意識地從心出發,主動尋求改變、追求質量和高效率、精益求精,再結合合適的工程實踐,才能做到‘道’和‘術’的雙重兼顧。”

對於筆者提到的這個點,跟讀者我的實際工作遇到的情況也是非常契合的

在自己之前的公司中,也多多少少接觸到各種測試工具和框架,在工作之初去學習這類工具框架的時候,與其說初始的目的是為以後長遠的職業發展學習一項或多項技能鞏固能力,更不如說是基於領導的各種任務要求而“心不甘情不願”的去學習,在抱着這種想法去學習的技能,不僅不深入而且成果甚微,更是浪費了很多時間,最後甚至磨滅了繼續學習下去的念頭。

直到工作生涯中後期,才開始有意識自發的通過學習一些工具和技術,來真正地解決實際工作中的問題,在這個過程中領悟到學習的技術知識確切能給自己的工作帶來“收大於支”的成果時,不僅工作能力得到提升,內心也認可了技術帶來的改變,讓“屠龍寶刀”發揮其最大化作用,也真正契合了筆者提到的“道”和術的雙重兼顧

當內心開始認可了這項東西時,會發現學習技術的路上原來如此有趣而引人入勝。利用自己所學,發揮其最大用處,會將自己的學習帶入一個良性的循環中,讓自己不只是在日常工作中得到效益,長遠來講,何嘗不是對將來的職業生涯鋪墊穩固的基石呢。

心得之二:談談學習過程中解決問題發思路。

在學習接口測試實戰項目時,在一些基礎環境配置、導入三方庫、接口認證鑒權等方面都遇到了阻礙。在解決這些問題的過程中,分享下我對於學習過程中遇到問題解決問題的一個思路。

  1. 首先自己在學習一些新技術時,心態都會放得比較平,因為面對新東西新技術,會遇到問題是在所難免的,一帆風順的狀況基本不存在,所以一定要擁有一份积極的心態,而不是遇到問題就開始心煩氣躁,不僅不利於解決問題,還很容易喪失繼續學習下去的信心。
  2. 其次就是解決問題的方法了,這次學習的RF框架,提供了詳細且比較全面的日誌信息,要學會通過具體報錯信息定位問題產生的原因。通過確定問題關鍵字在網絡上各大技術論壇社區平台進行搜索查找,對搜索到的結果也需要學會進行篩選總結,總結出搜索出來的解決方法的規律去解決問題,多次嘗試,不怕試錯,問題在這個階段80%都能得到解決。而不太建議一遇到問題就去找他人協助解決,首先溝通是有成本的,其次也會佔用他人寶貴的時間。
  3. 如果嘗試多次自己解決還是無果,接下來才是找能幫助自己解決問題可能性比較大的小夥伴,因為漫無目的的請教也是浪費雙方時間的行為。有其他小夥伴的協助,也很難有不能解決的問題了。最後解決問題之後的記錄總結也是很重要,作為學習的沉澱,可以在下次遇到同樣問題能快速解決,也可以給後續遇到同樣問題的小夥伴提供幫助。

總的來說,在這次學習RF接口測試中,自己所在部門的小夥伴都很熱心給予了很大的支持幫助,自己也才能在這麼短的時間掌握該項技能。大家能在百忙之中抽出時間給予協助是非常可貴的,作為請教者,在今後的學習中,也要提供給他人力所能及的協助。畢竟,學習是相互的,大家彙集起來的知識泉源才能壯大,也能更好推動大家一起發展。

4. 談一談RF框架可以優化的幾個點

從RF框架本身來談,它的優勢是絕對佔主導的,接下來談一談在使用RF框架中個人覺得還可以優化的幾點:

  1. RIDE編輯器性能有待提高,在加載現有的測試部的接口腳本,左側目錄樹經常出現卡頓,會一定程度影響腳本編寫效率。解決辦法之一可以嘗試用其他編輯器如pycharm等替代。

  2. 希望可以支持通過抓包工具抓取到接口數據進行轉化,自動生成符合腳本編寫格式的關鍵字,可以進一步提高編寫腳本的效率。如httprunner的har2case命令可以很方便的將har文件轉換成對應框架支持的腳本書寫規範。當然對於這塊優化點,也是有解決辦法的:可以通過自己寫工具去轉換抓到的har文件,而目前自己所在團隊也已經有大佬實現拓展了該工具

  3. robot framework 的編輯器RIDE目前對Python3 的兼容性還不是特別好,主要是擴展庫的語法有比較多不兼容。當然RF框架本身一直是支持Python3的,若習慣使用如pycharm這些編輯器來編寫腳本,這塊不足也不存在了。但如果是習慣使用RIDE編輯器的話,對於當前主流使用的Python3維護兼容性成本還是比較高。

總得來說,本次的學習實戰時間還是比較短暫,而本書提供的技術及知識理論是非常豐富的,在接下來的學習中,還需要繼續精讀細讀,慢慢消化,利用好這把“屠龍寶刀”加強自己的“戰鬥值”。

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

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

※教你寫出一流的銷售文案?

面試官:說說Redis的Hash底層 我:……(來自閱文的面試題)

redis源碼分析系列文章

[Redis源碼系列]在Liunx安裝和常見API 

為什麼要從Redis源碼分析 

String底層實現——動態字符串SDS 

Redis的雙向鏈表一文全知道

前言

hello,各位小可愛們,又見面了。今天這篇文章來自去年面試閱文的面試題,結果被虐了。這一part不說了,下次專門開一篇,寫下我面試被虐的名場面,尷尬的不行,全程尬聊。哈哈哈哈,話不多說,開始把。

 

今天要寫Redis的Hash類型,如果有對Redis不熟悉,或者對其他數據類型感興趣的,可以移步上面的系列文章。(最上面的最上面最上面,重要的事情說三遍)

在Redis中Hash類型的應用非常廣泛,其中key到value的映射就通過字典結構來維護的。記筆記,此處要考。

API使用

API的使用比較簡單,所以以下就粗略的寫了。

插入數據hset

使用hset命令往myhash中插入兩個key,value的鍵值對,分別是(name,zhangsan)和(age,20),返回值當前的myhash的長度。

獲取數據hget

使用hget命令獲取myhash中key為name的value值。

獲取所有數據hgetall

使用hgetall命令獲取myhash中所有的key和value值。

獲取所有key

使用hkeys命令獲取myhash中所有的key值。

獲取長度

使用hlen命令獲取myhash的長度。

獲取所有value

使用hvals命令獲取myhash中所有的value值。

具體邏輯圖

hash的底層主要是採用字典dict的結構,整體呈現層層封裝。

首先dict有四個部分組成,分別是dictType(類型,不咋重要),dictht(核心),rehashidx(漸進式hash的標誌),iterators(迭代器),這裏面最重要的就是dictht和rehashidx。

接下來是dictht,其有兩個數組構成,一個是真正的數據存儲位置,還有一個用於hash過程,包括的變量分別是真正的數據table和一些常見變量。

最後數據節點,和上篇說的雙向鏈表一樣,每個節點都有next指針,方便指向下一個節點,這樣目的是為了解決hash碰撞。具體的可以看下圖。

這邊看不懂沒關係,後面會針對每個模塊詳細說明。(千萬不要看到這裏就跳過啦)

雙向鏈表的定義

字典結構體dict

我們先看字典結構體dict,其包括四個部分,重點是dictht[2](真正的數據)和rehashidx(漸進式hash的標誌)。具體圖如下。

具體代碼如下:

//字典結構體 
 typedef struct dict {
    dictType *type;//類型,包括一些自定義函數,這些函數使得key和value能夠存儲 
    void *privdata;//私有數據 
    dictht ht[2];//兩張hash表 
    long rehashidx; //漸進式hash標記,如果為-1,說明沒在進行hash
    unsigned long iterators; //正在迭代的迭代器數量
} dict;

 

數組結構體dictht

dictht主要包括四個部分,1是真正的數據dictEntry類型的數組,裏面存放的是數據節點;2是數組長度size;3是進行hash運算的參數sizemask,這個不咋重要,只要記住等於size-1;4是數據節點數量used,當前有多少個數據節點。

具體代碼如下:

//hash結構體 
typedef struct dictht {
    dictEntry **table;//真正數據的數組 
    unsigned long size;//數組的大小 
    unsigned long sizemask;//用戶將hash映射到table的位置索引,他的值總是等於size-1 
    unsigned long used;//已用節點數量 
} dictht;

 

數據節點dictEntry

dictEntry為真正的數據節點,包括key,value和next節點。

//每個節點的結構體  
typedef struct dictEntry {
    void *key; //key
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
        double d;
    } v;//value
    struct dictEntry *next; //下一個數據節點的地址
} dictEntry;

 

 

 

擴容過程和漸進式Hash圖解

我們先來第一個部分,dictht[2]為什麼會要2個數組存放,真正的數據只要一個數組就夠了?

這其實和Java的HashMap相似,都是數據加鏈表的結構,隨着數據量的增加,hash碰撞發生的就越頻繁,每個數組後面的鏈表就越長,整個鏈表顯得非常累贅。如果業務需要大量查詢操作,因為是鏈表,只能從頭部開始查詢,等一個數組的鏈表全部查詢完才能開始下一個數組,這樣查詢時間將無線拉長。

這無疑是要進行擴容,所以第一個數組存放真正的數據,第二個數組用於擴容用。第一個數組中的節點經過hash運算映射到第二個數組上,然後依次進行。那麼過程中還能對外提供服務嗎?答案是可以的,因為他可以隨時停止,這就到了下一個變量rehashidx。(一點都不生硬的轉場,哈哈哈)

rehashidx其實是一個標誌量,如果為-1說明當前沒有擴容,如果不為-1則表示當前擴容到哪個下標位置,方便下次進行從該下標位置繼續擴容。

這樣說是不是太抽象了,還是一臉懵逼,貼心的送上擴容過程全解,一定要點贊評論多誇誇我哦。(越來越不要臉了。。。)

步驟1

首先是未擴容前,rehashidx為-1,表示未擴容,第一個數組的dictEntry長度為4,一共有5個節點,所以used為5。

步驟2

當發生擴容了,rahashidx為第一個數組的第一個下標位置,即0。擴容之後的大小為大於used*2的2的n次方的最小值,即能包含這些節點*2的2的倍數的最小值。因為當前為5個數據節點,所以used*2=10,擴容后的數組大小為大於10的2的次方的最小值,為16。從第一個數組0下標位置開始,查找第一個元素,找到key為name,value為張三的節點,將其hash過,找到在第二個數組的下標為1的位置,將節點移過去,其實是指針的移動。這邊就簡單說了。

 

步驟3

key為name,value為張三的節點移動結束后,繼續移動第一個數組dictht[0]的下標為0的後續節點,移動步驟和上面相同。

步驟4

繼續移動第一個數組dictht[0]的下標為0的後續節點都移動完了,開始移動下標為1的節點,發現其沒有數據,所以移動下標為2的節點,同時修改rehashidx為2,移動步驟和上面相同。

整個過程的重點在於rehashidx,其為第一個數組正在移動的下標位置,如果當前內存不夠,或者操作系統繁忙,擴容的過程可以隨時停止。

停止之後如果對該對象進行操作,那是什麼樣子的呢?

  • 如果是新增,則直接新增后第二個數組,因為如果新增到第一個數組,以後還是要移過來,沒必要浪費時間
  • 如果是刪除,更新,查詢,則先查找第一個數組,如果沒找到,則再查詢第二個數組。

字典的實現(源碼分析)

創建並初始化字典

首先分配內存,接着調用初始化方法_dictInit,主要是賦值操作,重點看下rehashidx賦值為-1(這驗證了剛才的圖解,-1表示未進行hash擴容),最後返回是否創建成功。

/* 創建並初始化字典 */
dict *dictCreate(dictType *type,
        void *privDataPtr)
{
    dict *d = zmalloc(sizeof(*d));
    _dictInit(d,type,privDataPtr);
    return d;
}

/* Initialize the hash table */
int _dictInit(dict *d, dictType *type,
        void *privDataPtr)
{
    _dictReset(&d->ht[0]);
    _dictReset(&d->ht[1]);
    d->type = type;
    d->privdata = privDataPtr;
    d->rehashidx = -1;//賦值為-1,表示未進行hash
    d->iterators = 0;
    return DICT_OK;
}

 

擴容

dict裏面有一個靜態方法_dictExpandIfNeed,判斷是否需要擴容。

首先判斷通過dictIsRehashing方法,判斷是否處於hash狀態,其調用的是宏常量#define dictIsRehashing(d) ((d)->rehashidx != -1),即判斷rehashidx是否為-1,如果為-1,即不處於hash狀態,if條件為false,可以進行擴容,如果不為-1,即處於hash狀態,if條件為true,不可以進行擴容,直接返回常量DICT_OK。

接着判斷第一個數組的size是否為0,如果為0,則擴容為默認大小4,如果不為0,則執行下面的代碼。

再接着判斷是否需要擴容,if中有三個條件,具體的分析如下。

最後就是調用dictExpand擴容方法了,參數為數據節點的雙倍大小ht[0].used*2。此處驗證了上面擴容過程的數組大小16。

擴容方法比較簡單點,獲取擴容后的大小,將第二個設置新的大小。

這樣講感覺有點空,看下流程圖。

擴容流程圖

具體代碼:

static int _dictExpandIfNeeded(dict *d)
{
    //判斷是否處於擴容狀態中,通過調用宏常量#define dictIsRehashing(d) ((d)->rehashidx != -1)
    //來判斷是否可以擴容
    if (dictIsRehashing(d)) return DICT_OK;

    //判斷第一個數組size是否為0,如果為0,則調用擴容方法,大小為宏常量
    //#define DICT_HT_INITIAL_SIZE     4
    if (d->ht[0].size == 0) return dictExpand(d, DICT_HT_INITIAL_SIZE);

    //下面先列出if條件中所使用到的參數 
    // static int dict_can_resize = 1;數值為1表示可以擴容
    //static unsigned int dict_force_resize_ratio = 5;
    //我們來分析if條件,如果第一個數組的所有節點數量大於等於第一個數組的大小(表示節點數據已經有些多)
    //並且可用擴容(數值為1)或者所有節點數量除以數組大小大於5
    //這個條件表示擴容那個的條件,第一個就是節點必要大於等於數組長度,
    //第二點就再可以擴容和數據太多,超過5兩个中選其一
    if (d->ht[0].used >= d->ht[0].size &&
        (dict_can_resize ||
         d->ht[0].used/d->ht[0].size > dict_force_resize_ratio))
    {
        //調用擴容方法
        return dictExpand(d, d->ht[0].used*2);
    }
    return DICT_OK;
}

int dictExpand(dict *d, unsigned long size)
{
    dictht n;
    //獲取擴容后真正的大小,找到比size大的最小值,且是2的倍數
    unsigned long realsize = _dictNextPower(size);

    //一些判斷條件
    if (dictIsRehashing(d) || d->ht[0].used > size)
        return DICT_ERR;

    if (realsize == d->ht[0].size) return DICT_ERR;

    n.size = realsize;
    n.sizemask = realsize-1;
    n.table = zcalloc(realsize*sizeof(dictEntry*));
    n.used = 0;

    //第一個hash為null,說明在初始化 
    if (d->ht[0].table == NULL) {
        d->ht[0] = n;
        return DICT_OK;
    }
    //正在hash,給第二個hash的長度設置新的, 
    d->ht[1] = n;
    d->rehashidx = 0;//設置當前正在hash 
    return DICT_OK;
}

/* 找到比size大的最小值,且是2的倍數 */
static unsigned long _dictNextPower(unsigned long size)
{
    unsigned long i = DICT_HT_INITIAL_SIZE;

    if (size >= LONG_MAX) return LONG_MAX;
    while(1) {
        if (i >= size)
            return i;
        i *= 2;
    }
}

 

 

漸進式hash

漸進式hash過程已經通過上面圖解說明,以下主要看下代碼是如何實現的,以及過程是不是對的。

擴容之後就是執行dictRehash方法,參數包括待移動的哈希表d和步驟数字n。

首先判斷標誌量rehashidx是否等於-1,如果等於-1,則表示hash完成,如果不等於-1,則執行下面的代碼。

接着進行循環,遍歷第一個數組上的每個下標,每次移動下標位置,都需要更新rehashidx值,每次加1。

再接着進行第二個循環,遍歷下標的鏈表每個節點,完成數據的遷移,主要是指針的移動和一些參數的修改。

最後,返回int數值,如果為0表示整個數據全部hash完成,如果返回1則表示部分hash結束,並沒有全部完成,下次可以通過rehashidx值繼續hash。

具體代碼如下:

//重新hash這個哈希表
 // Redis的哈希表結構公有兩個table數組,t0和t1,平常只使用一個t0,當需要重hash時則重hash到另一個table數組中
 //參數列表
 // 1. d: 待移動的哈希表,結構中存有目前已經重hash到哪個桶了
  //  2. n: N步進行rehash 
// 返回值 返回0說明整個表都重hash完成了,返回1代表未完成
int dictRehash(dict *d, int n) {
    int empty_visits = n*10; 
    //如果當前rehashidx=-1,則返回0,表示hash完成 
    if (!dictIsRehashing(d)) return 0;
    //分n步,而且ht[0]還有沒有移動的節點 
    while(n-- && d->ht[0].used != 0) {
        dictEntry *de, *nextde;
        assert(d->ht[0].size > (unsigned long)d->rehashidx);
        //第一個循環用來更新 rehashidx 的值,因為有些桶為空,所以 rehashidx並非每次都比原來前進一個位置,而是有可能前進幾個位置,但最多不超過 10。
        //將rehashidx移動到ht[0]有節點的下標,也就是table[d->rehashidx]非空
        while(d->ht[0].table[d->rehashidx] == NULL) {
            d->rehashidx++;
            if (--empty_visits == 0) return 1;
        }
        de = d->ht[0].table[d->rehashidx];  //第二個循環用來將ht[0]表中每次找到的非空桶中的鏈表(或者就是單個節點)拷貝到ht[1]中

        /* 利用循環講數據節點移過去 */
        while(de) {
            unsigned int h;

            nextde = de->next;
            /* Get the index in the new hash table */
            h = dictHashKey(d, de->key) & d->ht[1].sizemask;
            de->next = d->ht[1].table[h];
            d->ht[1].table[h] = de;
            d->ht[0].used--;
            d->ht[1].used++;
            de = nextde;
        }
        d->ht[0].table[d->rehashidx] = NULL;
        d->rehashidx++;
    }

    if (d->ht[0].used == 0) {
        zfree(d->ht[0].table);
        d->ht[0] = d->ht[1];
        _dictReset(&d->ht[1]);
        d->rehashidx = -1;
        return 0;
    }

    return 1;
}

總結

該篇主要講了Redis的Hash數據類型的底層實現字典結構Dict,先從Hash的一些API使用,引出字典結構Dict,剖析了其三個主要組成部分,字典結構體Dict,數組結構體Dictht,數據節點結構體DictEntry,進而通過多幅過程圖解釋了擴容過程和rehash過程,最後結合源碼對字典進行描述,如創建過程,擴容過程,漸進式hash過程,中間穿插流程圖講解。

如果覺得寫得還行,麻煩給個贊,您的認可才是我寫作的動力!

如果覺得有說的不對的地方,歡迎評論指出。

好了,拜拜咯。

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

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

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

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

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

看完這三款再考慮買汽油還是新能源車吧?

雷凌的外觀設計要比卡羅拉更顯年輕動感一些,1。2T的發動機最大馬力116匹,峰值扭矩185牛米。國家工信部對於豐田雷凌1。2T的油耗測試結果显示為5。7L/100km,而根據現任車主的反應,綜合油耗也是在6。5-7。0L/100km,比其他車型更具優勢的是,雷凌所使用的1。

基於以上種種的原因還是考慮合資車型,而一款油耗低,售價相對親民的合資轎車肯定更讓人覺得具有吸引力,但就目前來說,還是有不少消費者不太能接受純電動和混合動力車型;本次就推薦幾款油耗低,售價也相對能夠讓人接受的合資家用轎車。

標緻308 230THp

指導價格:10.97-13.37萬

標緻308的外觀更新讓人欣喜,家族式前臉設計更有精神,車身整體線條也更加和諧流暢,採用1.2T的標緻308最大馬力136匹,峰值扭矩230牛米。

工信部油耗显示1.2T的標緻308綜合耗油5.2L/100km左右,根據已經購入標緻308 230THp車型的車主反映,普遍油耗在6.5-7.5L/100km左右,油耗並不顯得太高,基礎排量小為其奠定了根基。

廣汽豐田雷凌1.2T

指導價格:10.98-13.38萬

豐田集團繼混合動力車型推出以後,在雷凌和卡羅拉車型上繼續細分了1.2T的發動機版本以供消費者選擇。雷凌的外觀設計要比卡羅拉更顯年輕動感一些,1.2T的發動機最大馬力116匹,峰值扭矩185牛米。

國家工信部對於豐田雷凌1.2T的油耗測試結果显示為5.7L/100km,而根據現任車主的反應,綜合油耗也是在6.5-7.0L/100km,比其他車型更具優勢的是,雷凌所使用的1.2T是一款4缸發動機,平順性更出色。

一汽大眾高爾夫230TSI

指導價格:14.09-15.79萬

大眾高爾夫是家用車層面銷量非常高的一款緊湊型轎車,市場上曝光率很高,人們對它也非常熟悉,外觀造型顯得大氣簡潔,接受人群的年齡覆蓋面非常廣,230TSI所搭載的1.4T EA211發動機最大馬力131匹,峰值扭矩225牛米。

工信部對高爾夫230TSI車型的油耗測試綜合油耗显示5.9L/100km,根據現任車主普遍的口碑放映,230TSI的自動車型綜合油耗在7.5L/100km左右,高爾夫的優勢在於更符合大眾審美的汽車造型,以及更出色的操控性。

全文總結:以上三款車型都是各自車系中油耗較低的選擇,而標緻308凸顯的是個性,雷凌體現的是平實家用,高爾夫的優點在於紮實的底盤感受以及優良的操控性,基本上可以符合訴求各自不同的消費者。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

離夢想又近了一丟丟 保時泰新款SUV也許下探10萬以內

由於SR9的自重過大,所以它並沒有使用T600的1。5T發動機,這款1。8T發動機預計將會和Z700的那款1。8T發動機型號一致。Z700的1。8T發動機最大馬力為177馬力,最大扭矩為245牛·米,變速箱為5擋手動和6擋雙離合。SR9很可能也會搭載此套動力系統。

保時捷卡宴一直是小編的夢想之車,但是百萬的售價讓太多人望而卻步。不過保時捷嘗到了SUV的甜頭,為了繼續擴大市場,推出了售價更低的Macan,Macan一推出就獲得了巨大的成功,訂單也是絡繹不絕。

雖然Macan更便宜了,但是,作為一個普通的搬磚工(不是香港的搬磚工),Macan還是距離我太遙遠,也許我這類搬磚工一輩子也開不上Macan。

但是只要有需求,必定會有企業來開拓市場,眾泰不負眾望研發出SR9,直接將“Macan”的價格做到了10.88萬。一時間坊間的小夥伴們奔走相告,喜極而泣,終於可以買到心愛的“Macan”了。不過即使是這個價格也有不少消費者覺得貴了。

作為豪車“價格殺手”的眾泰豈能善罷甘休?目前眾泰又打算推出了SR9的1.8T車型,也就是說如果你覺得10.88萬元的價格有點貴,那麼接下來這款車就可以滿足你的心愿了。

現款的SR9全係為2.0T 190馬力發動機,匹配5擋手動和6擋雙離合變速箱,售價區間為10.88-16.18萬元。眾泰為了豐富SR9的動力系統,提供更多樣化的選擇,同時也為了更大程度的降低售價,增強SR9的競爭力,果斷推出1.8T車型。使得SR9的價格進一步下探。

雖然眾泰官方沒有明確的公布1.8T發動機的具體參數,但是可以肯定的是價格更便宜的1.8T的SR9將會在2017年第四季度上市。由於SR9的自重過大,所以它並沒有使用T600的1.5T發動機,這款1.8T發動機預計將會和Z700的那款1.8T發動機型號一致。

Z700的1.8T發動機最大馬力為177馬力,最大扭矩為245牛·米,變速箱為5擋手動和6擋雙離合。SR9很可能也會搭載此套動力系統。

如果真的是這套動力系統的話那也就不用擔心動力輸出不夠了,這要動力系統還是可以可以滿足SR9的日常行車了。

SR9自從誕生之後就備受爭議,但是SR9憑藉著炫酷的外觀,極其豐富的配置和非常實惠的終端售價,吸引了一大批粉絲。況且,1.8T車型問世之後,SR9的起售價很有可能做到9萬左右,這樣會使得SR9的競爭力更上一層樓,銷量肯定會進一步增長。但是SR9也不是沒有對手,比如它們,熱度也很大。

陸風X7

指導價:12.98-14.78萬

X7的車身尺寸為4420*1910*1630mm,軸距為2670mm,定位緊湊型SUV。雖然SR9有“某保”護體,但是X7也有“某虎”助陣,同時X7全係為2.0T發動機,變速箱為8AT,這點也是比較厲害的。而且X7在坊間的名氣也是比較大的。

眾泰T600

指導價:7.98-14.98萬

誰說親兄弟就不能“互相傷害”,大家都是在激烈的市場裏面競爭,誰能取得熱銷就看誰的“活更好了”。T600在10月份交出了11508輛的銷量,表現非常好。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

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

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

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

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

不忽悠直接試!這輛車為什麼讓很多人慾罷不能?

對於在城市裡比較緊張的停車場停車,這就是避免剮蹭的一大保障。不過通過後視攝像頭集成倒車影像在這個價位的車裡不算特別稀奇,新凌派的安全配置才是最大的亮點。全系標配VSA車身穩定控制系統、HSA斜坡起步輔助系統、ESS緊急剎車警示系統及領先搭載LWC盲點显示系統四大安全科技。

又到年底,一年中大家的荷包最豐厚的時節,於是買車成為了不少人的心頭大事。後台關於車型的詢問量也與日俱增,搞得最近黃金右手有點撐不住。正好某天看到有個粉絲問能不能說說凌派,更妙的是恰好咱們手上有輛凌派試駕車,與其用黃金右手碼字說,不如直接上黃金右腳來得直接。於是一不做二不休乾脆勾搭上這位粉絲,帶着他共同試駕新凌派,讓他親自感受一番這車究竟如何!

這一次我們試駕的車型是次頂配,香檳雅金的凌派,這是新凌派的主打車色,路上見到的也多,可見大家對“土豪金”的喜愛。

接着另一位主角登場,正是邀請來試駕的粉絲——阿聰。

外觀——“時尚中不失個性”

阿聰首先感受了一番新凌派的外觀,他直言自己算是個“顏控”。而且相比中規中矩的卡羅拉、雷凌,他更喜歡凌派“時尚中不失個性”的外觀。

覺得,阿聰這個描述很到位。如果把同級車型比成一個班級,凌派就是班級里打扮最前衛,每次出現在教室門口全班同學都會抬頭看的那位。前臉十分特別,“大嘴”前格柵與“大眼睛”一般的大燈組成了獨特的“笑模樣”。側面刀鋒式的雙腰線和切削式的鋁合金輪轂造型充分展現個性,尾部採用運動型保險杠體現動感。可以說新凌派絕對是一輛辨識度非常高的車,恰恰滿足了像阿聰這樣的年輕人不想“泯然眾人已”的心理。

內飾——“簡約而不簡單”

進入車內,空調出風口、中控大屏、各個功能按鍵有序分佈,整體設計是一貫的本田風格,簡潔、實用、時尚。內飾用料也比較精細,手觸摸上去軟硬適中,完全沒有塑料感,相比很多同級車型,新凌派在這個價位做出了質感,這是非常讓人驚喜的地方。

在給阿聰對內飾做了一番講解后,阿聰瞭然的點頭,一句話總結了要表達的意思:“簡約而不簡單。”他想要的也正是這樣內飾布局簡單明了,一坐進去就非常容易上手操作的車。

空間——“夠大夠舒服”

體驗了內飾后,問阿聰對車的空間有些什麼要求。阿聰說主要是平時上下班代步,去運動,周末和朋友短途自駕,所以乘坐空間要夠大夠舒服,後備箱最好能多裝點。聽完就覺得難怪他會偏愛新凌派了。

擁有4664mm的超長車身和2650mm的軸距優勢,加上本田大師水準的空間利用技術,及本田獨有的MM理念的運用,新凌派無論前後排空間都非常寬敞。為了讓阿聰更加深刻的體驗到新凌派的空間,上陣教了他一套“媒體老濕”用的空間測試法。阿聰身高175,坐進新凌派後頭部空間一拳半,腿部空間遠遠超過兩拳,完全能夠舒服的乘坐。

後備箱空間就更能滿足阿聰的需求了。無論深度還是寬度都很夠,放了一摞又一摞物料后,阿聰整個人還能愜意的躺進後備箱,這個展現後備箱寬敞程度的招式,也是服氣。

配置——“亮點滿滿”

當然阿聰更關心的還有凌派的配置。上車之前他就親自體驗了新凌派的無鑰匙進入系統,只要攜帶鑰匙靠近,車門就會自動解鎖。阿聰覺得這個功能非常酷。

而從車內分佈的各個按鍵也能知道配置的豐富程度。尤其一鍵啟停、小綠恭弘=叶 恭弘也深得阿聰這個90后的歡心,既體現高科技,又保證經濟性。

細心的阿聰還發現,新凌派配備的倒車影像具有三模式視角,分別是廣角、常規和高角度。對於在城市裡比較緊張的停車場停車,這就是避免剮蹭的一大保障。

不過通過後視攝像頭集成倒車影像在這個價位的車裡不算特別稀奇,新凌派的安全配置才是最大的亮點。全系標配VSA車身穩定控制系統、HSA斜坡起步輔助系統、ESS緊急剎車警示系統及領先搭載LWC盲點显示系統四大安全科技。而LWC盲點显示系統更是本田的“黑科技”代表之一,在凌派的同級車型中更是絕無僅有。

LWC盲點显示系統使用非常簡單,只要按一下方向盤後方擋把上的啟動按鈕,就能啟動位於右後視鏡上的攝像頭,右後方的影像立即显示在中控大屏上。啟動這個功能后,右後方的視野能從20%擴大到80%,消除肉眼觀察時的盲區,並且帶有輔助線以供駕駛者判斷安全距離。

對這個逆天的功能阿聰表示,開車時右後方經常會有視線盲區,尤其在複雜路況行車時,切線或者轉彎都不免讓很多人的心都提一提,現在只需輕輕看一眼就能掌握右後方路況,開起車來會從容許多。甚至平時還可以來個創意自拍,新凌派的配置不僅豐富,還亮點滿滿。

只想說:果然是年輕人,會玩!

動力——“舒適之餘也談激情”

動力上凌派搭載的是1.8L自然吸氣發動機,擁有本田看家的i-VTEC系統,匹配CVT無級變速器,最大功率100kW,最大扭矩169N·m,參數表現是非常不錯的。而阿聰體驗過後實際是什麼感受呢?

剛把車發動起來,阿聰就感受到凌派強勁的動力了。不同於很多車經常會有起步比較“肉”的感受,本田的可變氣門正時系統讓發動機即使在低扭矩時也能保證足夠的動力輸出。

一天的相處下來,發現阿聰是一個個性又不失內斂的男生,開車風格是“暖男派”,不爭不搶。在市區駕駛時開啟ECON模式是非常適合他的,兼顧舒適性和經濟性。而當他偶爾想要來點激情時,讓他切到S擋,深踩油門感受了一番新凌派的加速,油門與剎車響應都比較靈敏,阿聰開起來完全游刃有餘。

最後還帶着阿聰來了一次劈彎。在比較高速的情況下轉彎,凌派的側傾只會讓你恰到好處的感覺到車身在過彎,並不會有傾斜幅度過大的感覺,車尾的循跡性也不錯。可見新凌派底盤是主打舒適的調校。用阿聰的話來說,新凌派給他的感覺非常“穩”。

最終一天試駕下來的油耗也讓阿聰更“穩”了,他開出了百公里6.8L的超低油耗,看來黃金右腳的稱號要拱手讓人了。

分別前問了阿聰最後一個,也是試駕前阿聰本人帶來的問題:

“今天能不能讓你決定射出這臨門一腳買下凌派呢?”

阿聰回答說:

“本來就覺得新凌派很對胃口,在和一起試駕后,還發現了它獨特的LWC、強勁的動力、超大的空間等超越同級的亮點,可以說由內而外都非常適合我,一天下來我感覺和新凌派幾乎不用磨合,不禁產生一種“這就是我的車”的感覺。”

還是那句話,最適合你的車就是最好的車。像阿聰這樣的年輕人,一輛外觀時尚,配置豐富,大空間,動力足的十萬級別轎車就是最大的助力。而擁有1.5油耗,1.6價格,1.8動力,2.0空間的新凌派,阿聰試完之後已經找不出不買它的理由。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

用路虎給公司女同事一個聖誕驚喜

主角到場,似乎激動得說不出話了,這是要求婚的節奏。顏值擔當:小喬Jacky深情演唱。攝影師:費玉清-如果我是DJ。後期剪輯:子詠運營:苦瓜。帥X主持人:張濤靈魂字幕君:KAM知道你們嫉妒我的顏。我就靜靜的看你們裝逼。祝大家聖誕快樂。

眼看幾年即將結束,為了給公司勞苦功高的女同事一個浪漫的聖誕之夜,TV的小夥伴們精心策劃了一個聖誕party。

有夢想的男人:大宇宙哥

7200干他:Jacky

滿滿一車東西,滿滿的都是驚喜,出發!

我曾經跨過高山大海,現在就經常買買菜。

包裝師:雞爺

悉心裝飾現場。

恩,小喬會不會感動就靠你了。

就等夜晚降臨。

主角到場,似乎激動得說不出話了,這是要求婚的節奏?

顏值擔當:小喬

Jacky深情演唱。

攝影師:費玉清-如果我是DJ。

後期剪輯:子詠

運營:苦瓜。

帥X主持人:張濤

靈魂字幕君:KAM

知道你們嫉妒我的顏。

我就靜靜的看你們裝逼。

祝大家聖誕快樂!

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

【其他文章推薦】

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

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

情報局:大排量發動機都狗帶了,霧霾還會繼續嗎?

未來,奧迪Q8的量產版還可能搭載3。0T V6汽油發動機或4。0T V8柴油發動機,並且會配備奧迪最新的48V電氣系統。(奧迪的設計師不是都跑光了。)中興手機也造車日前,中興通訊通過收購珠海廣通客車,獲得了進入汽車市場的資質以及傳統造車技術。

奔馳E180

日前,有媒體拍攝到了北京奔馳E 180 L的無偽裝實車圖,外觀與在售E級加長保持一致,內飾最大的不同就是採用了傳統机械式指針儀錶盤。

動力方面將搭載一台1.6T發動機,最大功率為115kW,峰值扭矩250牛米,與發動機匹配的是7速手自一體變速箱。預計將於2017年春季上市,將會成為國產全新E級的入門車型,售價也將進一步下探。(或將掀起一股新的扣標潮)

紅旗N501

近日,有媒體曝光一組紅旗全新大型車的路試諜照。據悉,新車將基於紅旗L5的平台進行打造,內部代號為N501,外觀方面。。。與勞斯萊斯古斯特有些相似。

動力將會搭載全新的4.0T V8雙渦輪增壓發動機,還說沒有搭載6.0L V12自然吸氣發動機的計劃。

全新寶馬x3

據海外媒體報道,全新寶馬X3將於2017年8月正式發布,並在同年9月開幕的2017法蘭克福車展上面向全球消費者亮相,它將比現款的X3(F25)在車身尺寸上有全面的放大。

在中國還將實現國產加長。新車將搭載四缸和六缸發動機,此外還將推出性能車型X3 M40i、X3 M40d,以及純電動版本車型(也就是更大更粗更強)

奧迪Q8e-tron概念車

而奧迪則正式公布了Q8e-tron概念車的官圖,並且將在2017年1月的北美車展上展出發布。直接與寶馬X6以及奔馳GLE Coupe進行pK。

從名字來看,這款奧迪Q8概念車將會搭載一套純電動或者插電式混動系統。

未來,奧迪Q8的量產版還可能搭載3.0T V6汽油發動機或4.0T V8柴油發動機,並且會配備奧迪最新的48V電氣系統。(奧迪的設計師不是都跑光了?)

中興手機也造車

日前,中興通訊通過收購珠海廣通客車,獲得了進入汽車市場的資質以及傳統造車技術。

此前中興智能汽車副總經理曾表示爭取在五年時間內,商用車市場做到業內前五”。

另有中興通訊的工作人員表示,中興收購廣通客車主要是為了取得資質,目前新能源客車的訂單量對於整個公司的業績還不構成影響,收購廣通就是為了牌照,所以產能有多少,能夠獲得多少,在於國家政策補貼。。。(哦哦,這個我們知道了)

Top gear賽道被賣

最近,前英國BBC媒體報道稱電視汽車節目《TopGear》專用賽道即將轉變成為生活住宅區,準備開發1800至2600棟全新房屋。

在經過多年的鬥爭,最終經過英國Waverly理事會公布10比8的投票結果,決定將《TopGear》使用的測試賽道重新開發規劃成生活、商業住宅區。(是不是李嘉誠做的?)

沃德十佳發動機大排全軍覆沒

不久前,沃德十佳發動機2017年的評選公布了名單,除了純自吸動力全軍覆沒之外,那就是今年沒有一台V8發動機,最大排量只有3.6L,要知道沃德是美國人的機構,V8發動機在他們心中的地位就像中國的乒乓球一樣。

其實這個評選是對美國本土銷售的車型進行了接近日常駕駛狀況的測試后,根據每台發動機的馬力、扭矩、技術含量,以及實際使用中表現出來的工作特性進行全面評估,最終選出十台綜合表現最好的發動機。

最早始於1994年,在每年年末發布。整個評選過程有着非常明確的規則,首先獲得提名的發動機必須是批量生產,而且所裝備的汽車開始銷售的時間也有明確的規定。同時參評的發動機所裝備的汽車售價須低於6萬美元,(有些沒獲獎的發動機可能是車賣得太貴了),此次的獲獎發動機要麼是混合動力,要麼是渦輪增壓,雖然曾有人研究表明不能盲目相信沃德十佳發動機

有諸多“潛規則”,比如豪車賣得便宜(這TM誰都喜歡啊),奇葩發動機容易獲獎:像沃爾沃的机械渦輪雙增壓,眼看着汽車的混合動力越來越多,排量是越來越小,排放越來越好,限號越來越多,要是以後路上全是4缸混動車等霧霾出來的時候,誰會成為下一個污染源呢?

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

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

※教你寫出一流的銷售文案?

不得不服!這台全能SUV居然能甩對手一條街

同時,奧迪Q7後排座椅支持前後移動,以身高178cm的體驗者,調節至最後面的後排實測腿部空間可超過2拳,即便調節最前面的腿部空間仍達1拳有餘。奧迪Q7的後備箱空間也不失所望,高達890L容積滿足一切對空間的想象。兼顧科技實用 配置領先同級在配置上,為了更好地體現兩者的差異性,我們不妨拿奧迪Q7和寶馬X5各自的頂配車型對比,從兩車的表格可以明顯看出,奧迪Q7擁有寶馬X5所不具備的感應後備箱,12。

在整個汽車大環境不太景氣的背景下,唯獨SUV銷量始終保持了逆市上揚的態勢,SUV市場份額從2012年的15%,一路攀升到今年的39%,由此可見,國人是有多喜歡SUV的高視野、高底盤以及大空間。然而,隨着消費需求的不斷升級,SUV同質化情況的加劇,用戶已經不滿足於SUV基礎單一的功能性,更需要兼具豪華感、科技感、駕駛性能等高端產品元素。

這也是為何豪華中大型SUV市場能受到極高的用戶關注度,而在這個級別中,最引人矚目想必是寶馬X5,奧迪Q7這兩款標杆之作。眾所周知,寶馬X5號稱是最強公路SUV,那麼奧迪Q7呢?事實上,奧迪Q7不僅是一款全路況SUV,同時還是一款能越野的SUV。因此,比較這兩台車就多了一番趣味性和參考價值。話不多說,還是趕緊看看寶馬X5和奧迪Q7,誰會更符合消費者的審美眼光呢?

外觀各具特色 奧迪Q7更顯豪華

寶馬X5的外觀風格強調力量感,雙腎前臉和天使眼是我們所熟知的寶馬家族化設計標誌,採用大量犀利有力量感的線條來突顯整車的運動感。而奧迪Q7作為奧迪旗下的旗艦車型,外觀方面自然也不敢馬虎,六邊形大嘴,搭配炫酷的LED 矩陣式大燈,兼具時尚和科技感,造型設計趨向於年輕動感。總的來說,同為德系的兩款豪華SUV都有很高的顏值,但寶馬X5更強調其運動身份,設計風格偏向於張揚高調。而奧迪Q7看上去更顯尊貴豪華,氣宇軒昂。

尺寸方面,長寬高達到5086/1968/1716mm,軸距3001mm,但相比寶馬X5,奧迪Q7在長度和軸距上更具優勢。此外,奧迪Q7還是同級別長度和軸距的領先者,舒適、寬敞不在話下。

內飾風格迥異 奧迪Q7科技完勝

兩車內飾的豪華感和品質感都營造得很出色,做工用料均無可挑剔。寶馬X5這套內飾設計相信大家已經非常熟悉,層次感分明,懸浮式中控大屏配合大量的實體按鍵,延續了寶馬以往的設計理念,但看久之後難免會有些審美疲勞。反觀之下,奧迪Q7的內飾則帶來一種新鮮感,煥然一新的內飾設計,瞬間燃爆用戶最敏銳的視覺神經,最大的驚喜莫過於這塊12.3英寸的全液晶儀錶盤,科技感爆棚,無論操作還是反饋的人性化程度都非常高,着實是令人愛不惜手。

正如上面所提到的,奧迪Q7的長度和軸距都要比寶馬X5優秀,實際表現也確實如此。同時,奧迪Q7後排座椅支持前後移動,以身高178cm的體驗者,調節至最後面的後排實測腿部空間可超過2拳,即便調節最前面的腿部空間仍達1拳有餘。奧迪Q7的後備箱空間也不失所望,高達890L容積滿足一切對空間的想象。

兼顧科技實用 配置領先同級

在配置上,為了更好地體現兩者的差異性,我們不妨拿奧迪Q7和寶馬X5各自的頂配車型對比,從兩車的表格可以明顯看出,奧迪Q7擁有寶馬X5所不具備的感應後備箱,12.3英寸全液晶儀錶盤,自動泊車,LED矩陣式大燈等科技配置。 尤其是在操控輔助方面,奧迪Q7旗艦車型所配備的quattro全時四驅系統、後輪主動轉向系統(選裝),同時全車減重300KG,足以提供奧迪Q7良好的操控性,賦予了奧迪Q7全路況駕駛性能。

更強勁的動力 更經濟的油耗

動力系統方面,兩車的銷量主力均為2.0T車型,寶馬X5和奧迪Q7都採用了2.0T發動機和8速手自一體變速箱的動力總成,寶馬X5的最大功率為180Kw,最大扭矩為350Nm,而奧迪Q7的最大功率為185Kw,最大扭矩為370Nm。從兩車的技術參數可見,奧迪Q7相對寶馬X5略勝一籌。而且,在燃油經濟性上,奧迪Q7 8.5L的官方百公里油耗數據,也確實比寶馬X5更有話語權。

如此全能的奧迪Q7會是你明年的目標?

說完了一大段后,誰更適合你,答案不正明擺着嗎?相比寶馬X5,奧迪Q7在許多方面都擁有過硬的實力,隨便一個產品點就能讓你為之傾心。氣場十足的高顏值外觀、由內到外的科技感和品質感,哦!別忘了,還有奧迪Q7最引以為傲的動力性和操控性。當然,或許你還在為操控還是舒適,實用還是逼格而煩惱,那麼綜合來看,除了全能均衡的奧迪Q7,還能有誰?嗯嗯,看到這之後,已經猜到你為明年購車計劃定好目標了。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

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

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

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

Redis 持久化

RDB

簡介

RDB持久化方式是通過快照(snapshotting)完成的,當符合一定條件時,redis會自動將內存中所有數據以二進制方式生成一份副本並存儲在硬盤上。當redis重啟時,並且AOF持久化未開啟時,redis會讀取RDB持久化生成的二進制文件(默認名稱dump.rdb,可通過設置dbfilename修改)進行數據恢復,對於持久化信息可以用過命令“info Persistence”查看。

save

該命令會由worker thread 執行,因此會阻塞 redis 的 worker ,期間不會響應任何其他客戶端發來的請求,直到RDB快照文件執行完畢,所以慎用。

測試

info persistence 
# rdb_last_save_time:1570126868
save
info persistence
# rdb_last_save_time:1570126928

bgsave

bgsave“後台保存”。與save 最大的差異為它並不是由 worker thread 執行的,而是由redis fork 齣子進程,交由子進程來完成持久化操作。

redisfork子進程這個時間段內 redis是阻塞的(此段時間不會響應客戶端請求),當子進程創建完成以後redis才會響應客戶端請求。

並且redis不會在控制台显示完成信息,只會寫入日誌。

流程

客戶端執行bgsave命令,redis主進程收到指令並判斷此時是否在執行bgrewriteaof(AOF文件重新過程,後續會講解),如果此時正好在執行則bgsave直接返回,不fork子進程,如果沒有執行bgrewriteaof重寫AOF文件,則進入下一個階段;

主進程調用fork方法創建子進程,在創建子進程過程中redis主進程阻塞,所以不能響應客戶端請求;

子進程創建完成以後,bgsave命令返回Background saving started,此時標志著redis可以響應客戶端請求了;

子經常根據主進程的內存副本創建臨時快照文件,當快照文件完成以後對原快照文件進行替換;

子進程發送信號給redis主進程完成快照操作,主進程更新統計信息(info Persistence可查看),子進程退出;

測試

bgsave
Background saving started  # 子進程創建成功,它會去 完成持久化操作

查看日誌

config get logfile
 11) "logfile"
 12) "/var/log/redis/redis-server.log"
cat "/var/log/redis/redis-server.log"
2497:M 04 Oct 2019 10:26:46.764 * Background saving started by pid 28960   # 開始後台 持久化
2497:M 04 Oct 2020 10:26:46.772 * Background saving terminated with success   # 後台持久化完成 

RDB相關配置

查看配置的方法:

1 查看配置文件

2 在redis 中查看當前 redis 的配置

CONFIG get *    # 獲取所有的配置
CONFIG get dir   # 獲取 快照文件 保存的 位置
CONFIG get dbfilename   # 獲取 快照文件 的文件名

快照文件位置

配置文件中 dir 指定

快照文件名

配置文件中 dbfilename

是否壓縮

配置文件中 rdbcompression default:yes

設置存儲至本地數據庫時是否壓縮數據,默認為yes,採用LZF壓縮

yes 會耗費一定的CPU資源,默認是 yes 。

no 會使存儲的文件變大(巨大)

是否校驗

配置文件中 yesrdbchecksumy default: yes

yes 會消耗一部分CPU資源,但是數據相對安全不容易損壞

no 可以節約讀寫性過程約10%時間消耗,但是存儲一定的數據損壞風險

後台持久化報錯

配置文件中 stop-writes-on-bgsave-error default: yes

後台存儲過程中如果出現錯誤線程,是否停止保存操作,默認是停止的

no 則忽略錯誤繼續。

快照檢查

配置文件中 rdbchecksum default: yes
在寫入文件和讀取文件時是否開啟rdb文件檢查,檢查是否有無損壞,如果在啟動是檢查發現損壞,則停止啟動。

RDB觸發

自動觸發

配置文件中 save default: yes

save second changes
# 查看默認的配置
config get save
"900 1 300 10 60 10000"
# 900秒內 1次鍵更新了就觸發持久化 或 300秒內 10次更新 持久化 60 秒內 10000次更新 觸發持久化
# 該持久化是 bgsave

手動觸發

手動執行 savebgsave

其他觸發

以下幾種種情況下會觸發執行快照操作,並且默認的使用bgsave

主從複製時,從庫全量複製同步主庫數據,此時主庫會執行bgsave命令進行快照;

客戶端執行數據庫清空命令FLUSHALL時候,觸發快照;

客戶端執行shutdown關閉redis時,觸發快照,也可以 使用 nosave 參數顯式聲明不保存快照

shutdown nosave

故障恢復

當redis意外崩潰或者關閉再次啟動時,此時AOF持久化未開啟時(默認未開啟),將使用RDB快照文件恢複數據。

# 查看日誌
cat /var/log/redis/redis-server.log
30448:M 04 Oct 2019 10:09:37.145 # Server initialized
30448:M 04 Oct 2019 10:09:37.145 * DB loaded from disk: 0.000 seconds   # 從快照恢復
30448:M 04 Oct 2019 10:09:37.146 * Ready to accept connections

缺點

RDB方式無論是執行指令還是利用配置,無法做到實時持久化,具體較大的可能性丟失數據

bgsave指令每次運行要執行fork操作創建子進程,要犧牲掉一些性能

Redis的眾多版本中未進行RDB文件格式的版本統一,有可能出現個版本服務之間數據格式無法兼容現象

存儲數據量較大,效率較低——基於快照思想,每次讀寫都是全部數據,當數據量巨大時,效率非常低
大數據量下的IO性能較低

AOF

簡介

日誌形式的AOF,將命令追加到文件。AOF可以將Redis執行的每一條寫命令追加到磁盤文件(appendonly.aof)中,在redis啟動時候優先選擇從AOF文件恢複數據。因為要頻繁的將每一個操作記錄到文件中,所以開啟AOF持久化會對性能有一定的影響,但是大部分情況下這個影響是可以接受的。

與RDB持久化相比,AOF持久化數據丟失更少,其消耗內存更少(RDB方式執行bgsve會有內存拷貝)。

AOF持久化過程

redisAOF持久化過程可分為以下階段:

追加寫入

redis將每一條寫命令以redis通訊協議添加至緩衝區aof_buf,這樣的好處在於在大量寫請求情況下,採用緩衝區暫存一部分命令隨後根據策略一次性寫入磁盤,這樣可以減少磁盤的I/O次數,提高性能。

同步三種策略

當寫命令寫入aof_buf緩衝區后,redis會將緩衝區的命令寫入到文件,redis提供了三種同步策略,由配置參數appendfsync決定,下面是每個策略所對應的含義:

no

不使用fsync方法同步,而是交給操作系統write函數去執行同步操作,在linux操作系統中大約每30秒執行一次 sync(man 2 sync 查看)。這種情況下,緩衝區數據同步不可控,並且在大量的寫操作下,aof_buf緩衝區會堆積會越來越嚴重,一旦redis出現故障,數據丟失嚴重,整體不可控。

always

表示每次有寫操作都調用fsync方法強制內核將數據寫入到aof文件。這種情況下由於每次寫命令都寫到了文件中, 雖然數據比較安全,但是因為每次寫操作都會同步到AOF文件中,所以在性能上會有影響,同時由於頻繁的IO操作,硬盤的使用壽命會降低。

everysec

數據將使用調用操作系統write寫入文件,並使用fsync每秒一次從內核刷新到磁盤。 這是折中的方案,兼顧性能和數據安全,所以redis默認推薦使用該配置。

文件重寫

當開啟AOF時,隨着時間推移,AOF文件會越來越大,redis提出一種重寫的策略來緩解數據存儲和恢復壓力。

重寫策略

重複或無效的命令不寫入文件

過期的數據不再寫入文件

多條命令合併寫入(當多個命令能合併一條命令時候會對其優化合併作為一個命令寫入,例如“RPUSH list1 a RPUSH list1 b” 合併為“RPUSH list1 a b” )

觸發條件

AOF文件觸發條件可分為手動觸發和自動觸發:

手動觸發:客戶端執行bgrewriteaof命令。

自動觸發:自動觸發通過以下兩個配置協作生效:

auto-aof-rewrite-min-size

AOF文件最小重寫大小,只有當AOF文件大小大於該值時候才可能重寫,4.0默認配置64mb。

auto-aof-rewrite-percentage

當前AOF文件大小和最後一次重寫后的大小之間的比率等於或者等於指定的增長百分比,如100代表當前AOF文件是上次重寫的兩倍時候才重寫。 

redis在AOF功能開啟的情況下,會維持以下三個變量

aof_current_size :記錄當前AOF文件大小

aof_rewrite_base_size:記錄最後一次AOF重寫之後,AOF文件大小

aof_rewrite_perc:增長百分比變量

每次當serverCron(服務器周期性操作函數)函數執行時,它會檢查以下條件是否全部滿足,如果全部滿足的話,就觸發自動的AOF重寫操作:

沒有BGSAVE命令(RDB持久化)/AOF持久化在執行;

沒有BGREWRITEAOF在進行;

當前AOF文件大小要大於server.aof_rewrite_min_size的值;

當前AOF文件大小和最後一次重寫后的大小之間的比率等於或者大於指定的增長百分比(auto-aof-rewrite-percentage參數)

重寫過程

  AOF文件重寫過程與RDB快照bgsave工作過程有點相似,都是通過fork子進程,由子進程完成相應的操作,同樣的在fork子進程簡短的時間內,redis是阻塞的,以下圖文說明其重寫過程:

開始bgrewriteaof,判斷當前有沒有bgsave命令(RDB持久化)/bgrewriteaof在執行,倘若有,則這些命令執行完成以後在執行。

主進程fork齣子進程,在這一個短暫的時間內,redis是阻塞的。

當完成重寫后,將重寫后的aof 文件合併到原有aof緩存文件中。並刪除臨時創建的重寫后的aof文件

AOF實現本質

AOF實現本質是基於redis通訊協議,將命令以純文本的方式寫入到文件中。

redis協議:

首先Redis是以行來劃分,每行以\r\n行結束。每一行都有一個消息頭,消息頭共分為5種分別如下:

(+) 表示一個正確的狀態信息,具體信息是當前行+後面的字符。

(-) 表示一個錯誤信息,具體信息是當前行-後面的字符。

(*) 表示消息體總共有多少行,不包括當前行,*後面是具體的行數。

($) 表示下一行數據長度,不包括換行符長度\r\n,$後面則是對應的長度的數據。

(:) 表示返回一個數值,:後面是相應的数字節符。

我們可以直接查看AOF文件中的格式,如下圖:

數據恢復

之前已經提到當AOF開啟時候,redis數據恢復優先選用AOF進行數據恢復,以下使用停止redis來模擬redis故障,然後在重寫啟動進行恢復。

AOF配置參數

auto-aof-rewrite-min-size

AOF文件最小重寫大小,只有當AOF文件大小大於該值時候才可能重寫,4.0默認配置64mb。

auto-aof-rewrite-percentage

當前AOF文件大小和最後一次重寫后的大小之間的比率等於或者等於指定的增長百分比,如100代表當前AOF文件是上次重寫的兩倍時候才重寫。默認 100

appendfsync

上文中提到的三種策略,默認 everysec

always | everysec | no

aof-load-truncated yes

當redis突然運行崩潰時,會出現aof文件被截斷的情況,Redis可以在發生這種情況時退出並加載錯誤,以下選項控制此行為。
如果aof-load-truncated設置為yes,則加載截斷的AOF文件,Redis服務器啟動發出日誌以通知用戶該事件。
如果該選項設置為no,則服務將中止並显示錯誤並停止啟動。當該選項設置為no時,用戶需要在重啟之前使用redis-check-aof實用程序修復AOF文件在進行啟動。

appendonly no

yes開啟AOF,no關閉AOF 默認 no

appendfilename

指定AOF文件名,4.0無法通過config set 設置,只能通過修改配置文件設置。默認 appendonly.aof

RDB-AOF混合持久化

簡介

redis4.0添加了新的持久化方式混合持久化

混合持久化默認是關閉的,它採用一種rdb + aof 的方式來實現,文件頭rdb 一個全量的快照,格式為二進制,後面是 aof 格式。這樣恢復會先查看開頭是否為REDIS,rdb開頭必然是REDIS。然後從快照恢復,之後從aof恢復。

這樣做的好處是可以結合 rdb 和 aof 的優點, 快速加載同時避免丟失過多的數據

缺點是 aof 裏面的 rdb 部分就是壓縮格式不再是 aof 格式,可讀性差。

開啟混合持久化

5 版本的redis 默認的開啟了aof-use-rdb-preamble 但是 appendonly 默認是 no 也就是說,只要開啟了aof 默認的會使用混合持久化。如果要使用單純的aof 則需要手動的 將 aof-use-rdb-preamble 設為 no (好坑)

4.0版本的混合持久化默認關閉的,通過aof-use-rdb-preamble配置參數控制,yes則表示開啟,no表示禁用,默認是禁用的,可通過config set修改。

混合持久化過程

創建子進程

生成全量的rdb快照,放在appendonly.aof 文件頭部。然後,接下來將aof緩衝區的增量命令以aof方式寫入文件尾

每次恢複數據時,首先從RDB部分恢復,然後執行aof。

數據恢復

開啟了混合持久化時,啟動redis依然優先加載aof文件,aof文件加載可能有兩種情況如下:

aof文件開頭是rdb的格式, 先加載 rdb內容再加載剩餘的 aof。

aof文件開頭不是rdb的格式,直接以aof格式加載整個文件。

三種持久化方案對比

RDB

優點

RDB 是一個非常緊湊(compact)的文件,體積小,傳輸速度快,適合災備。

RDB 可以最大化 Redis 的性能:父進程在保存 RDB 文件時唯一要做的就是 fork 出一個子進程,然後這個子進程就會處理接下來的所有保存工作,父進程無須執行任何磁盤 I/O 操作。

RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快很多。

缺點

RDB 丟數據將會丟掉兩次持久化之間的所有數據~

當redis中數據集比較大時候,RDB由於RDB方式需要對數據進行完成拷貝並生成快照文件,fork的子進程會耗CPU,並且數據越大,RDB快照生成會越耗時。

RDB文件是特定的格式,閱讀性差,由於格式固定,並且多版本之間存在不兼容情況。很難受~

AOF

優點

數據更完整,秒級數據丟失(取決於設置fsync策略)

兼容性較高,由於是基於redis通訊協議而形成的命令追加方式,無論何種版本的redis都兼容,再者aof文件是明文的,可閱讀性較好。

缺點

數據文件體積較大,即使有重寫機制,但是在相同的數據集情況下,AOF文件通常比RDB文件大。

相對RDB方式,AOF速度慢於RDB,並且在數據量大時候,恢復速度AOF速度也是慢於RDB。

由於頻繁地將命令同步到文件中,AOF持久化對性能的影響相對RDB較大,但是對於我們來說是可以接受的。

混合持久化

優點

混合持久化結合了RDB持久化 和 AOF 持久化的優點, 由於絕大部分都是RDB格式,加載速度快,同時結合AOF,增量的數據以AOF方式保存了,數據更少的丟失。

缺點

由於前部分是RDB格式,閱讀性較差,兼容性差,一旦開啟了混合持久化,4.0 版本之前的redis 都不認識這種aof文件~ 。

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

【其他文章推薦】

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

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

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

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

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