程序包android.support.annotation不存在_我不知道我不了解的Redis知识
"已知的東西; 有些事情我們知道我們知道。 我們也知道有未知的事物。 就是說(shuō)我們知道有些事情我們不知道。 但是,還有未知的未知數(shù)-我們不知道的我們不知道的……后一類往往是困難的。"
唐納德·拉姆斯菲爾德
> Redis Wikipedia Page Logo
我與Redis在一起已經(jīng)有好幾年了,從來(lái)沒有真正遇到過(guò)任何問(wèn)題。 我已經(jīng)使用Redis計(jì)劃和部署了大規(guī)模的Web服務(wù),并使用了數(shù)十億條日常讀寫命令(使用可上下伸縮的主從復(fù)制),并且可以"正常工作"。 從開發(fā)人員的角度來(lái)看,這導(dǎo)致了我一個(gè)錯(cuò)誤的假設(shè),即我了解關(guān)于Redis所需的全部知識(shí)(而且,正如一位偉大的詩(shī)人所說(shuō),假設(shè)是所有問(wèn)題的源頭)。
當(dāng)然,我不是DevOps工程師,也不知道Redis的所有細(xì)節(jié)(但我仍然不知道),但是我覺得使用Redis被"發(fā)現(xiàn)"了。 其他服務(wù)(例如MySQL)迫使我對(duì)它們的概念有扎實(shí)的了解,以便編寫快速高效的代碼(再次,無(wú)需像DBA一樣掌握MySQL,但至少您需要了解索引或JOIN才能快速編寫代碼 和高效的查詢)。 但是使用Redis,我可以將其"即插即用"到我的代碼中。
幾周前,我被分配來(lái)解決在我們的一項(xiàng)舊服務(wù)中從Redis提取數(shù)據(jù)時(shí)的性能問(wèn)題。 該服務(wù)的業(yè)務(wù)邏輯并不那么重要,但是對(duì)該服務(wù)的工作方式以及Redis的使用方式的總體概述將有助于我們理解問(wèn)題所在以及最終如何解決。
我們擁有一個(gè)大型系統(tǒng),可以存儲(chǔ)由不同實(shí)體產(chǎn)生的數(shù)十億每日事件。 查詢實(shí)體事件可能很慢,并且在許多情況下是多余的,因?yàn)槲覀儾恍枰袛?shù)據(jù)。 這就是我們提供服務(wù)的地方-它提供了一個(gè)API,可以快速查詢最近30天的實(shí)體唯一事件。
例如,假設(shè)有一個(gè)系統(tǒng)監(jiān)視著帶有傳感器的空調(diào),該傳感器在每次AC狀態(tài)發(fā)生變化(打開/關(guān)閉會(huì)更改AC狀態(tài)以及改變溫度)時(shí)發(fā)送事件。 一個(gè)AC狀態(tài)每天可能會(huì)更改很多次,并且我們的系統(tǒng)將為每次更改存儲(chǔ)一個(gè)事件,但是我們的服務(wù)僅會(huì)為過(guò)去30天內(nèi)所做的每個(gè)更改返回一個(gè)事件(無(wú)論AC被翻轉(zhuǎn)了多少次) ,我們的服務(wù)將返回單個(gè)"打開"事件)。
Redis快速,支持?jǐn)?shù)據(jù)過(guò)期(我們只需要最近30天的事件,還記得嗎?),并且具有Set數(shù)據(jù)結(jié)構(gòu),是我們服務(wù)的理想存儲(chǔ):將同一項(xiàng)目多次添加到Set中將導(dǎo)致只有一個(gè)副本 此商品在套裝中。 可以將存儲(chǔ)在我們系統(tǒng)中的每個(gè)實(shí)體(AC)的數(shù)百萬(wàn)個(gè)不同事件轉(zhuǎn)換為幾十個(gè)唯一項(xiàng)(事件)的小集合。 我們的服務(wù)僅需要"偵聽"傳入的事件,并使用AC ID和日期作為鍵將它們存儲(chǔ)到Redis中,并將到期時(shí)間設(shè)置為30天。 當(dāng)查詢AC事件時(shí),我們的服務(wù)將計(jì)算所有此AC密鑰并返回存儲(chǔ)在這些密鑰中的所有事件的并集。
Redis中存儲(chǔ)的數(shù)據(jù)的一覽視圖如下所示:
: #{on, off, 24°, 28° ...}, expires 2019-10-30
: #{on, off, 25°, 27° ...}, expires 2019-10-29
: #{on, 26°, humidity 32° ...}, expires 2019-10-28
...
...
...
: #{off, humidity 35° ...}, expires 2019-10-01
: #{on, off, 23°, 27° ...}, expires 2019-10-30
: #{on, off, 25°, 28° ...}, expires 2019-10-29
...
...
...
: #{24°, 26°, humidity 42° ...}, expires 2019-10-01
: #{on, off, 23°, 27° ...}, expires 2019-10-30
...
...
...
密鑰是具有事件收集日期的實(shí)體的ID。 ac1-2019-09-30代表id = ac1的實(shí)體,其值是該日期收集的一組事件。 該密鑰將于2019–10–30到期。
在Redis內(nèi)部,我們的服務(wù)使用SUNION命令來(lái)獲取特定實(shí)體在不同日期存儲(chǔ)的所有事件的聯(lián)合集:
SUNION
...
...
這個(gè)簡(jiǎn)單的邏輯可以處理99.6%的查詢。 但是,有時(shí)從Redis獲取數(shù)據(jù)花費(fèi)的時(shí)間很長(zhǎng)(在某些情況下可能需要30秒),這在產(chǎn)品上并不被接受。
我已經(jīng)開始解決因搜索通用規(guī)則而導(dǎo)致的響應(yīng)緩慢的問(wèn)題,這并不奇怪,這通常發(fā)生在SUNION處理大型Set時(shí)(也并非總是如此)。 Redis中存儲(chǔ)的大多數(shù)Set(基本代表元素?cái)?shù))的基數(shù)小于100。 但是對(duì)于少量的Set,大小可能會(huì)很大。 如您在下表中所見,有85%的組合有0–50個(gè)項(xiàng)目,少于0.5%的組合有1,000個(gè)或更多項(xiàng)目)
我在閱讀服務(wù)代碼時(shí)注意到的另一件事是,為了避免產(chǎn)生較大的響應(yīng)負(fù)載,無(wú)論對(duì)服務(wù)進(jìn)行編碼的是誰(shuí),都對(duì)API返回的事件數(shù)量進(jìn)行了限制(我們將在后面看到為什么這與 解決方案)。
了解我對(duì)Redis的了解后,使用SUNION命令似乎是一個(gè)合理的解決方案。 如果我是首先編寫此服務(wù)的人,那么我可能會(huì)做同樣的事情。 但是,您不知道的內(nèi)容有時(shí)會(huì)造成很多痛苦……谷歌搜索很快發(fā)現(xiàn)了兩個(gè)我對(duì)Redis不了解或不完全了解的事實(shí):
· SUNION是一個(gè)緩慢的命令,采用兩個(gè)大集合的交集可能會(huì)花費(fèi)大量時(shí)間。 實(shí)際上,我在Redis官方文檔中閱讀它感到很驚訝,因?yàn)槲乙恢闭J(rèn)為Redis會(huì)一直保持快速。
· 從命令執(zhí)行的角度來(lái)看,Redis主要是單線程服務(wù)器,這意味著當(dāng)請(qǐng)求緩慢時(shí),所有其他客戶端將等待該請(qǐng)求得到處理。
了解問(wèn)題是找到正確解決方案的一半。 我意識(shí)到SUNION并不是我需要的命令,但是有哪些替代方案? 好吧,感謝Google和Redis.io文檔,我遇到了SSCAN命令。 SSCAN命令(實(shí)際上,Redis中有針對(duì)不同數(shù)據(jù)類型的一堆不同的SCAN命令)允許在Set上進(jìn)行增量迭代,每次調(diào)用僅返回少量元素。 可以使用它而不會(huì)受到諸如SMEMBERS或SUNION之類的命令的負(fù)面影響,這些命令在針對(duì)大型集合進(jìn)行調(diào)用時(shí)可能會(huì)長(zhǎng)時(shí)間阻塞服務(wù)器。
請(qǐng)注意,SSCAN在一個(gè)集合上完全迭代的時(shí)間復(fù)雜度為O(N),其中N是集合基數(shù)。 對(duì)于SMEMBERS來(lái)說(shuō),這也是命令的復(fù)雜性,但是如果您還記得,我還說(shuō)過(guò)我們的服務(wù)對(duì)從其API返回的商品數(shù)量有一定的限制。 由于一旦達(dá)到此限制就可以中斷SSCAN迭代,因此我們的時(shí)間復(fù)雜度實(shí)際上將是O(Min(N,Limit)),這是SUNION的要求,它將始終從Redis(和我們的服務(wù)邏輯)中提取數(shù)據(jù) 將對(duì)整個(gè)項(xiàng)目集合中返回的項(xiàng)目數(shù)設(shè)置限制)
到目前為止,一切都很好,但是在SUNION上使用SSCAN可能會(huì)有不利的一面嗎? 好吧,可能存在—盡管像SUNION這樣的阻塞命令可以保證在給定的時(shí)間內(nèi)提供集合中的所有元素,但是SSCAN命令只能提供有限的保證,因?yàn)榧峡梢栽诘^(guò)程中進(jìn)行更改。 在完整的SSCAN迭代過(guò)程中,集合中不存在的元素可能會(huì)返回,也可能不會(huì)返回:它是未定義的。 但是,考慮到我們不會(huì)從Redis中刪除項(xiàng)目(只是添加新項(xiàng)目),因此這并不是我們服務(wù)中的真正問(wèn)題。
確實(shí)運(yùn)行了一些基準(zhǔn)測(cè)試可以測(cè)試SSCAN(僅提取有限數(shù)量的項(xiàng)目)與SUNION提取所有數(shù)據(jù),并且它們以編程方式僅從中提取第一個(gè)有限的項(xiàng)目,這顯示出明顯的改進(jìn)。 對(duì)于小型Set,時(shí)間大致相同,但是對(duì)于具有1,000多個(gè)項(xiàng)目的大型Set,時(shí)間要好得多
繁榮! 問(wèn)題解決了。 從這個(gè)過(guò)程中我得出什么結(jié)論? -可以說(shuō)我們需要更好地了解我們的知識(shí),但是在現(xiàn)實(shí)生活中,我們?cè)谌粘9ぷ髦惺褂迷S多不同的服務(wù)和程序包(數(shù)據(jù)庫(kù),云服務(wù),開源程序包等),而這幾乎是不可能的 掌握所有這些知識(shí)(不僅僅是性能,請(qǐng)考慮其中一些軟件包可能存在的安全性問(wèn)題)。
但是,我們至少應(yīng)該嘗試掌握我們所依賴的服務(wù),這些軟件包會(huì)對(duì)我們的服務(wù)產(chǎn)生巨大影響。
(本文翻譯自Tzafrir Ben Ami的文章《What I didn't know I didn't know about Redis》,參考:https://medium.com/swlh/what-i-didnt-know-i-didn-t-know-about-redis-6ad3729f29ed)
總結(jié)
以上是生活随笔為你收集整理的程序包android.support.annotation不存在_我不知道我不了解的Redis知识的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python列表元素零的移动_pytho
- 下一篇: idea代码提示插件_IDEA 插件推荐