Gemfire CQ 之持續(xù)查詢

站在巨人的肩膀上

  • ContinuousQuery(簡(jiǎn)稱CQ):持續(xù)查詢,是指Client可以按照OQL(Object Query Language)查詢語(yǔ)句注冊(cè)自己感興趣的event部念,而這些event將發(fā)送給Client的Listener誊稚,一旦Server有event發(fā)生扳缕,就會(huì)將此event傳遞給Client丈冬。
  • 監(jiān)聽的事件類型:update create destroy
  • CQ查詢的特性:
    能夠使用標(biāo)準(zhǔn)的OQL語(yǔ)句
    對(duì)CQ事件進(jìn)行管理
    完全整合C/S架構(gòu)
    基于數(shù)據(jù)值的訂閱
    活躍查詢執(zhí)行

一個(gè)簡(jiǎn)單的業(yè)務(wù)需求:

Client向Server訂閱監(jiān)聽年齡在15~35歲Customer之間的數(shù)據(jù):

Server

@SpringBootApplication
@CacheServerApplication(name = "GemFireContinuousQueryServer")
public class Application {

    @Bean(name = "Customers")
    PartitionedRegionFactoryBean<Long, Customer> customersRegion(GemFireCache gemfireCache) {
        PartitionedRegionFactoryBean<Long, Customer> customers = new PartitionedRegionFactoryBean<>();
        customers.setCache(gemfireCache);
        customers.setClose(false);
        customers.setPersistent(false);
        return customers;
    }
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

pom.xml 中的關(guān)鍵依賴:

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-gemfire</artifactId>
            <version>2.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.gj.demo</groupId>
            <artifactId>gemfire-common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

Client

@SpringBootApplication
@ClientCacheApplication(name = "GemFireContinuousQueryClient", subscriptionEnabled = true)
@SuppressWarnings("unused")
public class Application {
    @Bean(name = "Customers")
    ClientRegionFactoryBean<Long, Customer> customersRegion(GemFireCache gemfireCache) {
        ClientRegionFactoryBean<Long, Customer> customers = new ClientRegionFactoryBean<>();
        customers.setCache(gemfireCache);
        customers.setClose(true);
        customers.setShortcut(ClientRegionShortcut.PROXY);
        return customers;
    }

    @Bean
    ContinuousQueryListenerContainer continuousQueryListenerContainer(GemFireCache gemfireCache) {
        Region<Long, Customer> customers = gemfireCache.getRegion("/Customers");
        ContinuousQueryListenerContainer container = new ContinuousQueryListenerContainer();
        container.setCache(gemfireCache);
        container.setQueryListeners(asSet(ageQueryDefinition(customers, 15,35)));
        return container;
    }
    private ContinuousQueryDefinition ageQueryDefinition(Region<Long, Customer> customers, int 
   ageFrom,int ageTo){
        String query = String.format("SELECT * FROM /Customers c WHERE c.getAge().intValue() > %d AND c.getAge().intValue() < %d ", ageFrom,ageTo);
        return new ContinuousQueryDefinition("Young Query ",query,newQueryListener(customers,"Young Query"));
    }

