查詢數(shù)據(jù)的方法及裝置制造方法
【專利摘要】本申請公開了查詢數(shù)據(jù)的方法及裝置,其中,所述方法包括:攔截當前查詢請求;判斷是否存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作;如果是,則阻塞所述當前查詢請求;待所述歷史查詢請求執(zhí)行完成后,利用其查詢結(jié)果向所述當前查詢請求返回查詢結(jié)果。在實現(xiàn)過程中,本申請實施例不會出現(xiàn)在一次查詢數(shù)據(jù)庫操作正在執(zhí)行的過程中,又有相同的查詢請求重復提交到數(shù)據(jù)庫的情況,有效減輕了數(shù)據(jù)庫的訪問負擔,并提高了查詢效率。
【專利說明】查詢數(shù)據(jù)的方法及裝置
【技術(shù)領(lǐng)域】
[0001]本申請涉及數(shù)據(jù)查詢【技術(shù)領(lǐng)域】,特別是涉及查詢數(shù)據(jù)的方法及裝置。
【背景技術(shù)】
[0002]在高并發(fā)環(huán)境下,很容易發(fā)生以下情況:在同一時間段內(nèi),大量用戶對數(shù)據(jù)庫系統(tǒng)的并發(fā)查詢導致數(shù)據(jù)庫壓力增大,響應緩慢,進而影響整個系統(tǒng)的正常運轉(zhuǎn)。但在實踐中發(fā)現(xiàn),在大量的查詢請求中有很多都是同樣的。例如,用戶點擊網(wǎng)站首頁,如果首頁上面需要展示的部分或全部數(shù)據(jù)來自于數(shù)據(jù)庫,則大部分內(nèi)容對于用戶來說是完全一樣的,對于后臺服務器而言,需要執(zhí)行的數(shù)據(jù)庫查詢操作也是一樣的。
[0003]基于該特點,為了提高數(shù)據(jù)查詢的效果,現(xiàn)有技術(shù)中一般會采用緩存來應對,也即,如果客戶端提交的兩個查詢是完全一樣的,則服務器端會緩存前一個查詢結(jié)果,并直接將緩存的查詢結(jié)果返回給下一個相同的查詢,從而減少對數(shù)據(jù)庫的訪問。由于內(nèi)存比數(shù)據(jù)庫的讀寫效率要高,所以對于發(fā)起同樣請求的客戶端來說,響應時間會大大縮短。
[0004]然而,現(xiàn)有技術(shù)中雖然使用了緩存方案,但是,在緩存尚未建立的時間段內(nèi),所有的查詢請求都會無差別地提交到數(shù)據(jù)庫里。如果查詢時間較長,那么這段時間內(nèi)產(chǎn)生的并發(fā)請求也足以使數(shù)據(jù)庫性能驟降,因此,仍然會經(jīng)常發(fā)生數(shù)據(jù)庫負擔過重的問題。
【發(fā)明內(nèi)容】
[0005]本申請?zhí)峁┝瞬樵償?shù)據(jù)的方法及裝置,能夠避免對數(shù)據(jù)庫造成不必要的負擔,有利于提高查詢效率。
[0006]本申請?zhí)峁┝巳缦路桨?
[0007]一種查詢數(shù)據(jù)的方法,包括:
[0008]攔截當前查詢請求;
[0009]判斷是否存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作;
[0010]如果是,則阻塞所述當前查詢請求;
[0011]待所述歷史查詢請求執(zhí)行完成后,利用其查詢結(jié)果向所述當前查詢請求返回查詢結(jié)果。
[0012]一種查詢數(shù)據(jù)的裝置,包括:
[0013]請求攔截單元,用于攔截當前查詢請求;
[0014]判斷單元,用于判斷是否存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作;
[0015]請求阻塞單元,用于如果判斷單元的判斷結(jié)果為是,則阻塞所述當前查詢請求;
[0016]查詢結(jié)果返回單元,用于待所述歷史查詢請求執(zhí)行完成后,利用其查詢結(jié)果向所述當前查詢請求返回查詢結(jié)果。
[0017]根據(jù)本申請?zhí)峁┑木唧w實施例,本申請公開了以下技術(shù)效果:[0018]通過本申請,在攔截到一個數(shù)據(jù)庫查詢請求之后,可以首先判斷是否存在相同的查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作,如果存在,則可以將該當前查詢請求阻塞,不再將其提交到數(shù)據(jù)庫進行查詢,等到正在執(zhí)行查詢數(shù)據(jù)庫操作的查詢請求獲得查詢結(jié)果之后,再利用該查詢結(jié)果向當前查詢請求返回查詢結(jié)果。因此,在實現(xiàn)過程中,不會出現(xiàn)在一次查詢數(shù)據(jù)庫操作正在執(zhí)行的過程中,又有相同的查詢請求重復提交到數(shù)據(jù)庫的情況,因此,減輕了數(shù)據(jù)庫的訪問負擔,有利于提高查詢效率。
[0019]當然,實施本申請的任一產(chǎn)品并不一定需要同時達到以上所述的所有優(yōu)點。
【專利附圖】
【附圖說明】
[0020]為了更清楚地說明本申請實施例或現(xiàn)有技術(shù)中的技術(shù)方案,下面將對實施例中所需要使用的附圖作簡單地介紹,顯而易見地,下面描述中的附圖僅僅是本申請的一些實施例,對于本領(lǐng)域普通技術(shù)人員來講,在不付出創(chuàng)造性勞動的前提下,還可以根據(jù)這些附圖獲得其他的附圖。
[0021]圖1是本申請實施例提供的方法的流程圖;
[0022]圖2是本申請實施例提供的另一方法的流程圖;
[0023]圖3是本申請實施例提供的裝置的示意圖。
【具體實施方式】
[0024]下面將結(jié)合本申請實施例中的附圖,對本申請實施例中的技術(shù)方案進行清楚、完整地描述,顯然,所描述的實施例僅僅是本申請一部分實施例,而不是全部的實施例。基于本申請中的實施例,本領(lǐng)域普通技術(shù)人員所獲得的所有其他實施例,都屬于本申請保護的范圍。
[0025]本申請發(fā)明人在實現(xiàn)本申請的過程中發(fā)現(xiàn),現(xiàn)有技術(shù)的緩存方案中,之所以仍然會產(chǎn)生數(shù)據(jù)庫負載過重,查詢效果不高的問題,一方面原因是,現(xiàn)有技術(shù)中往往存在以下情況:如果數(shù)據(jù)庫查詢請求A在執(zhí)行時,發(fā)現(xiàn)緩存中沒有對應的查詢結(jié)果,則它會立即被數(shù)據(jù)庫執(zhí)行,也即進行查詢數(shù)據(jù)庫的操作,得到查詢結(jié)果;但是,如果執(zhí)行過程中有新的查詢Al被提交,不論Al請求的內(nèi)容與A請求的內(nèi)容是否相同,Al同樣也會立即得到執(zhí)行,這樣就造成在A與Al請求相同時,兩個請求都會被執(zhí)行,并且直到A查詢完成并緩存結(jié)果,后續(xù)的新請求才能利用緩存內(nèi)容。也就是說,必須等到至少有一個查詢返回查詢結(jié)果并存入緩存中,才能使后續(xù)的查詢能夠利用緩存提升性能;而如果在第一個查詢結(jié)果返回前,又同時發(fā)生了其他同樣的查詢,由于無緩存可用,所有的查詢都會從頭開始執(zhí)行,而實際上查詢的內(nèi)容卻是一樣的,這顯然增加了數(shù)據(jù)庫系統(tǒng)的負擔。
[0026]為此,本申請實施例提供了一種查詢數(shù)據(jù)的方法,參見圖1,該方法可以包括以下步驟:
[0027]SlOl:攔截當前查詢請求;
[0028]在本申請實施例中,可以在服務器端對查詢請求進行攔截操作,也即,當接收到一個數(shù)據(jù)庫查詢請求之后,不是直接將其提交到數(shù)據(jù)庫進行查詢,而是首先進行一些判斷處理操作,之后再確定是否需要提交到數(shù)據(jù)庫進行查詢。
[0029]S102:判斷是否存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作;
[0030]具體在進行判斷操作時,可以首先判斷緩存中是否已經(jīng)存在與該查詢請求相關(guān)的查詢結(jié)果,如果存在,則直接從緩存中取出查詢結(jié)果返回即可。如果緩存中還沒有查詢結(jié)果,本申請實施例不是直接將查詢請求提交到數(shù)據(jù)庫進行查詢操作,而是進一步判斷一下是否存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作,如果存在,則不再將該請求提交到數(shù)據(jù)庫進行查詢,直接等待當前正在執(zhí)行的查詢請求的查詢結(jié)果即可,這樣可以減少對數(shù)據(jù)庫的訪問,減輕數(shù)據(jù)庫的負擔。
[0031]具體地,為了在攔截到一個查詢請求時,判斷出是否存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作,本申請實施例可以在緩存中保存正在執(zhí)行的查詢請求的信息,例如校驗信息,該校驗信息可以是對應查詢語句的簽名信息(例如,MD5值等等),這樣在接收到新的查詢請求之后,就可以首先計算當前查詢請求的查詢語句的簽名信息,得到當前查詢請求的校驗信息,并判斷緩存中是否存在與當前查詢請求的校驗信息匹配的內(nèi)容,如果存在,則確定存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行。
[0032]也就是說,在攔截到一個查詢請求之后,可以首先根據(jù)該查詢請求的查詢語句做MD5簽名,算出信息摘要(diges t)字符串,然后判斷緩存中是否存在與該diges t字符串匹配的內(nèi)容,如果不存在,則證明沒有相同的查詢請求正在執(zhí)行,進而,就可以將該查詢請求對應的digest字符串保存在緩存中,例如,JAVA里面具體可以利用并發(fā)哈希表(ConcurrentHashMap)來保存diges t與查詢語句的映射,這樣就可以將該查詢請求提交到數(shù)據(jù)庫執(zhí)行查詢操作。在后續(xù)如果再有相同的查詢請求被攔截到時,就可以利用計算出新的查詢請求的digest字符串,然后通過與緩存中保存的內(nèi)容進行比較,就可以判斷出存在相同的查詢請求正在執(zhí)行數(shù)據(jù)庫查詢操作。
[0033]需要說明的是,對于各個相同的查詢請求而言,只需要在第一個查詢請求被提交到數(shù)據(jù)庫進行查詢操作時,向緩存中寫入查詢請求的校驗信息,后續(xù)的查詢請求再被攔截到時,如果緩存中存在與其校驗信息相同的內(nèi)容,則不需要再重新寫入緩存,也不需要執(zhí)行數(shù)據(jù)庫查詢操作。
[0034]另外需要說明的是,查詢請求的查詢語句一般是某種具有特定規(guī)則組合的文本,也有少數(shù)是二進制數(shù)據(jù)。因此,可以基于整個查詢語句做MD5簽名,算出digest字符串。根據(jù)MD5的原理,可以保證在查詢語句相同的情況下,得到的digest字符串是相同的,因此,如果發(fā)現(xiàn)兩個查詢請求對應的digest字符串相同,就可以證明兩個查詢請求具有相同的查詢語句,也就是說,這兩個查詢請求是相同的。
[0035]當然,在實際應用中,還可以有其他的判斷兩個查詢請求是否相同的實現(xiàn)方式,例如,直接在緩存中保存查詢語句,或者,對查詢語句進行其他的摘要處理,保存得到的摘要信息,等等,這里不再一一詳述。
[0036]S103:如果是,則阻塞所述當前查詢請求;
[0037]如果發(fā)現(xiàn)存在與當前查詢查詢請求相同的查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作,則可以將當前查詢請求阻塞,不再將其提交到數(shù)據(jù)庫進行查詢,而是等待其他相同查詢請求的查詢結(jié)果。也就是說,對于相同的查詢請求而言,執(zhí)行的數(shù)據(jù)庫查詢操作都是相同的,因此,只要其中一個執(zhí)行具體的查詢數(shù)據(jù)庫的操作即可,不需要重復提交。其中,所謂的將當前查詢請求阻塞,相當于將對應的程序轉(zhuǎn)移到另一個對象上等待正在執(zhí)行的查詢請求的查詢結(jié)果。當然,在一個查詢請求執(zhí)行查詢的過程中,可能攔截到了多個與之相同的查詢請求,此時可將這些查詢請求全部阻塞,直到該查詢請求得到查詢結(jié)果之后,再通知各個相同的查詢請求對應的發(fā)起方到來提取相應的查詢結(jié)果。
[0038]當然,如果判斷出不存在與當前查詢請求相同的查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作,則可以將該當前查詢請求提交到數(shù)據(jù)庫執(zhí)行具體的查詢操作。同時,還可以在緩存中保存該當前查詢請求的校驗信息,這樣,如果在該當前查詢請求執(zhí)行數(shù)據(jù)庫查詢操作的過程中,又攔截到了新的查詢請求,就可以通過比對新的查詢請求的校驗信息與緩存中的信息,來判斷新的查詢請求是否與當前查詢請求相同,以此類推。
[0039]S104:待所述歷史查詢請求執(zhí)行完成后,利用其查詢結(jié)果向所述當前查詢請求返回查詢結(jié)果。
[0040]當正在執(zhí)行查詢數(shù)據(jù)庫操作的查詢請求獲得查詢結(jié)果之后,就可以首先將查詢結(jié)果保存在緩存中,在保存時,可以以該查詢請求的校驗信息作為鍵值。并通知其他各個相同查詢請求的發(fā)起方到緩存中來提取查詢結(jié)果。因此,對于被阻塞的查詢請求而言,在收到通知消息之后,就意味著之前正在執(zhí)行查詢數(shù)據(jù)庫操作的查詢請求已經(jīng)完成查詢,因此,就可以到緩存中找到相應的鍵值對應的查詢結(jié)果即可。
[0041 ] 可見,在本申請實施例中,在攔截到一個數(shù)據(jù)庫查詢請求之后,可以首先判斷是否存在相同的查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作,如果存在,則可以將該當前查詢請求阻塞,不再將其提交到數(shù)據(jù)庫進行查詢,等到正在執(zhí)行查詢數(shù)據(jù)庫操作的查詢請求獲得查詢結(jié)果之后,再利用該查詢結(jié)果向當前查詢請求返回查詢結(jié)果。因此,在實現(xiàn)過程中,不會出現(xiàn)在一次查詢數(shù)據(jù)庫操作正在執(zhí)行的過程中,又有相同的查詢請求重復提交到數(shù)據(jù)庫的情況,因此,減輕了數(shù)據(jù)庫的訪問負擔,有利于提高查詢效率。
[0042]如前文所述,為了能夠判斷出兩個查詢請求是否相同,可以在第一個查詢請求提交到數(shù)據(jù)庫進行查詢時,在緩存中保存對應的校驗信息,然后第二個查詢請求被攔截到之后,就可以通過比對校驗信息,判斷兩者是否相同。但是,在實際應用中,將校驗信息寫入緩存也需要一定的時間,并且現(xiàn)在的硬件環(huán)境中往往存在多個內(nèi)核共存的情況,使得多個指令可以并行處理,兩個查詢請求可能會在兩個內(nèi)核中并行處理,因此,在按照本申請的上述方法實現(xiàn)數(shù)據(jù)查詢的過程中,可能存在以下情況:兩個查詢請求到達的時間間隔可能只是毫秒級,甚至更短,這樣,當一個查詢請求A將其校驗信息寫入到緩存的過程中(尚未完全寫入),另一個查詢請求B可能就已經(jīng)被攔截到;此時,查詢請求B在訪問緩存時,就會發(fā)現(xiàn),緩存中不存在與該查詢請求B相同的查詢請求,因此,就可能也會再針對該查詢請求B執(zhí)行將校驗信息寫入緩存的操作,并將該查詢請求B也提交到數(shù)據(jù)庫進行查詢,這樣,就仍然可能出現(xiàn)一個查詢請求正在數(shù)據(jù)庫中查詢的過程中,又有一個相同的查詢請求被提交到數(shù)據(jù)庫進行查詢的現(xiàn)象。
[0043]為了避免上述情況的發(fā)生,進一步降低數(shù)據(jù)庫的負擔,提高數(shù)據(jù)查詢的效率,在單機情況下,可以通過一定的機制來保證各個查詢請求在寫緩存事務上的原子性。所謂的原子性,就是指一個事務要么完全被執(zhí)行,要么完全不被執(zhí)行,不會出現(xiàn)在一個事務尚未被完全執(zhí)行的過程中,被插入另一個事務的現(xiàn)象。具體實現(xiàn)時,JAVA程序中可以利用某個JAVA對象加鎖,只有取得該鎖之后,才能執(zhí)行后續(xù)步驟。語言層面的鎖可以由操作系統(tǒng)來保證,足以確保兩個查詢請求A和B不會同時獲取到鎖,從而就給查詢請求A、B安排了先后順序,防止了同時提交。當查詢請求A完成某操作之后,再解鎖。查詢請求B完成某操作之后,也解鎖,如果有更多的查詢請求,都做類似處理。當然,如果數(shù)據(jù)庫被部署在分布式環(huán)境下,可以使用zookeeper之類的分布式鎖來解決。
[0044]具體實現(xiàn)時,每攔截到一個查詢請求,都可以首先嘗試去鎖定一個指定的計數(shù)器對象,只有在鎖定成功的情況下,才能訪問緩存,在訪問緩存時,如果發(fā)現(xiàn)緩存中存在與自己的校驗信息相匹配的內(nèi)容,則可以阻塞自身以等待歷史查詢請求完成的通知;如果發(fā)現(xiàn)緩存中不存在與自己的校驗信息相匹配的內(nèi)容,則可以執(zhí)行將自己的校驗信息寫入緩存的操作,在全部寫入完成之后,再解除對計數(shù)器對象的鎖定。只有在一個查詢請求解除鎖定之后,其他的查詢請求才能鎖定成功,只有在鎖定成功之后才能訪問緩存。這樣,對于后續(xù)的查詢請求而言,就算在前一個查詢請求尚未完成將校驗信息寫入到緩存的操作時,就已經(jīng)被攔截到,也會因為無法成功鎖定而無法訪問緩存,進而也不會將其提交到數(shù)據(jù)庫進行查詢。因此,也就保證了即使在非常短的時間內(nèi)接收到了多個相同的查詢請求,也只有一個查詢請求會被提交到數(shù)據(jù)庫執(zhí)行查詢操作,其他的查詢請求都只需等待其查詢結(jié)果即可。
[0045]例如,首先攔截到了查詢請求A,如果在此之前尚未接收到與之相同的查詢請求,則一定被會成功鎖定,計算出的MD5簽名是digest,此時,查詢緩存也會發(fā)現(xiàn),緩存中并不存在與該digest相匹配的內(nèi)容,因此,就可以在緩存中保存以下內(nèi)容:〈digest, SQL_A>,并將該查詢請求A提交到數(shù)據(jù)庫進行查詢操作。如果在攔截到查詢請求A之后的很短時間內(nèi),又攔截到了查詢請求B,并且查詢請求B =查詢請求A,但是,查詢請求B被攔截到后,在嘗試鎖定執(zhí)行的計數(shù)器對象時,會發(fā)現(xiàn)無法鎖定成功,因為已經(jīng)被查詢請求A鎖定,直到將查詢請求A的digest等內(nèi)容完全寫入到緩存中之后,才會解除鎖定,此時,查詢請求B才會鎖定成功。查詢請求B鎖定成功之后,就可以計算出查詢請求B的MD5簽名,并可以查詢緩存,由于查詢請求B =查詢請求A,所以查詢請求B的MD5簽名也是diges t,所以查詢請求B會看到緩存里面有〈digest,SQL_A>這條記錄存在,因此,就不會再將查詢請求B提交到數(shù)據(jù)庫。雖然此時查詢請求A對應的數(shù)據(jù)庫查詢操作尚未執(zhí)行完畢,緩存中尚未有對應的查詢結(jié)果,查詢請求B知道已經(jīng)有同樣的查詢正在執(zhí)行,因此,它自己可以放棄執(zhí)行,直接等待查詢請求A的查詢結(jié)果。
[0046]在實際應用中,一段時間內(nèi)發(fā)生的不同的數(shù)據(jù)庫查詢數(shù)量可能成千上萬,全部都將查詢結(jié)果長時間緩存起來成本很高,因此,在應用了本申請?zhí)峁┑纳鲜龇桨钢螅趯Σ樵兘Y(jié)果進行緩存時,可以采用如下優(yōu)選方式:如果查詢請求A被提交到數(shù)據(jù)庫之后,在執(zhí)行查詢的過程中又收到了與該查詢請求A相同的查詢請求B、C、D,則在將查詢結(jié)果返回給查詢請求A、B、C、D之后,就可以將〈digest,SQL_A>這條記錄從緩存中刪除,并將對應的查詢結(jié)果也刪除。這樣,如果后續(xù)又接收到新的查詢請求E,并且也與查詢請求A相同,則由于緩存中已經(jīng)不再保存有查詢請求A的查詢結(jié)果,因此,仍然將查詢請求E提交到數(shù)據(jù)庫進行查詢。如果在查詢的過程中又接收到相同的查詢請求F、G,就可以將查詢請求E的查詢結(jié)果返回給查詢請求F、G的發(fā)起方。
[0047]當然,在實際應用中,在前述情況下,關(guān)于查詢請求A的查詢結(jié)果,也可以選擇保留一段時間供后續(xù)同樣的查詢調(diào)用。但數(shù)據(jù)庫中的數(shù)據(jù)更新速度一般比較快,為了保證查詢到的數(shù)據(jù)盡可能地跟隨數(shù)據(jù)庫的更新,都可以采用前述方式,也即查詢請求A在獲得查詢結(jié)果之后,只要在該查詢請求A在查詢數(shù)據(jù)庫過程中接收到的新的相同查詢請求都獲得查詢結(jié)果之后,就可以將查詢結(jié)果從緩存中刪除,后續(xù)再有相同的查詢請求時,也重新到數(shù)據(jù)庫中查詢,不再使用之前的查詢結(jié)果。這樣可以最大限度的減少誤差,提升數(shù)據(jù)準確性。如果確實需要緩存一段時間,可以使用常規(guī)的緩存方案來對查詢結(jié)果單獨緩存。
[0048]按照本申請實施例中方案,如果在查詢請求A執(zhí)行數(shù)據(jù)庫查詢的過程中,又接收到了查詢請求B、C、D,則需要在將查詢結(jié)果返回給查詢請求A、B、C、D之后,才會將此次的查詢結(jié)果刪除。為了保證在刪除查詢結(jié)果之前,查詢請求A、B、C、D都已經(jīng)獲得了查詢結(jié)果,本申請實施例可以在一個查詢請求被提交到數(shù)據(jù)庫執(zhí)行查詢操作時,為該查詢請求關(guān)聯(lián)一個計數(shù)器,在該查詢請求執(zhí)行數(shù)據(jù)庫查詢的過程中,每次截獲到與之相同的查詢請求,均將該計數(shù)器的值增加一個計數(shù)單位,直到獲取到查詢結(jié)果;在獲取到查詢結(jié)果后,每向一個查詢請求的發(fā)起方返回查詢結(jié)果,均將該計數(shù)器的值減小一個基計數(shù)單位,當計數(shù)器的值被減小到預置的值(例如為O)時,確定具有相同校驗信息的各個查詢請求均已獲得查詢結(jié)果,此時,就可以將該查詢結(jié)果刪除了。
[0049]例如,假設(shè)A、B、C三個相同的查詢請求到達應用系統(tǒng),基于上述機制,查詢請求A被提交數(shù)據(jù)庫執(zhí)行實際查詢,查詢請求B、C等待查詢請求A的查詢結(jié)果??梢詾檫@些查詢請求維護一個單獨的計數(shù)器count,查詢請求A獲取同步鎖后,count加I,查詢請求B、C獲取同步鎖后count也各自加I。這樣最終count = 3。
[0050]當查詢請求A查詢數(shù)據(jù)庫完畢后,先將查詢結(jié)果a保存在內(nèi)存變量中,再依次開始向查詢請求A、B、C的發(fā)起方返回這個查詢結(jié)果a。當查詢請求A的發(fā)起方收到查詢結(jié)果a后,count減I,查詢請求B的發(fā)起方收到查詢結(jié)果a后再減I,查詢請求C也一樣。當count=O時,查詢結(jié)果a就結(jié)束使命,可以刪除了。在整個操作的過程中,count保持原子性,避免出錯。
[0051]最后需要說明的是,本申請實施例相當于在普通的用戶函數(shù)基礎(chǔ)上包裝了一層,加上了對查詢請求的攔截、判重、緩存、計數(shù)、查詢結(jié)果緩存、通知返回等機制,最終達到提高查詢效率、降低數(shù)據(jù)庫負擔的目的。
[0052]為了更好地理解本申請實施例提供的上述方案,下面通過一個實際應用中的例子進行更為詳細的介紹。參見圖2,該方法可以包括以下步驟:
[0053]S201:攔截到查詢請求A ;
[0054]S202:獲取查詢請求A的查詢語句;
[0055]S203:嘗試鎖定指定的對象;如果鎖定不成功,則每隔預置的時間間隔返回到該步驟新進行嘗試,或者,也可以利用程序語言本身的特性先阻塞,然后等待操作系統(tǒng)調(diào)度;
[0056]S204:如果鎖定成功,則計算查詢請求A的查詢語句的唯一性標識a,例如MD5簽名信息等;
[0057]S205:讀取緩存,判斷標識a是否存在在緩存中;如果是,則進入步驟S206,否則進入步驟S211 ;
[0058]S206:取出與標識a關(guān)聯(lián)的計數(shù)器countA,并將countA的值原子性地加I ;
[0059]S207:等待與countA相關(guān)的通知消息;
[0060]S208:接收到通知消息之后,從緩存中取出標識a對應的查詢結(jié)果,并將countA的值原子性地減I ;
[0061]S209:判斷countA的值是否為0,如果是,則進入步驟S210,否則進入步驟S217 ;[0062]S210:刪除與標識a相關(guān)的查詢結(jié)果;
[0063]S211:原子性地將標識a保存在緩存中,并關(guān)聯(lián)一個值為O的計數(shù)器countA ;
[0064]S212:判斷是否保存成功,如果是,進入步驟S213,否則進入步驟S206 ;
[0065]S213:將查詢請求A提交到數(shù)據(jù)庫進行查詢;
[0066]S214:以標識a為鍵值將查詢結(jié)果保存在緩存中;
[0067]S215:通知所有標識為a的查詢請求發(fā)起方到緩存中提取查詢結(jié)果;
[0068]S216:原子性地刪除緩存中的標識a,但不回收計數(shù)器countA ;
[0069]S217:向查詢請求的發(fā)起方返回查詢結(jié)果。
[0070]與本申請實施例提供的數(shù)據(jù)查詢方法相對應,本申請實施例還提供了一種數(shù)據(jù)查詢裝置參見圖3,該裝置可以包括:
[0071]請求攔截單元301,用于攔截當前查詢請求;
[0072]判斷單元302,用于判斷是否存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作;
[0073]請求阻塞單元303,用于如果判斷單元的判斷結(jié)果為是,則阻塞所述當前查詢請求;
[0074]查詢結(jié)果返回單元304,用于待所述歷史查詢請求執(zhí)行完成后,利用其查詢結(jié)果向所述當前查詢請求返回查詢結(jié)果。
[0075]具體實現(xiàn)時,該裝置還可以包括:
[0076]請求提交單元,用于如果不存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作,則將當前查詢請求提交到數(shù)據(jù)庫執(zhí)行查詢操作。
[0077]為了判斷兩個查詢請求是否相同,該裝置還可以包括:
[0078]校驗信息緩存單元,用于在緩存中保存正在執(zhí)行的查詢請求的校驗信息,所述校驗信息為對應查詢語句的簽名信息;
[0079]相應的,所述判斷單元302可以包括:
[0080]校驗信息獲取子單元,用于計算當前查詢請求的查詢語句的簽名信息,得到當前查詢請求的校驗信息;
[0081]匹配子單元,用于判斷緩存中是否存在與當前查詢請求的校驗信息匹配的內(nèi)容,如果存在,則確定存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作。
[0082]具體實現(xiàn)時,該裝置還可以包括:
[0083]查詢結(jié)果緩存單元,用于當正在執(zhí)行查詢數(shù)據(jù)庫操作的查詢請求獲取到查詢結(jié)果之后,以所述校驗信息作為鍵值,在緩存中保存查詢結(jié)果;
[0084]通知單元,用于通知具有相同校驗信息的查詢請求發(fā)起方到緩存中提取相應的查詢結(jié)果。
[0085]為了在多個相同的查詢請求在非常短的時間內(nèi)先后到達時,避免將多個查詢請求都提交到數(shù)據(jù)庫,該裝置還可以包括:
[0086]原子性保持單元,用于在查詢緩存過程中,保持各個查詢請求之間的原子性。
[0087]具體實現(xiàn)時,所述原子性保持單元可以包括:
[0088]鎖定嘗試子單元,用于攔截到所述當前查詢請求后,嘗試鎖定指定的計數(shù)器對象;
[0089]緩存查詢子單元,用于如果鎖定成功,則查詢緩存中是否存在與攔截到的查詢請求的校驗信息匹配的內(nèi)容;
[0090]阻塞子單元,用于如果存在,則確定存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行,并阻塞自身以等待歷史查詢請求完成的通知;
[0091]鎖定解除子單元,用于如果不存在,則將該當前查詢請求的校驗信息寫入到緩存中,完成寫入緩存的操作之后,解除對所述指定計數(shù)器對象的鎖定,并將該當前查詢請求提交到數(shù)據(jù)庫執(zhí)行查詢操作。
[0092]為了最大限度的減少誤差,提升數(shù)據(jù)準確性,該裝置還可以包括:
[0093]刪除單元,用于當具有相同校驗信息的查詢請求都獲得查詢結(jié)果之后,從緩存中刪除該查詢結(jié)果;所述具有相同校驗信息的查詢請求為將一個查詢請求提交到數(shù)據(jù)庫進行查詢的過程中,接收到的與該查詢請求相同的查詢請求。
[0094]為了有效的判斷出各個查詢請求是否均以獲得查詢結(jié)果,該裝置還可以包括:
[0095]計數(shù)器關(guān)聯(lián)單元,用于當一個查詢請求被提交到數(shù)據(jù)庫執(zhí)行查詢操作時,為該查詢請求關(guān)聯(lián)一個計數(shù)器對象;
[0096]計數(shù)器自加單元,用于在該查詢請求執(zhí)行數(shù)據(jù)庫查詢的過程中,每次截獲到與之相同的查詢請求,均將該計數(shù)器的值增加一個計數(shù)單位,直到獲取到查詢結(jié)果;
[0097]計數(shù)器自減單元,用于在獲取到查詢結(jié)果后,每向一個查詢請求的發(fā)起方返回查詢結(jié)果,均將該計數(shù)器的值減小一個計數(shù)單位;
[0098]確定單元,用于當所述計數(shù)器的值被減小到預置的值時,確定具有相同校驗信息的各個查詢請求均已獲得查詢結(jié)果。
[0099]總之,在本申請實施例提供的上述裝置中,在攔截到一個數(shù)據(jù)庫查詢請求之后,可以首先判斷是否存在相同的查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作,如果存在,則可以將該當前查詢請求阻塞,不再將其提交到數(shù)據(jù)庫進行查詢,等到正在執(zhí)行查詢數(shù)據(jù)庫操作的查詢請求獲得查詢結(jié)果之后,再利用該查詢結(jié)果向當前查詢請求返回查詢結(jié)果。因此,在實現(xiàn)過程中,不會出現(xiàn)在一次查詢數(shù)據(jù)庫操作正在執(zhí)行的過程中,又有相同的查詢請求重復提交到數(shù)據(jù)庫的情況,因此,避免對數(shù)據(jù)庫造成不必要的負擔,有利于提高查詢效率。
[0100]通過以上的實施方式的描述可知,本領(lǐng)域的技術(shù)人員可以清楚地了解到本申請可借助軟件加必需的通用硬件平臺的方式來實現(xiàn)?;谶@樣的理解,本申請的技術(shù)方案本質(zhì)上或者說對現(xiàn)有技術(shù)做出貢獻的部分可以以軟件產(chǎn)品的形式體現(xiàn)出來,該計算機軟件產(chǎn)品可以存儲在存儲介質(zhì)中,如R0M/RAM、磁碟、光盤等,包括若干指令用以使得一臺計算機設(shè)備(可以是個人計算機,服務器,或者網(wǎng)絡(luò)設(shè)備等)執(zhí)行本申請各個實施例或者實施例的某些部分所述的方法。
[0101]本說明書中的各個實施例均采用遞進的方式描述,各個實施例之間相同相似的部分互相參見即可,每個實施例重點說明的都是與其他實施例的不同之處。尤其,對于系統(tǒng)或系統(tǒng)實施例而言,由于其基本相似于方法實施例,所以描述得比較簡單,相關(guān)之處參見方法實施例的部分說明即可。以上所描述的系統(tǒng)及系統(tǒng)實施例僅僅是示意性的,其中所述作為分離部件說明的單元可以是或者也可以不是物理上分開的,作為單元顯示的部件可以是或者也可以不是物理單元,即可以位于一個地方,或者也可以分布到多個網(wǎng)絡(luò)單元上??梢愿鶕?jù)實際的需要選擇其中的部分或者全部模塊來實現(xiàn)本實施例方案的目的。本領(lǐng)域普通技術(shù)人員在不付出創(chuàng)造性勞動的情況下,即可以理解并實施。
[0102]以上對本申請所提供的查詢數(shù)據(jù)的方法及裝置,進行了詳細介紹,本文中應用了具體個例對本申請的原理及實施方式進行了闡述,以上實施例的說明只是用于幫助理解本申請的方法及其核心思想;同時,對于本領(lǐng)域的一般技術(shù)人員,依據(jù)本申請的思想,在【具體實施方式】及應用范圍上均會有改變之處。綜上所述,本說明書內(nèi)容不應理解為對本申請的限制。
【權(quán)利要求】
1.一種查詢數(shù)據(jù)的方法,其特征在于,包括: 攔截當前查詢請求; 判斷是否存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作; 如果是,則阻塞所述當前查詢請求; 待所述歷史查詢請求執(zhí)行完成后,利用其查詢結(jié)果向所述當前查詢請求返回查詢結(jié)果O
2.根據(jù)權(quán)利要求1所述的方法,其特征在于,還包括: 如果不存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作,則將當前查詢請求提交到數(shù)據(jù)庫執(zhí)行查詢操作。
3.根據(jù)權(quán)利要求1所述的方法,其特征在于,還包括: 在緩存中保存正在執(zhí)行的查詢請求的校驗信息,所述校驗信息為對應查詢語句的簽名信息; 所述判斷是否存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作包括: 計算當前查詢請求的查詢語句的簽名信息,得到當前查詢請求的校驗信息; 判斷緩存中是否存在與當前查詢請求的校驗信息匹配的內(nèi)容,如果存在,則確定存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作。
4.根據(jù)權(quán)利要求3所述的方法,其特征在于,還包括: 當正在執(zhí)行查詢數(shù)據(jù)庫操作的查詢請求獲取到查詢結(jié)果之后,以所述校驗信息作為鍵值,在緩存中保存查詢結(jié)果; 通知具有相同校驗信息的查詢請求發(fā)起方到緩存中提取相應的查詢結(jié)果。
5.根據(jù)權(quán)利要求3或4所述的方法,其特征在于,還包括: 在查詢緩存過程中,保持各個查詢請求之間的原子性。
6.根據(jù)權(quán)利要求5所述的方法,其特征在于,所述在查詢緩存過程中,保持各個查詢請求之間的原子性包括: 攔截到所述當前查詢請求后,嘗試鎖定指定的計數(shù)器對象; 如果鎖定成功,則查詢緩存中是否存在與攔截到的查詢請求的校驗信息匹配的內(nèi)容;如果存在,則確定存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行,并阻塞自身以等待歷史查詢請求完成的通知; 如果不存在,則將該當前查詢請求的校驗信息寫入到緩存中,完成寫入緩存的操作之后,解除對所述計數(shù)器對象的鎖定,并將該當前查詢請求提交到數(shù)據(jù)庫執(zhí)行查詢操作。
7.根據(jù)權(quán)利要求1所述的方法,其特征在于,還包括: 當具有相同校驗信息的查詢請求都獲得查詢結(jié)果之后,從緩存中刪除該查詢結(jié)果;所述具有相同校驗信息的查詢請求為將一個查詢請求提交到數(shù)據(jù)庫進行查詢的過程中,接收到的與該查詢請求相同的查詢請求。
8.根據(jù)權(quán)利要求7所述的方法,其特征在于,還包括: 當一個查詢請求被提交到數(shù)據(jù)庫執(zhí)行查詢操作時,為該查詢請求關(guān)聯(lián)一個計數(shù)器對象; 在該查詢請求執(zhí)行數(shù)據(jù)庫查詢的過程中,每次截獲到與之相同的查詢請求,均將該計數(shù)器的值增加一個計數(shù)單位,直到獲取到查詢結(jié)果; 在獲取到查詢結(jié)果后,每向一個查詢請求的發(fā)起方返回查詢結(jié)果,均將該計數(shù)器的值減小一個計數(shù)單位; 當所述計數(shù)器的值被減小到預置的值時,確定具有相同校驗信息的各個查詢請求均已獲得查詢結(jié)果。
9.一種查詢數(shù)據(jù)的裝置,其特征在于,包括: 請求攔截單元,用于攔截當前查詢請求; 判斷單元,用于判斷是否存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作; 請求阻塞單元,用于如果判斷單元的判斷結(jié)果為是,則阻塞所述當前查詢請求; 查詢結(jié)果返回單元,用于待所述歷史查詢請求執(zhí)行完成后,利用其查詢結(jié)果向所述當前查詢請求返回查詢結(jié)果。
10.根據(jù)權(quán)利要求9所述的裝置,其特征在于,還包括: 請求提交單元,用于如果不存在與該當前查詢請求相同的歷史查詢請求正在執(zhí)行查詢數(shù)據(jù)庫的操作,則將當前查詢請求提交到數(shù)據(jù)庫執(zhí)行查詢操作。
【文檔編號】G06F17/30GK104035923SQ201310067958
【公開日】2014年9月10日 申請日期:2013年3月4日 優(yōu)先權(quán)日:2013年3月4日
【發(fā)明者】周劍, 周宇 申請人:阿里巴巴集團控股有限公司