攜手 Uber 比亞迪進軍美電動車市場

叫車服務 Uber 日前證實已與比亞迪達成合作協議,將在美國推廣電動車服務,此舉被視為比亞迪挑戰美國電動車霸主特斯拉的一項舉動。   Uber 發言人 Lauren Altmin 指出,Uber 與比亞迪合作,將是其聚焦電動汽車服務的第一步。Uber 的測試計畫幾周前已在芝加哥展開,並最終將擴大到更多美國城市。Altmin 表示,Uber 去年年底開始與比亞迪和美國汽車銷售商 Green Wheels USA 展開談判,Green Wheels USA 將銷售比亞迪 e6 電動車,並負責在當地建設充電樁。   報導指出,Uber 正試圖用電動車擴大其低階租車領域的市場規模。比亞迪則透過與 Uber 的合作,實現進軍美國電動汽車市場的目標。

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

【其他文章推薦】

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

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

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

※幫你省時又省力,新北清潔一流服務好口碑

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

印度空污如毒氣室 準媽媽護嬰避免外出

摘錄自2019年11月08日中央通訊社印度報導

挺著大肚子的戈卡維(Rachel Gokavi)把自己關在新德里家中,拚命保護即將出生的嬰孩免於有毒空氣危害——印度流產率和嬰孩死亡率飆高,被歸咎於有毒空氣。

在最近新德里一場產前課程,戈卡維和其他懷孕母親分享她們的無助和憤怒,因為每天必須呼吸有毒空氣。26歲的戈卡維告訴法新社:「我總是關閉陽台的門,並且盡量不要外出。我害怕在孩子誕生時會有呼吸問題。」由於空氣如此差,新德里市長最近把首都比擬為「毒氣室」。

在可預見的未來,空氣污染仍然看不到緩解。面對這個情況,醫生也別無選擇,只能建議例如戴口罩或者使用大多數人都買不起的家用空氣清淨機。

根據世界衛生組織統計,全球污染最嚴重的15個城市,有14個在印度境內。每年冬天農民焚燒作物殘梗產生的煙霧,加上工業及車輛排放的廢氣,讓印度北部各地城鎮變成煙霧籠罩的可怕地獄。

根據6月出版的政府研究報告,這種有毒混合物每年縮短100萬名印度人的壽命。報告也表示,空氣污染每年造成超過10萬名5歲以下小孩死亡。

醫生說,兒童呼吸有毒空氣的速度是大人的兩倍,因為兒童的肺比較小,這會造成小孩呼吸系統問題,甚至傷害腦部發育。聯合國兒童基金會(UNICEF)本週指出,證據顯示,青少年暴露在較嚴重空氣污染中,更容易出現心理健康問題。

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

【其他文章推薦】

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

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

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

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

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

土地劣化警訊 歐洲泥炭地乾旱擴大 部分達2000年來最嚴重

環境資訊中心外電;姜唯 翻譯;林大利 審校;稿源:Carbon Brief

根據,歐洲的泥炭地可能會從碳匯轉變為碳排放源,因為有1/4的泥炭地乾旱程度已達到2000年來最嚴重。

這種「大範圍」且「嚴重」乾旱趨勢與近期自然和人為氣候變遷趨勢吻合,也可能是因為泥炭地被用於農業和燃料而加劇。

同時有,北部地區泥炭地儲存的碳量可能是過去估計值的兩倍。

這兩篇論文都發表在《自然地球科學》(Nature Geoscience)期刊上,顯示有必要努力保護泥炭地作為高緯度地區的碳儲存場所。

歐洲泥炭地乾旱程度達到令科學家緊張的程度。照片來源:里茲大學(CC0)

受威脅的泥炭地

土壤積水情況延緩植物分解的速度時便形成泥炭地,死去的植物在此長時間層層累積。透過泥炭地,科學家能了解地球陸地表面如何排放和吸收碳。

儘管泥炭地僅覆蓋地球表面的3%左右,但土壤碳含量卻佔了大約五分之一。在歐洲,泥炭地生態系統儲存的二氧化碳比森林多五倍。

但是許多泥炭地生態受到威脅,部分原因是人類數百年來利用泥炭作為燃料或肥料。

受損的泥炭地是顯著的碳排放源,每年釋放約3.5%的全球人為二氧化碳排放量。

里茲大學的研究人員、論文之一的主要作者史雲鐸(Graeme Swindles)博士介紹了歐洲乃至歐洲之外地區泥炭地生態系統面臨的各種問題:

「因為人類對泥炭資源或土地利用的需求,泥炭地面臨破碎化、水分排乾、燃燒、農業和綠化等威脅。氣候暖化和乾旱也是主要因素。」

雖然淹水的泥炭會繼續儲存碳,但氣候變動或人類破壞引起的擾動會使氧氣進入,觸發二氧化碳的釋放。

歐洲許多泥炭地已經顯示出這種跡象,其中植被從泥炭苔蘚變成草木和灌木。

芬蘭Torronsuo國家公園的一處沼澤濕地。 攝(CC BY 2.0)

乾旱趨勢

萊斯特大學濕地生態學家佩姬(Susan Page)教授肯定史雲鐸的研究。該研究確認了從斯堪地那維亞到波羅的海,整個歐洲泥炭地的乾旱趨勢,在最近200年間尤其明顯。佩姬向Carbon Brief解釋:

「泥炭地提供許多有益的生態系統服務,但常常被低估,包括碳儲存和封存,對減緩氣候變化有重要作用,其日漸乾旱的趨勢應受到關注。」

這個趨勢不只是人為活動所造成,但作者指出,歐洲泥炭地「可能正在偏離自然變化的基線」,其中又以英國和愛爾蘭的泥炭地最為嚴重。

由於缺乏長期的水文監測數據,科學家們利用沼澤中的微小變形蟲的殼來推測歷史水位。

他們分析了31個歐洲泥炭地的重建情況,發現從1800年到2000年,有60%的土地比過去600年更為乾旱。

此外,有40%的泥炭地處於1,000年來最乾旱的狀態,更有24%是2,000年以來最乾旱。

他們認為這反映了該地區氣候日益乾旱,人為影響可能加劇了這個趨勢。整體而言,研究人員在42%的測試地點發現重大破壞,另有29%遭受輕微破壞。

但是史雲鐸強調,他們的研究工作大多在歐洲最完好的土地上進行…因此許多泥炭地的狀況會更糟。

第二篇論文讓史雲鐸的研究結果更顯重要。第二篇研究指出,歐洲泥炭地儲存碳的作用可能比過去所知更大。