    private ContinuousQueryListener newQueryListener(Region<Long, Customer> customers, String qualifier) {
        return event -> {
            System.err.printf("new order!" + event.toString());
        };
    }
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Customer:

@Region
public class Customer implements Serializable {
    private static final long serialVersionUID = -3860687524824507124L;
    private String firstname, lastname;
    private int age;
    Long id;
//此處省略了get,set方法
@Override
    public String toString() {
        return String.format("%1$s %2$s %3$s", getFirstname(), getLastname(),getAge());
    }
}

程序跑起來(lái)~

分別啟動(dòng)Server和Client,在瀏覽器傳入相關(guān)參數(shù):


server.png

查看Client的控制臺(tái)日志:


Client-Terminal.png

Client.png

至此吠勘,就是一個(gè)完整的Client向Server訂閱監(jiān)聽,收到訂閱消息的全過(guò)程居兆。

CQ查詢的數(shù)據(jù)流

當(dāng)數(shù)據(jù)條目在服務(wù)器端更新時(shí),新數(shù)據(jù)會(huì)經(jīng)過(guò)下面的步驟:
1.region條目發(fā)生變更
2.每一個(gè)事件竹伸,服務(wù)器的CQ處理框架檢查是否與運(yùn)行的CQ匹配
3.如果數(shù)據(jù)條目的變更匹配了CQ查詢泥栖,CQ事件將被發(fā)送到客戶端上的CQ監(jiān)聽器簇宽,CQ監(jiān)聽器獲得此事件。


CQ stream.png

如上圖所示:
X條目新值和舊值都匹配了CQ查詢吧享,因此查詢結(jié)果的更新的事件被發(fā)送出來(lái)魏割。
Y條目舊值匹配了,但這是查詢結(jié)果的一部分钢颂,Y條目操作為失敗 钞它,因?yàn)椴樵兘Y(jié)果被銷毀的事件被發(fā)送出來(lái)。
Z條目為新創(chuàng)殊鞭,并不匹配CQ事件遭垛,所以事件不發(fā)送。

值得注意的是操灿,CQ并不更新客戶端的Region,CQ作為CQ監(jiān)聽器的通告工具而服務(wù)锯仪,CQ監(jiān)聽器可以按照客戶應(yīng)用的要求任意編程

當(dāng)一個(gè)CQ運(yùn)行在服務(wù)器Region的時(shí)候趾盐,每一個(gè)Server條目更新線程都放在CQ查詢中庶喜,如果old value或者new value 滿足查詢條件,線程將放到CqEvent的Client隊(duì)列中去救鲤,一旦Client接受了此事件溃卡,CqEvent將被傳遞到CqListeners的onEvent方法上,如下圖所示:


CQ.png

QueryService 接口提供的方法

  • create a new CQ and specify whether it is durable

  • execute a CQ,with or without an initial set

  • list all the CQs registered by the client

  • close and stop CQs at the cache and region level

  • get a handle on CqStatistics for the client

  • CqQuery:管理持續(xù)查詢的方法蜒简,通過(guò)QueryService 創(chuàng)建瘸羡,用于開啟和停止CQ執(zhí)行,同時(shí)查詢其他與CQ想關(guān)聯(lián)的對(duì)象搓茬,such as CQ屬性犹赖,CQ統(tǒng)計(jì)和CQ狀態(tài)。

  • CqListener:用于處理持續(xù)查詢的事件卷仑。
    *CqEvent:提供了從Server發(fā)送的所有的CQ事件信息峻村,此事件被傳遞到CqListener的onEvent方法。

程序媛小白一枚锡凝,如有錯(cuò)誤粘昨,煩請(qǐng)批評(píng)指正!(#.#)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末窜锯,一起剝皮案震驚了整個(gè)濱河市张肾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌锚扎,老刑警劉巖吞瞪,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異驾孔,居然都是意外死亡芍秆,警方通過(guò)查閱死者的電腦和手機(jī)惯疙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)妖啥,“玉大人霉颠,你說(shuō)我怎么就攤上這事【J” “怎么了掉分?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)克伊。 經(jīng)常有香客問(wèn)我酥郭,道長(zhǎng),這世上最難降的妖魔是什么愿吹? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任不从,我火速辦了婚禮,結(jié)果婚禮上犁跪,老公的妹妹穿的比我還像新娘椿息。我一直安慰自己,他們只是感情好坷衍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布寝优。 她就那樣靜靜地躺著,像睡著了一般枫耳。 火紅的嫁衣襯著肌膚如雪乏矾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天迁杨,我揣著相機(jī)與錄音钻心,去河邊找鬼。 笑死铅协,一個(gè)胖子當(dāng)著我的面吹牛捷沸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播狐史,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼痒给,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了骏全?” 一聲冷哼從身側(cè)響起苍柏,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吟温,沒想到半個(gè)月后序仙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體突颊,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鲁豪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年潘悼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爬橡。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡治唤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出糙申,到底是詐尸還是另有隱情宾添,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布柜裸,位于F島的核電站缕陕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏疙挺。R本人自食惡果不足惜扛邑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望铐然。 院中可真熱鬧蔬崩,春花似錦、人聲如沸搀暑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)自点。三九已至桐罕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間桂敛,已是汗流浹背冈绊。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留埠啃,地道東北人死宣。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像碴开,于是被迫代替她去往敵國(guó)和親毅该。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353