英國湖區的泥炭地。照片來源: (CC BY-NC-ND 2.0)

碳儲存估算結果倍增

紐約哥倫比亞大學的尼可斯(Jonathan Nichols)教授和同事皮特(Dorothy Peteet)教授的研究估計,北部泥炭地儲存著大約10,550億公噸的碳。2010年理海大學余自成(Zicheng Yu,音譯)博士等人在同一地區估算出的數據則是5,470億公噸。

尼可斯說,過去的研究沒有將適當將未採樣地區納入估計,如亞洲和南部歐洲。

他說,泥炭地的碳通常使用「歷時法」測量,將各個地點的碳隨時間累積的速率求平均值,再加上泥炭地的面積以求出總碳量。

根據他們的論文,過去使用此方法的研究已受到「幾個已知的採樣偏差來源」的影響。

兩位作者強調了這樣一個假設:泥炭隨時間的累積速率是全球氣候的結果,因此北半球的泥炭地都相似。

尼可斯向Carbon Brief解釋在此假設下他們的方法如何改善估計精準度:

「最大的差異在於如何求所有不同地點的平均水準……人們用來衡量碳累積率的大多數地點都在西北歐洲和加拿大,因此計算會偏向那些地方,而遠離其他地方……(我們試著)根據地區加權平均值,而不是根據已進行的測量次數任意加權。」

研究人員使用4,000多個放射性碳測量值來確定645個泥炭地測試點的泥炭年齡。

他們將來自Neotoma古生態學資料庫先前未使用的數據與新的計算方法結合,估算碳累積的歷史以及泥炭地的形成時間。

位於拉脫維亞的大凱邁里(Great Kemeri)沼澤區。來源: (CC BY 2.0)

潛在問題

Carbon Brief採訪了許多科學家,他們對尼可斯和皮特的分析感到驚訝,因為他們的碳儲量估計比過去大很多。有人對他們的估計方法提出了疑問。

2010年泥炭地碳累積研究主持人余博士告訴Carbon Brief,他很高興看到這樣的論文取得了可觀的進展,但他擔心其中可能有「重大技術缺陷」而必須修訂。

他告訴Carbon Brief,這個領域的科學家很早就認同必須考量泥炭地之間的區域差異,但缺乏足夠的資料來這麼做:

「在這方面,新論文透過計算八個泥炭地區中每個區域的碳累積率來解決空間偏差,很可能是重大的進展跟改善。」

(新研究的作者主要依據政治邊界將北部的泥炭地分為八個區域。他們還設計了另外兩種劃分區域的方式,以消除任何偏誤。)

余自成說,據他所知,儘管泥炭地之間存在已知的差異,但尼可斯和皮特必須用一個平均碳密度值代表所有站點「很可惜,但也許無法避免。」

透過合併以前被忽略的數據,新論文的作者納入了通常不被視為「北部」泥炭地的地點,包括南歐某些地區,甚至還有北非的一些地區。

余自成認為,這兩個因素的結合導致對北部泥炭碳儲存量的高估。

尼可斯在回應此批評時告訴Carbon brief,除了平均碳密度以外,他們還納入有16,000個測量值的大量分布,因此能考慮到相當大的變化和不確定性。至於採納更多地點,他說「基於這份研究的觀點,這麼做是對的」:

「我們要根據已知泥炭地的所在來測量泥炭地的碳,而非根據假設的泥炭地所在。」

實際上,這表示該研究包括了過去不納入研究的區域(包括泥炭地比較少的地區)的數據。整體而言,他說,他們的方法旨在產生「更大的不確定性」,但最終結果比過去的研究更接近「真實」答案。

芬蘭北部奧伊湖(Oijärvi)附近一處沼澤溼地。 (CC BY 2.0)

真正的問題

這兩篇論文強調泥炭地對科學家了解氣候系統的重要性,以及維護和恢復泥炭地的必要性。

阿伯丁大學土壤學專家、政府間氣候變遷專門委員會的作者史密斯(Pete Smith)教授沒有參與任何一項研究,他對Carbon brief表示:

「綜觀這兩份研究,它們顯示高緯度泥炭地是重要的碳匯,因為泥炭地面積和碳儲量都在成長,但是一旦變得乾旱,則可能從淨碳匯變成碳排放源,這是真正的問題。」

他指出,儘管史雲鐸的論文顯示泥炭地變乾的現象可能還沒有超出「正常的泥炭地乾濕週期,但偏離長期基準表示逼近一個臨界值,超過這個臨界值則泥炭形成會轉為泥炭降解,導致大量的碳進入空氣。」

佩姬說,特別令人擔憂的是,這些擾動和人類活動的結合會產生「累積效應」。

史雲鐸和他的團隊寫道,歐洲泥炭地正處於「過渡狀態」,已經採取一些措施,像是堵塞人工排水溝和溝渠來恢復部分泥炭地。

他們指出,這些行動對於防範人為影響和未來的全球暖化可能非常重要。他們說要採取這些措施必須參考他們的研究發現。

尼可斯表示,考慮到泥炭地面臨的威脅,對於科學家而言,調查全世界可用的泥炭總量很重要,才能計算有多少可以損失:

「泥炭地通常不被當成全球氣候模型的一部分。但如果我們想對未來的氣候做出現實的預測,泥炭地就必須成為一部分。」

Europe’s carbon-rich peatlands show ‘widespread’ and ‘concerning’ drying trends by Josh Gabbatiss

European peatlands could turn from carbon sinks to sources as a quarter have reached levels of dryness unsurpassed in a record stretching back 2,000 years, according to a new study.

This trend of “widespread” and “substantial” drying corresponds to recent climate change, both natural and human-caused, but may also be exacerbated by the peatlands being used for agriculture and fuel.

It comes as another study estimates that the amount of carbon stored in peatlands across northern regions could be as much as double previous, widely reported estimates.

The papers, both published in Nature Geoscience, indicate a need for efforts to conserve peatlands as sites of carbon storage at higher latitudes.

Taken together, the findings are “a real concern”, according to one scientist not involved in the research, given the key role these ecosystems play in the global carbon cycle.

Threatened peat

Peatlands when waterlogged conditions slow down plant decomposition, meaning layers of dead plants accumulate over many years as peat. They are a vital component in scientists’ understanding of how the planet’s land surface emits and takes up carbon.

Despite only covering around 3% of the Earth’s surface, peatlands contain of its soil carbon. In Europe, these ecosystems store more CO2 than forests.

However, the existence of many peatlands is under threat, partly thanks to centuries of human exploitation of peat as a or .

Damaged peatlands are a significant source of emissions, 3.5% of global anthropogenic CO2 emissions each year.

, a researcher and lead author of one of the papers, lays out the various issues facing these ecosystems in Europe and further afield:

“Cutting, drainage, burning, agriculture, afforestation. All driven by need for peat as a resource or for land-use practices not in line with keeping healthy peatlands. Climate warming and drying is also a major factor in tandem with these.”

While waterlogged peat will continue to store carbon, disturbances resulting from climate fluctuations or humans damaging these ecosystems allow oxygen to enter it, triggering the release of CO2.

Many European peatlands have already shown evidence of this transition, as the vegetation they support shifting from peat mosses to grass and shrubs.

Drying trend

The , produced by Swindles and a large international group of scientists, was welcomed by wetland ecologist as a “robust piece of work” – and one with some significant implications.

It identifies a drying trend across European peatlands, from Scandinavia to the Baltics, that has become particularly pronounced in the last 200 years. Page explains to Carbon Brief:

“This trend should be of concern given that peatlands deliver a range of beneficial, but often undervalued ecosystem services, including carbon storage and sequestration and, therefore, have an important role to play in climate mitigation.”

While the results are not merely the result of human interventions, the authors note that European peatlands “may now be moving away from natural baselines”. The results were most severe for peatlands across Great Britain .

As there is no long-term hydrological monitoring data available, the scientists use the presence of shells (or “tests”) from tiny, to gauge historic water levels.

They analysed reconstructions of 31 European peatlands, concluding 60% of the sites were drier from 1800 to 2000 than they had been for the last 600 years.

Furthermore, 40% of sites were at their driest in 1,000 years, and 24% were drier than they had ever been across the entire 2,000-year record.

While they concluded that this effect mirrored an increasingly dry climate in the region, they also note that human influence in peatlands is likely to have exacerbated the trend. In total, they identified significant damage by people in 42% of the sites and a further 29% suffering from minor damage.

However, Swindles notes that they “mostly worked on the most intact sites in Europe…so there are many more that have suffered drainage far worse than this”.

These results could be particularly significant in light of the second paper, which suggests the role played by European peatlands in storing carbon may be even greater than previously imagined.

Doubling storage

In , and his colleague , both at in New York, estimate that northern peatlands store approximately 1,055 gigatonnes (Gt) of carbon.

They compared this to a made by from and his collaborators back in 2010, who arrived at a figure of 547Gt for the same region.

Nichols explains their work to Carbon Brief, noting that past analyses did not properly account for undersampled regions, such as Asia and Southern Europe.

Peatland carbon, he says, is normally measured using a “time-history method” that involves averaging together the rate at which carbon has accumulated over time at a variety of sites, combined with the area of the peatland to get the total amount of carbon.

According to their paper, past attempts that have used this method have been affected by “several known sources of sampling bias”.

Specifically, the pair highlight the assumption that peat accumulation rates over time are the result of the global climate and are, therefore, similar across the northern hemisphere.

Nichols explains to Carbon Brief how their method improves on this assumption:

“The big difference is how I average all the different sites together…Most of the sites that people have measured carbon accumulation rate at are in Northwest Europe and Canada. So you basically bias your calculations towards those places and away from other places…[We tried to] fix that problem by weighting our averages based on area, instead of arbitrarily based on how many measurements had been made.”

The researchers used over 4,000 radiocarbon measurements to determine the age of peat from 645 peatland sites.

They incorporated previously unused data from the , together with new computer algorithms for estimating the history of peat carbon accumulation and when peatlands were formed.

Nichols notes that while their final figure for carbon storage is considerably higher than previous data-driven efforts, modelling studies have already yielded higher figures:

“If you used an earth system model to predict how much peat there should be, it’s usually more than what we get when we measure, so hopefully this will make it so they are more in line.”

Potential shortcomings

Carbon Brief talked to a number of scientists who expressed surprise at Nichols and Peteet’s analysis, given the far larger estimate of carbon storage it yielded. Others raised questions about the methods the pair had used to arrive at their final figure.

Yu, who led the team that arrived at the 2010 peatland estimate, tells Carbon Brief that while he is pleased to see such a paper achieving prominence, he is concerned there are “major technical shortcomings” that have led to this considerable revision.

He tells Carbon Brief that while scientists working in this area have “long recognised” that accounting for regional differences between peatlands is the “right way to go”, lack of sufficient data has hampered their efforts:

“In this regard, this new paper has made a potentially important progress and improvement by attempting the calculations of carbon accumulation rates for each of eight peat regions, with a goal to account for spatial bias.”

(As part of their analysis, the researchers divided northern peatlands into eight regions, based mainly on political boundaries, that tend to be reported in scientific literature. They also devised two other ways of dividing the region up to eliminate any biases.)

Yu goes on to say that it is “unfortunate and perhaps unavoidable” that, from what he could tell, Nichols and Peteet had to use a single average carbon density value for all sites, despite the known variation across peatlands.

He adds that by incorporating previously overlooked data, the authors of the new paper have included sites that would not normally be considered under the category of “northern” peatlands. Among these are some parts of southern Europe and even a couple in North Africa.

Yu says that, in his view, the combination of these two factors has led to an overestimation of the amount of carbon storage provided by northern peat.

Responding to this criticism, Nichols tells Carbon Brief that beyond the average carbon density, they also took into account the considerable variation and uncertainty by incorporating a large distribution of values based on 16,000 measurements. As for the wider array of locations, he says this “gets right at the point of the paper”:

“We set out to measure carbon in peatlands based on where we know peatlands to exist, not where we assume them to be.”

In practice, this means including data from unconventional areas, including regions where peatlands are sparse. Overall, he says their methods were designed to produce “much wider uncertainties” but also a final result that is closer to the “real” answer than previous attempts.

‘Real concern’

The publication of these two papers serves to highlight the importance of peat for scientists’ understanding of the climate system, as well as the need to preserve and restore peatlands.

, a soils expert at the and author who was not involved in either study, tells Carbon Brief:

“Taken together, the studies suggest that high-latitude peatlands are acting as a significant carbon sink, as they are growing in area and carbon stock – but, if they are also drying, there is potential that they could turn from net carbon sinks to sources. Given the huge store of carbon in high latitude peatlands, that is a real concern.”

He notes that while the Swindles paper suggests drying may not yet be beyond “normal peatland drying cycles”, the shift away from long-term baselines “may be pushing them closer to a threshold whereby peat formation is replaced by peat degradation, which would lead to massive losses of carbon to the atmosphere”.

Page says a particular concern is that a combination of these perturbations and human activities have a “cumulative effect”.

Swindles and his team write that with European peatlands in a “state of transition”, there are to restore some of them by damming artificial drains and gullies.

They note that these actions may be “vital” in protecting against both human impacts and future global warming. They say these initiatives must take their findings into account.

For his part, Nichols says that considering the threats facing peatlands, it is important for scientists to investigate the total volume of peat available across the world, in order to “put a number on how much there is to lose”:

“Peatlands are not usually part of global climate models. If we want to make realistic predictions of future climate, peatlands need to be a part of it.”

※ 全文及圖片詳見:()

參考資料

  • Swindles, G.T. et al. (2019) Widespread drying of European peatlands in recent centuries, Nature Geoscience,
  •  
  • Nichols, J.E. and Peteet, D.M. (2019) Rapid expansion of northern peatlands and doubled estimate of carbon storage, Nature Geoscience,

※ 本文與 行政院農業委員會 林務局  合作刊登

作者

如果有一件事是重要的,如果能為孩子實現一個願望,那就是人類與大自然和諧共存。

於特有生物研究保育中心服務,小鳥和棲地是主要的研究對象。是龜毛的讀者,認為龜毛是探索世界的美德。

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

【其他文章推薦】

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

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

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

※幫你省時又省力,新北清潔一流服務好口碑

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

特斯拉第 1 季交車破萬輛 年增 55%

美國電動車大廠特斯拉(Tesla Motors)今年第 1 季交車量突破 1 萬台,較去年同期暴增 55%,創下新高,今年全年銷量可望超越去年,但欲達成執行長穆斯克(Elon Musk)所設的今年交車 5.5 萬輛目標,恐怕還得加把勁。   特斯拉今年首季 Model S 交車量 10,030 台,比該公司初估的還高出 500 台,年增 55%。由此數據看來,今年 Model S 銷量很有希望大幅超越去年的 31,655 輛。   創辦人兼執行長穆斯克立下今年 5.5 萬台、2020 年前 50 萬台的交車目標,若能達成的話,特斯拉將在割喉競爭的汽車市場占有一席之地。

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

【其他文章推薦】

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

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

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

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

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

台歐盟電動車研討會登場!助台廠入全球供應鏈

為推動台歐盟雙方未來在電動車領域的合作,經濟部標準檢驗局、國際貿易局及歐洲經貿辦事處於 4 月 10 日共同舉辦「臺歐盟電動車研討會」。   台灣具有良好資通訊產業基礎及發展智慧車輛模組系統能量,發展電動車產業有競爭潛力,如能獲得歐盟相關經驗,必可切入全球電動車之零件與系統模組供應鏈,促成國內電動車產業迅速發展。   標準檢驗局劉明忠局長表示,為加速推動台灣電動車發展,自 2011 年便積極推動電動車運行環境的標準,至 2014 年底已完成包括整車、鋰電池系統,電動機/驅動器及共通詞彙/符號等總計 34 種電動車國家標準,已完成包括最高速率、電能消耗、行駛距離、加速能力及爬坡速率等超過 50 個以上測試項目之實車驗證。

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

【其他文章推薦】

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

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

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

※幫你省時又省力,新北清潔一流服務好口碑

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

恕我直言你可能真的不會java第7篇:像使用SQL一樣排序集合

在開始之前,我先賣個關子提一個問題:我們現在有一個Employee員工類。

@Data
@AllArgsConstructor
public class Employee {

   private Integer id;
   private Integer age;   //年齡
   private String gender;  //性別
   private String firstName;  
   private String lastName;
}

你知道怎麼對一個Employee對象組成的List集合,先按照性別字段倒序排序,再按照年齡的倒序進行排序么?如果您不知道4行代碼以內的解決方案(其實是1行代碼就可以實現,但筆者格式化為4行),我覺得您有必要一步步的看下去。

一、字符串List排序

cities是一個字符串數組。注意london的首字母是小寫的。

List<String> cities = Arrays.asList(
        "Milan",
        "london",
        "San Francisco",
        "Tokyo",
        "New Delhi"
);
System.out.println(cities);
//[Milan, london, San Francisco, Tokyo, New Delhi]

cities.sort(String.CASE_INSENSITIVE_ORDER);
System.out.println(cities);
//[london, Milan, New Delhi, San Francisco, Tokyo]

cities.sort(Comparator.naturalOrder());
System.out.println(cities);
//[Milan, New Delhi, San Francisco, Tokyo, london]
  • 當使用sort方法,按照String.CASE_INSENSITIVE_ORDER(字母大小寫不敏感)的規則排序,結果是:[london, Milan, New Delhi, San Francisco, Tokyo]
  • 如果使用Comparator.naturalOrder()字母自然順序排序,結果是:[Milan, New Delhi, San Francisco, Tokyo, london]

同樣我們可以把排序器Comparator用在Stream管道流中。

cities.stream().sorted(Comparator.naturalOrder()).forEach(System.out::println);

//Milan
//New Delhi
//San Francisco
//Tokyo
//london

在java 7我們是使用Collections.sort()接受一個數組參數,對數組進行排序。在java 8之後可以直接調用集合類的sort()方法進行排序。sort()方法的參數是一個比較器Comparator接口的實現類,Comparator接口的我們下一節再給大家介紹一下。

二、整數類型List排序

List<Integer> numbers = Arrays.asList(6, 2, 1, 4, 9);
System.out.println(numbers); //[6, 2, 1, 4, 9]

numbers.sort(Comparator.naturalOrder());  //自然排序
System.out.println(numbers); //[1, 2, 4, 6, 9]

numbers.sort(Comparator.reverseOrder()); //倒序排序
System.out.println(numbers);  //[9, 6, 4, 2, 1]

三、按對象字段對List<Object>排序

這個功能就比較有意思了,舉個例子大家理解一下。

Employee e1 = new Employee(1,23,"M","Rick","Beethovan");
Employee e2 = new Employee(2,13,"F","Martina","Hengis");
Employee e3 = new Employee(3,43,"M","Ricky","Martin");
Employee e4 = new Employee(4,26,"M","Jon","Lowman");
Employee e5 = new Employee(5,19,"F","Cristine","Maria");
Employee e6 = new Employee(6,15,"M","David","Feezor");
Employee e7 = new Employee(7,68,"F","Melissa","Roy");
Employee e8 = new Employee(8,79,"M","Alex","Gussin");
Employee e9 = new Employee(9,15,"F","Neetu","Singh");
Employee e10 = new Employee(10,45,"M","Naveen","Jain");


List<Employee> employees = Arrays.asList(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);

employees.sort(Comparator.comparing(Employee::getAge));
employees.forEach(System.out::println);
  • 首先,我們創建了10個Employee對象,然後將它們轉換為List
  • 然後重點的的代碼:使用了函數應用Employee::getAge作為對象的排序字段,即使用員工的年齡作為排序字段
  • 然後調用List的forEach方法將List排序結果打印出來,如下(當然我們重寫了Employee的toString方法,不然打印結果沒有意義):
Employee(id=2, age=13, gender=F, firstName=Martina, lastName=Hengis)
Employee(id=6, age=15, gender=M, firstName=David, lastName=Feezor)
Employee(id=9, age=15, gender=F, firstName=Neetu, lastName=Singh)
Employee(id=5, age=19, gender=F, firstName=Cristine, lastName=Maria)
Employee(id=1, age=23, gender=M, firstName=Rick, lastName=Beethovan)
Employee(id=4, age=26, gender=M, firstName=Jon, lastName=Lowman)
Employee(id=3, age=43, gender=M, firstName=Ricky, lastName=Martin)
Employee(id=10, age=45, gender=M, firstName=Naveen, lastName=Jain)
Employee(id=7, age=68, gender=F, firstName=Melissa, lastName=Roy)
Employee(id=8, age=79, gender=M, firstName=Alex, lastName=Gussin)
  • 如果我們希望List按照年齡age的倒序排序,就使用reversed()方法。如:
employees.sort(Comparator.comparing(Employee::getAge).reversed());

四、Comparator鏈對List<Object>排序

下面這段代碼先是按性別的倒序排序,再按照年齡的倒序排序。

employees.sort(
        Comparator.comparing(Employee::getGender)
        .thenComparing(Employee::getAge)
        .reversed()
);
employees.forEach(System.out::println);

//都是正序 ,不加reversed
//都是倒序,最後面加一個reserved
//先是倒序(加reserved),然後正序
//先是正序(加reserved),然後倒序(加reserved)

細心的朋友可能注意到:我們只用了一個reversed()倒序方法,這個和SQL的表述方式不太一樣。這個問題不太好用語言描述,建議大家去看一下本文對應的視頻!

排序結果如下:

Employee(id=8, age=79, gender=M, firstName=Alex, lastName=Gussin)
Employee(id=10, age=45, gender=M, firstName=Naveen, lastName=Jain)
Employee(id=3, age=43, gender=M, firstName=Ricky, lastName=Martin)
Employee(id=4, age=26, gender=M, firstName=Jon, lastName=Lowman)
Employee(id=1, age=23, gender=M, firstName=Rick, lastName=Beethovan)
Employee(id=6, age=15, gender=M, firstName=David, lastName=Feezor)
Employee(id=7, age=68, gender=F, firstName=Melissa, lastName=Roy)
Employee(id=5, age=19, gender=F, firstName=Cristine, lastName=Maria)
Employee(id=9, age=15, gender=F, firstName=Neetu, lastName=Singh)
Employee(id=2, age=13, gender=F, firstName=Martina, lastName=Hengis)

歡迎關注我的博客,裏面有很多精品合集

  • 本文轉載註明出處(必須帶連接,不能只轉文字):字母哥博客。

覺得對您有幫助的話,幫我點贊、分享!您的支持是我不竭的創作動力! 。另外,筆者最近一段時間輸出了如下的精品內容,期待您的關注。

  • 《手摸手教你學Spring Boot2.0》
  • 《Spring Security-JWT-OAuth2一本通》
  • 《實戰前後端分離RBAC權限管理系統》
  • 《實戰SpringCloud微服務從青銅到王者》
  • 《VUE深入淺出系列》

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

【其他文章推薦】

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

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

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

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

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

認證授權方案之授權初識

1.前言

回顧:認證授權方案之JwtBearer認證

在上一篇中,我們通過JwtBearer的方式認證,了解在認證時,都是基於Claim的,因此我們可以通過用戶令牌獲取到用戶的Claims,在授權過程中對這些Claims進行驗證,從而來判斷是否具有獲取或執行目標資源操作的權限。本章就來介紹一下 ASP.NET Core 的授權系統的簡單使用。

2.說明

授權與身份認證是相互獨立,但是,授權卻需要一種身份驗證機制,因此,身份驗證可以為當前用戶創建一個或多個標識,是確定用戶真實身份的過程。而授權是根據標識確定用戶可執行的操作的過程,其本質就是具有某種特性的用戶會有權限訪問某個資源或者執行某個操作。例如:一個擁有管理員身份的用戶有創建人員、刪除人員、編輯人員和刪除人員的操作權限,而一個非管理身份的用戶僅有讀取自己信息的權限。

這時候,你可能會問,究竟怎樣特性的用戶可以被授權訪問某個資源或執行某個操作。由此我們引出了授權策略的方式,可以根據用戶擁有的角色,也可以根據用戶的職位,部門甚至是性別,年齡等等特性進行授權。

通過建立授權策略方式,檢驗認證的用戶所攜帶的身份聲明(ClaimsPrincipal對象)與授權策略是否一致,從而確定用戶可否執行操作。

3.授權

3.1. 基於角色

3.1.1 添加角色

將角色賦予某個控制器或控制器內的操作,指定當前用戶必須是其角色才能訪問請求資源。

可以使用Authorize屬性的Roles特性指定所請求資源的角色。

例如:

  • 分配了“admin”角色用戶進行訪問操作
[Authorize(Roles ="admin")]
public class WeatherForecastController : ControllerBase
{

}
  • 以逗號分隔角色名來允行多個角色訪問操作
[Authorize(Roles ="admin,user")]
public class WeatherForecastController : ControllerBase
{ 


}

其中只要滿足admmin或者user其一就可以進行訪問。

  • 同時滿足指定的多個角色進行的訪問操作
[Authorize(Roles = "admin")]
[Authorize(Roles = "user")]
public class WeatherForecastController : ControllerBase
{ 
}

3.1.2 添加策略的角色

可以創建策略的方式進行訪問控制,在配置授權服務中添加註冊授權服務策略。

在Startup.cs文件中,通過ConfigureServices()配置服務,創建一個允許具有admin角色的用戶才能進行訪問的策略

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        //添加授權角色策略
        services.AddAuthorization(options =>
        {
            options.AddPolicy("BaseRole", options => options.RequireRole("admin"));
        });
        //或者指定多個允許的角色
        //services.AddAuthorization(options =>
        // {
        //    options.AddPolicy("MoreBaseRole", options => options.RequireRole("admin","user"));
        // });
    }

在控制器方法使用特性Policy的屬性進行策略應用

    [Authorize(Policy = "BaseRole")]
    public class WeatherForecastController : ControllerBase
    {
    
    }

3.2. 基於聲明

3.2.1添加聲明

對當前用戶必須擁有的聲明,並將聲明賦予某個控制器或控制器內的操作,因此,指定聲明必須持有對應的值才能訪問請求資源。

聲明要求基於策略,所以必須進行構建一個表示聲明要求的策略,才能進行授權。

最簡單的類型聲明是將判斷聲明是否存在,而不檢查值。

可以創建策略的方式進行訪問控制,在配置授權服務中添加註冊授權服務策略。

在Startup.cs文件中,通過ConfigureServices()配置服務,創建一個允許具有聲明的用戶才能進行訪問的策略

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        //添加基於聲明的授權
        services.AddAuthorization(options =>
        {
            options.AddPolicy("BaseClaims", options => options.RequireClaim("name"));
        });
    }

BaseClaims聲明策略會檢查name當前標識是否存在聲明。

在控制器方法使用特性Policy的屬性進行策略應用

    [Authorize(Policy = "BaseClaims")]
    public class WeatherForecastController : ControllerBase
    {
    
    }

但是,大多時候,我們需要聲明包含值,只有指定允許值的列表,才能授權成功。所以,可以添加指定值。

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        //添加基於聲明的授權,指定允許值列表。
        services.AddAuthorization(options =>
        {
            options.AddPolicy("BaseClaims", options => options.RequireClaim("name","i3yuan"));
        });
    }

3.3 基於策略

上面介紹的基於角色和基於聲明的授權,都使用了要求、要求處理程序和預配置的策略。這些在構建上提供了便捷,但是最終都是生成授權策略。ASP.NET Core,設計了另一種靈活的授權方式,一種更豐富的可重複使用的授權結構,基於策略的授權,同時這也是授權的核心。

這節會先講一下授權策略的應用,在下一節中,會對授權策略的核心進行一步步的詳解。

在上面我們簡單的介紹了基於策略的角色授權,但是這種方式無非基於角色或者聲明多一些。

因此,這裏我們基於自定義策略授權的方式,實現授權。

自定義授權,就要我們自己寫策略提供器,自己根據不同的參數來生成不同的策略,重新實現策略的方式。策略要求由以下兩種元素組成:僅保留數據的要求類,以及對用戶驗證數據的授權處理程序。創建自定義要求,還可以進一步表達特定策略。

3.3.1. 定義權限策略PermissionRequirement

定義一個權限策略,這個策略並包含一些屬性。

public class PermissionRequirement: IAuthorizationRequirement
{
    public string _permissionName { get; }

    public PermissionRequirement(string PermissionName)
    {
        _permissionName = PermissionName;
    }
}

3.3.2. 再定義一個策略處理類

public class PermissionRequirementHandler : AuthorizationHandler<PermissionRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
    {
        var role = context.User.FindFirst(c => c.Type == ClaimTypes.Role);
        if (role != null)
        {
            var roleValue = role.Value;
            if (roleValue==requirement._permissionName)
            {
                context.Succeed(requirement);
            }
        }
        return Task.CompletedTask;

授權處理程序讀取與角色用戶關聯的聲明,並檢查自定義的角色,如果角色匹則成功,否則無法返回成功。

這裏的自定義聲明是寫固定了,但是也可以通過數據庫或外部服務的方式進行運行查詢獲取用戶相關角色信息相對應的判斷條件,從而在處理程序中進行判斷處理。

授權處理程序調用方法 Succeed,同時傳遞當前要求,以通知此要求已成功得到驗證。如果沒有傳遞要求,處理程序無需執行任何操作,可以直接返回內容。不過,如果處理程序要確定是否不符合要求(無論其他處理程序是否已成功驗證同一要求),將會對授權上下文對象調用方法 Fail

3.3.3. 下面展示了如何將自定義要求添加到策略

(請注意,由於這是自定義要求,因此沒有擴展方法,而必須繼續處理策略對象的整個 Requirements 集合):

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        //基於自定義策略授權
        services.AddAuthorization(options =>
        {
            options.AddPolicy("customizePermisson",
              policy => policy
                .Requirements
                .Add(new PermissionRequirement("admin")));
        });
        //此外,還需要在 IAuthorizationHandler 類型的範圍內向 DI 系統註冊新的處理程序:
        services.AddScoped<IAuthorizationHandler, PermissionRequirementHandler>();
        // 如前所述,要求可包含多個處理程序。如果為授權層的同一要求向 DI 系統註冊多個處理程序,有一個成功就足夠了。

    }

3.3.4. 應用自定義的策略的特性

指定當前用戶必須是應用對控制器或控制器內的操作,如

   [Authorize(Policy = "customizePermisson")]
    public class WeatherForecastController : ControllerBase
    { 
    }

4.場景

在上一篇認證授權方案之JwtBearer認證中,我們已經實現了獲取token的方式,這一次,我們實現一個以基於角色場景為例的認證授權。

在原來生成token的方式中,添加多一個聲明角色的Claim,如下:

new Claim(JwtClaimTypes.Role,”admin”)

    [HttpGet]
    public IActionResult GetToken()
    {
        try
        {
            //定義發行人issuer
            string iss = "JWTBearer.Auth";
            //定義受眾人audience
            string aud = "api.auth";
            //定義許多種的聲明Claim,信息存儲部分,Claims的實體一般包含用戶和一些元數據
            IEnumerable<Claim> claims = new Claim[]
            {
                new Claim(JwtClaimTypes.Id,"1"),
                new Claim(JwtClaimTypes.Name,"i3yuan"),
                new Claim(JwtClaimTypes.Role,"admin"),
            };
            //notBefore  生效時間
            // long nbf =new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds();
            var nbf = DateTime.UtcNow;
            //expires   //過期時間
            // long Exp = new DateTimeOffset(DateTime.Now.AddSeconds(1000)).ToUnixTimeSeconds();
            var Exp = DateTime.UtcNow.AddSeconds(1000);
            //signingCredentials  簽名憑證
            string sign = "q2xiARx$4x3TKqBJ"; //SecurityKey 的長度必須 大於等於 16個字符
            var secret = Encoding.UTF8.GetBytes(sign);
            var key = new SymmetricSecurityKey(secret);
            var signcreds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            //String issuer = default(String), String audience = default(String), IEnumerable<Claim> claims = null, Nullable<DateTime> notBefore = default(Nullable<DateTime>), Nullable<DateTime> expires = default(Nullable<DateTime>), SigningCredentials signingCredentials = null
            var jwt = new JwtSecurityToken(issuer: iss, audience: aud, claims:claims,notBefore:nbf,expires:Exp, signingCredentials: signcreds);
            var JwtHander = new JwtSecurityTokenHandler();
            var token = JwtHander.WriteToken(jwt);
            return Ok(new
            {
                access_token = token,
                token_type = "Bearer",
            });
        }
        catch (Exception ex)
        {
            throw;
        }
    }

對控制器或控制器內的操作,指定當前用戶必須是其角色才能訪問請求資源,如WeatherForecastController.cs

[ApiController]
[Route("[controller]")]
[Authorize(Roles ="admin")]
public class WeatherForecastController : ControllerBase
{ 
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

5.運行

5.1. 獲取token

分別獲取role為admin和role為user的情況下頒發的token,只有在角色為admin的情況下才能授權通過。

5.2. 授權資源接口訪問

在role為admin的情況下

在role為user的情況下

由上可知,只有在角色為admin的情況下,才能訪問目標資源進行操作。

6.總結

  1. 從上一篇的認證到這一篇的授權階段,簡單的介紹了Asp.net Core的認證授權系統,對授權有了初步的認識以及使用,對授權進行劃分為兩種,一種是基於角色的授權,但隨着角色的增加會對處理授權產生限制,不適合表達複雜的授權邏輯。另一種是基於策略的身份驗證,策略包含一系列基於聲明的要求,以及基於可從 HTTP 上下文或外部源注入的其他任何信息的自定義邏輯。這些要求各自與一個或多個處理程序相關聯,這些處理程序負責要求的實際計算。
  2. 可以發現,asp.net core提供的授權策略是一個非常強大豐富且靈活的認證授權方案,能夠滿足大部分的授權場景。
  3. 如果有不對的或不理解的地方,希望大家可以多多指正,提出問題,一起討論,不斷學習,共同進步。
  4. 因此,在後續的篇章中,會繼續探索授權系統,對授權策略的核心進行一步步的詳解。
  5. 本示例源碼地址

參考文獻文檔

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

【其他文章推薦】

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

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

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

※幫你省時又省力,新北清潔一流服務好口碑

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

阿拉斯加「平紀錄高溫+破紀錄大雪」出現同一天!

摘錄自2019年11月18日ETtoday綜合報導

今年入秋以來,美國阿拉斯加州氣候異常溫暖,當地最大城市安克拉治居民,近日竟在同一天內,先後經歷了創紀錄高溫與破紀錄降雪兩種截然不同的極端天氣型態!

位於安克拉治國際機場南側的美國國家氣象局(NWS)安克拉治辦公室,當天觀測到超過8.3英吋積雪,打破當地1958年以來的降雪新紀錄。奇怪的是,安克拉治市當天不止出現破紀錄降雪,同一天凌晨3時,當地還出現華氏45度(攝氏7.2度)氣溫,與1967創下的的同日最高溫紀錄持平。

NWS預報員德魯茲(Eric Drewitz)解釋,16日凌晨,一股東南風從海上吹來,為城市帶來溫暖空氣,雖著風勢減弱,氣溫也隨之下滑,並且降下硬幣大小的雪花。報導提到,阿拉斯加州今年秋天以來異常溫暖,10月下旬也曾出現破紀錄高溫,溫暖天氣一直延續到11月。在16日降下大雪以前,當地今年入冬第一場,也是唯一一場降雪出現在10月16日,但降雪量僅5分之1英吋(約0.5公分)。

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

【其他文章推薦】

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

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

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

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

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

減塑全球風潮 2020年起泰國商場禁用塑膠袋

摘錄自2019年11月18日NOWnews報導

為了達到環保的目的,2020年起泰國許多連鎖超商或大賣場將不再供應塑膠袋。根據路透社的報導,泰國國家資源和環境部部長瓦拉伍特(Varawut Silpa-archa)在臉書宣佈,許多商店與政府合作,暫停提供一次用塑膠袋,措施將於2020年1月起生效。

「方便性會下降,不過這是為了延續環境的生態循環。」瓦拉伍特受訪時說,他建議民眾可以使用可重複利用的大布袋取代塑膠袋。

不再提供塑膠袋的商店包括在泰國管理上千家7-11的CP All Plc公司和泰國購物商場集團。其實,這並不是泰國第一次嘗試縮減塑膠袋使用的政策。早在2018年,CAN便報導過泰國旅遊局曾發佈「國家淨化聲明」,希望在2021年時,能減少一半以上現行使用的塑膠袋總用量。

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

【其他文章推薦】

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

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

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

※幫你省時又省力,新北清潔一流服務好口碑

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

因為我的一個低級錯誤,生產數據庫崩潰了將近半個小時

前言

halo,相信大家一定過了一個很開心的端午節吧,我看朋友圈裡各種曬旅遊,曬美食的,真是羡慕啊,不像我,感冒了只能在家擼文章。
當然,玩的多開心,節後上班就有多鬱悶,假日綜合征可不是說說而已。對此我想表達的是,沒事,不用鬱悶,來看我如何自爆家醜來讓你們開心下。

反常的sql語句

上周四午休時分,我正在工位上小憩,睡夢中彷彿看到了自己拿着李白在榮耀峽谷里大殺四方的情景,就在我剛拿完五殺準備帶領隊友推對面水晶的時候,一句慌亂急促的“糟了”把我從睡夢中驚醒。我眯開朦朧的雙眼,才發現剛才的發聲來源於我的組長庄哥,看到他在緊張的點開日誌系統查看日誌,我預感到有什麼不妙的事情發生,仔細一問才知道,原來就在我眯眼的期間,線上數據庫服務器的CPU被打滿,同時觸發了生產數據庫只讀延遲的限定時間並且發出告警,而且告警的過程持續了半個小時。

這讓我倒吸了一口涼氣,因為我們組做的系統很多都用的是同一個數據庫服務器,日用戶活躍量有好幾十萬,如果服務器崩潰了將會使所有的系統服務都不可用,於是我們趕緊通過sql日誌進行問題查找,最後排查出來是因為一張sql的高量查詢沒有走索引導致,日誌列表显示,這條sql語句的掃描行數達到了上百萬,基本就是全表掃描的情況,而且半個小時的時間查詢了達上萬次,每條sql查詢的耗時都在3000ms以上。我的天啊,難怪服務器會CPU打滿,這麼一條耗時的sql語句查詢量這麼大,數據庫的資源當然是直接就崩潰了,這是當時那條sql的查詢情況:

臨時處理

看了這條語句,我又倒吸一口涼氣,這不就是我寫的系統調用的sql語句嗎?完了,這回逃不掉了,真是人在睡夢裡,鍋從天上來。

當然,因為是我自己寫的sql,所以我一看就知道這條語句是有問題的。

根據我的代碼處理,這條sql的調用還少了個重要的參數user_fruit_id,這個參數沒有傳的話是不應該走這條sql查詢的,在我的設計里,該參數是數據表裡一個聯合索引的最左側字段,如果該字段沒有傳值的話,那麼索引就不會生效了。

KEY `idx_userfruitid_type` (`user_fruit_id`,`task_type`,`receive_start_time`,`receive_end_time`) USING BTREE

雖然定位到了sql語句,但是線上的問題刻不容緩,總不可能找出bug改完再上線吧,所以,我們只能做了一個臨時處理,就是在原來的表上多加了一個聯合索引,其實就是去掉了user_fruit_id 字段,讓這些高量的查詢都能走新的索引,就像下面這樣

KEY `idx_task_type_receive_start_time` (`task_type`,`receive_start_time`,`receive_end_time`,`created_time`) USING BTREE

加上索引后,sql的掃描行數就大幅度的降低了,重啟實例后就又能正常運行了。

最左匹配原則

那麼為什麼最左側的字段沒傳索引就不生效了,這是因為MySQL的聯合索引是基於“最左匹配原則”匹配的。

我們都知道,索引的底層是B+樹結構,聯合索引的結構也是B+樹,只不過鍵值數量不是一個,而是多個,構建一顆B+樹只能根據一個值來構建,因此數據庫依據聯合索引最左的字段來構建B+樹。

例如我們用兩個字段(name,age)這個聯合索引來分析,

圖片來源於林曉斌老師的《MySQL實戰45講》課程,

當我們在where條件中查找name為“張三”的所有記錄的時候,可以快速定位到ID4,並且查出所有包含“張三”的記錄,而如果要查找“張三,10”這一條特定的數據,就可以用 name = “張三” and age = 10 獲取,因為聯合索引的鍵值對是兩個,所以只要前面的name確定的情況下就可以進一步定位到具體的age記錄,但是如果你的查詢條件只有age的話,那麼索引就不會生效,因為沒有匹配最左邊的字段,後面所有的索引字段都不會生效,所以我之前寫的sql語句才會因為少了最左邊的user_fruit_id字段而走了全表掃描的查詢方式。

正常來說,假設一個聯合索引設計成(a,b)這樣的結構的話,那麼用a and b作為條件,或者a單獨作為查詢條件都會走索引,這種情況下我們就不要再為a字段單獨設計索引了。

但如果查詢條件裏面只有b的語句,是無法使用(a,b)這個聯合索引的,這時候你不得不維護另外一個索引,也就是說你需要同時維護(a,b)、(b) 這兩個索引。

找出Bug

雖然臨時做了處理,但問題並不算解決,很明顯是系統出現了bug才會有走這樣的查詢條件。因為是我自己寫的代碼,所以知道是哪條sql后我就馬上定位到了代碼里的具體方法,後來才發現是因為我對user_fruit_id字段的判空處理不生效所致。

因為該字段是從調用方傳過來的,所以我在方法參數里對該字段做了非空限制的註解,也就是javax包下的@NotNull,

public class GardenUserTaskListReq implements Serializable {

    private static final long serialVersionUID = -9161295541482297498L;

    @ApiModelProperty(notes = "水果id")
    @NotNull(message = "水果id不能為空")
    private Long userFruitId;
    /**以下省略*/
    .....................
}

雖然加上該註解來做非空校驗,但我卻沒有在參數加上另一個註解@Validated,該註解如果沒加上的話,那麼調用javax包下的校驗規則就都不生效,正確的寫法是在controller層方法的參數前面加上註解,

除此之外,因為user_fruit_id這個字段是另一張表的主鍵,我在代碼里也沒有對這張表是否存在這個id做查詢判斷,這樣一來,無論調用方傳什麼值過來都會直接觸發sql查詢,並且在不跑索引的情況下直接走全表掃描。

不得不說,這真是個低級錯誤,說真的,我對這個原因真是感到嘀笑皆非,再怎麼說也工作幾年了,怎麼還犯一些新手級別的錯誤呢,這臉打得真是讓我相當慚愧。

總結

雖然是低級錯誤,但造成的後果也算挺嚴重了,這次事件也讓我更加的警醒,在以後的開發工作中必須要遵守該有的原則,大概有這麼幾點:

1、不能相信調用端。重要的參數都要先做驗證,即使是非空值也需要做驗證,不符合條件的就要直接返回或拋異常,不能參与業務sql的查詢,否則頻繁的訪問也會對服務造成負擔。

2、sql語句要先做性能查詢。對於數據量大的表,建好索引后,所有的sql查詢語句要用explain檢測性能,並且根據結果來進一步優化索引。

3、代碼必須要review。之前我沒有放太大的精力在代碼的review上,雖說跟迭代排期的緊湊也有關係,但不管怎麼說,bug確實是我的疏忽造成的,尤其是像空值這種細小的錯誤在Java里可以說家常便飯。千里之堤毀於蟻穴,有時一個小bug很容易就引發整個系統的崩盤,這一次的問題也讓我更加深刻的認識到了review代碼的重要性,不管業務開發的工作量有多麻煩,這一步操作絕對不能忽視。

後續

知道了bug的原因,改完代碼當天就重新發布了,後來,庄哥告訴我說,為了以後讓組裡的其他人對此次問題有所警戒,讓我寫一篇問題記錄總結一下,我想了一下,這不是我的強項啊,但怎麼說也確實是自己的問題,還是老老實實的寫一下記錄好了。我本以為這樣就可以松一口氣了,可平哥 (組裡的一位大佬) 卻突然用詭異的眼神看着我,語重心長的說,上次xxx也因為線上出現問題寫了報告,你這一次估計也不能例外了,可能要一萬字以上。我瞬間就感覺一個雷劈到了我頭上,蒼天啊。。。。。。

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

【其他文章推薦】

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

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

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

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

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