最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java實(shí)現(xiàn)cassandra高級(jí)操作之分頁(yè)實(shí)例(有項(xiàng)目具體需求)

 更新時(shí)間:2017年04月01日 08:50:36   作者:youzhibing2904  
這篇文章主要介紹了java實(shí)現(xiàn)cassandra高級(jí)操作之分頁(yè)實(shí)例(有項(xiàng)目具體需求),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。

上篇博客講到了cassandra的分頁(yè),相信大家會(huì)有所注意:下一次的查詢依賴上一次的查詢(上一次查詢的最后一條記錄的全部主鍵),不像mysql那樣靈活,所以只能實(shí)現(xiàn)上一頁(yè)、下一頁(yè)這樣的功能,不能實(shí)現(xiàn)第多少頁(yè)那樣的功能(硬要實(shí)現(xiàn)的話性能就太低了)。

我們先看看驅(qū)動(dòng)官方給的分頁(yè)做法

如果一個(gè)查詢得到的記錄數(shù)太大,一次性返回回來(lái),那么效率非常低,并且很有可能造成內(nèi)存溢出,使得整個(gè)應(yīng)用都奔潰。所以了,驅(qū)動(dòng)對(duì)結(jié)果集進(jìn)行了分頁(yè),并返回適當(dāng)?shù)哪骋豁?yè)的數(shù)據(jù)。

一、設(shè)置抓取大小(Setting the fetch size)

抓取大小指的是一次從cassandra獲取到的記錄數(shù),換句話說(shuō),就是每一頁(yè)的記錄數(shù);我們能夠在創(chuàng)建cluster實(shí)例的時(shí)候給它的fetch size指定一個(gè)默認(rèn)值,如果沒(méi)有指定,那么默認(rèn)是5000

// At initialization:
Cluster cluster = Cluster.builder()
  .addContactPoint("127.0.0.1")
  .withQueryOptions(new QueryOptions().setFetchSize(2000))
  .build();

// Or at runtime:
cluster.getConfiguration().getQueryOptions().setFetchSize(2000);

另外,statement上也能設(shè)置fetch size

Statement statement = new SimpleStatement("your query");
statement.setFetchSize(2000);

如果statement上設(shè)置了fetch size,那么statement的fetch size將起作用,否則則是cluster上的fetch size起作用。

注意:設(shè)置了fetch size并不意味著cassandra總是返回準(zhǔn)確的結(jié)果集(等于fetch size),它可能返回比f(wàn)etch size稍微多一點(diǎn)或者少一點(diǎn)的結(jié)果集。

二、結(jié)果集迭代

fetch size限制了每一頁(yè)返回的結(jié)果集的數(shù)量,如果你迭代某一頁(yè),驅(qū)動(dòng)會(huì)在后臺(tái)自動(dòng)的抓取下一頁(yè)的記錄。如下例,fetch size = 20:

 

默認(rèn)情況下,后臺(tái)自動(dòng)抓取發(fā)生在最后一刻,也就是當(dāng)某一頁(yè)的記錄被迭代完的時(shí)候。如果需要更好的控制,ResultSet接口提供了以下方法:

getAvailableWithoutFetching() and isFullyFetched() to check the current state;

fetchMoreResults() to force a page fetch;

以下是如何使用這些方法提前預(yù)取下一頁(yè),以避免在某一頁(yè)迭代完后才抓取下一頁(yè)造成的性能下降:

ResultSet rs = session.execute("your query");
for (Row row : rs) {
  if (rs.getAvailableWithoutFetching() == 100 && !rs.isFullyFetched())
    rs.fetchMoreResults(); // this is asynchronous
  // Process the row ...
  System.out.println(row);
}

三、保存并重新使用分頁(yè)狀態(tài)

有時(shí)候,將分頁(yè)狀態(tài)保存起來(lái),對(duì)以后的恢復(fù)是非常有用的,想象一下:有一個(gè)無(wú)狀態(tài)Web服務(wù),顯示結(jié)果列表,并顯示下一頁(yè)的鏈接,當(dāng)用戶點(diǎn)擊這個(gè)鏈接的時(shí)候,我們需要執(zhí)行與之前完全相同的查詢,除了迭代應(yīng)該從上一頁(yè)停止的位置開始;相當(dāng)于記住了上一頁(yè)迭代到了哪了,那么下一頁(yè)從這里開始即可。

為此,驅(qū)動(dòng)程序會(huì)暴露一個(gè)PagingState對(duì)象,該對(duì)象表示下一頁(yè)被提取時(shí)我們?cè)诮Y(jié)果集中的位置。

ResultSet resultSet = session.execute("your query");
// iterate the result set...
PagingState pagingState = resultSet.getExecutionInfo().getPagingState();

// PagingState對(duì)象可以被序列化成字符串或字節(jié)數(shù)組
String string = pagingState.toString();
byte[] bytes = pagingState.toBytes();

PagingState對(duì)象被序列化后的內(nèi)容可以持久化存儲(chǔ)起來(lái),也可用作分頁(yè)請(qǐng)求的參數(shù),以備后續(xù)再次被利用,反序列化成對(duì)象即可:

PagingState.fromBytes(byte[] bytes);
PagingState.fromString(String str);

請(qǐng)注意,分頁(yè)狀態(tài)只能使用完全相同的語(yǔ)句重復(fù)使用(相同的查詢,相同的參數(shù))。而且,它是一個(gè)不透明的值,只是用來(lái)存儲(chǔ)一個(gè)可以被重新使用的狀態(tài)值,如果嘗試修改其內(nèi)容或?qū)⑵涫褂迷诓煌恼Z(yǔ)句上,驅(qū)動(dòng)程序會(huì)拋出錯(cuò)誤。

具體我們來(lái)看下代碼,下例是模擬頁(yè)面分頁(yè)的請(qǐng)求,實(shí)現(xiàn)遍歷teacher表中的全部記錄:

接口:

import java.util.Map;

import com.datastax.driver.core.PagingState;

public interface ICassandraPage
{
  Map<String, Object> page(PagingState pagingState);

}

主體代碼:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.datastax.driver.core.PagingState;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.SimpleStatement;
import com.datastax.driver.core.Statement;
import com.huawei.cassandra.dao.ICassandraPage;
import com.huawei.cassandra.factory.SessionRepository;
import com.huawei.cassandra.model.Teacher;

public class CassandraPageDao implements ICassandraPage
{
  private static final Session session = SessionRepository.getSession();
  
  private static final String CQL_TEACHER_PAGE = "select * from mycas.teacher;";
  
  @Override
  public Map<String, Object> page(PagingState pagingState)
  {
    final int RESULTS_PER_PAGE = 2;
    Map<String, Object> result = new HashMap<String, Object>(2);
    List<Teacher> teachers = new ArrayList<Teacher>(RESULTS_PER_PAGE);

    Statement st = new SimpleStatement(CQL_TEACHER_PAGE);
    st.setFetchSize(RESULTS_PER_PAGE);
    
    // 第一頁(yè)沒(méi)有分頁(yè)狀態(tài)
    if (pagingState != null)
    {      
      st.setPagingState(pagingState);
    }
    
    ResultSet rs = session.execute(st);
    result.put("pagingState", rs.getExecutionInfo().getPagingState());
    
    //請(qǐng)注意,我們不依賴RESULTS_PER_PAGE,因?yàn)閒etch size并不意味著cassandra總是返回準(zhǔn)確的結(jié)果集
    //它可能返回比f(wàn)etch size稍微多一點(diǎn)或者少一點(diǎn),另外,我們可能在結(jié)果集的結(jié)尾
    int remaining = rs.getAvailableWithoutFetching();
    for (Row row : rs)
    {
      Teacher teacher = this.obtainTeacherFromRow(row);
      teachers.add(teacher);
      
      if (--remaining == 0) 
      {
        break;
      }
    }
    result.put("teachers", teachers);
    return result;
  }

  private Teacher obtainTeacherFromRow(Row row)
  {
    Teacher teacher = new Teacher();
    teacher.setAddress(row.getString("address"));
    teacher.setAge(row.getInt("age"));
    teacher.setHeight(row.getInt("height"));
    teacher.setId(row.getInt("id"));
    teacher.setName(row.getString("name"));
    
    return teacher;
  }
 
}

測(cè)試代碼:

import java.util.Map;

import com.datastax.driver.core.PagingState;
import com.huawei.cassandra.dao.ICassandraPage;
import com.huawei.cassandra.dao.impl.CassandraPageDao;

public class PagingTest
{
  
  public static void main(String[] args)
  {
    ICassandraPage cassPage = new CassandraPageDao();
    Map<String, Object> result = cassPage.page(null);
    PagingState pagingState = (PagingState) result.get("pagingState");
    System.out.println(result.get("teachers"));
    while (pagingState != null)
    {
      // PagingState對(duì)象可以被序列化成字符串或字節(jié)數(shù)組
      System.out.println("==============================================");
      result = cassPage.page(pagingState);
      pagingState = (PagingState) result.get("pagingState");
      System.out.println(result.get("teachers"));
    }
  }
  
}

我們來(lái)看看Statement的setPagingState(pagingState)方法:

四、偏移查詢

保存分頁(yè)狀態(tài),能夠保證從某一頁(yè)移動(dòng)到下一頁(yè)很好地運(yùn)行(也可以實(shí)現(xiàn)上一頁(yè)),但是它不滿足隨機(jī)跳躍,比如直接跳到第10頁(yè),因?yàn)槲覀儾恢赖?0頁(yè)的前一頁(yè)的分頁(yè)狀態(tài)。像這樣需要偏移查詢的特點(diǎn),并不被cassandra原生支持,理由是偏移查詢效率低下(性能與跳過(guò)的行數(shù)呈線性反比),所以cassandra官方不鼓勵(lì)使用偏移量。如果非要實(shí)現(xiàn)偏移查詢,我們可以在客戶端模擬實(shí)現(xiàn)。但是性能還是呈線性反比,也就說(shuō)偏移量越大,性能越低,如果性能在我們的接受范圍內(nèi),那還是可以實(shí)現(xiàn)的。例如,每一頁(yè)顯示10行,最多顯示20頁(yè),這就意味著,當(dāng)顯示第20頁(yè)的時(shí)候,最多需要額外的多抓取190行,但這也不會(huì)對(duì)性能造成太大的降低,所以數(shù)據(jù)量不大的話,模擬實(shí)現(xiàn)偏移查詢還是可以的。

舉個(gè)例子,假設(shè)每頁(yè)顯示10條記錄,fetch size 是50,我們請(qǐng)求第12頁(yè)(也就是第110行到第119行):

1、第一次執(zhí)行查詢,結(jié)果集包含0到49行,我們不需要用到它,只需要分頁(yè)狀態(tài);

2、用第一次查詢得到的分頁(yè)狀態(tài),執(zhí)行第二次查詢;

3、用第二次查詢得到的分頁(yè)狀態(tài),執(zhí)行第三次查詢。結(jié)果集包含100到149行;

4、用第三次查詢得到的結(jié)果集,先過(guò)濾掉前10條記錄,然后讀取10條記錄,最后丟棄剩下的記錄,讀取的10條記錄則是第12頁(yè)需要顯示的記錄。

我們需要嘗試著找到最佳的fetch size來(lái)達(dá)到最佳平衡:太小就意味著后臺(tái)更多的查詢;太大則意味著返回了更大的信息量以及更多不需要的行。

另外,cassandra本身不支持偏移量查詢。在滿足性能的前提下,客戶端模擬偏移量的實(shí)現(xiàn)只是一種妥協(xié)。官方建議如下:

1、使用預(yù)期的查詢模式來(lái)測(cè)試代碼,以確保假設(shè)是正確的

2、設(shè)置最高頁(yè)碼的硬限制,以防止惡意用戶觸發(fā)跳過(guò)大量行的查詢

五、總結(jié)

Cassandra對(duì)分頁(yè)的支持有限,上一頁(yè)、下一頁(yè)比較好實(shí)現(xiàn)。不支持偏移量的查詢,硬要實(shí)現(xiàn)的話,可以采用客戶端模擬的方式,但是這種場(chǎng)景最好不要用在cassandra上,因?yàn)閏assandra一般而言是用來(lái)解決大數(shù)據(jù)問(wèn)題,而偏移量查詢一旦數(shù)據(jù)量太大,性能就不敢恭維了。

在我的項(xiàng)目中,索引修復(fù)用到了cassandra的分頁(yè),場(chǎng)景如下:cassandra的表不建二級(jí)索引,用elasticsearch實(shí)現(xiàn)cassandra表的二級(jí)索引,那么就會(huì)涉及到索引的一致性修復(fù)的問(wèn)題,這里就用到了cassandra的分頁(yè),對(duì)cassandra的某張表進(jìn)行全表遍歷,逐條與elasticsearch中的數(shù)據(jù)進(jìn)行匹對(duì),若elasticsearch中不存在,則在elasticsearch中新增,若存在而又不一致,則在elasticsearch中修復(fù)。具體elasticsearch怎么樣實(shí)現(xiàn)cassandra的索引功能,在我后續(xù)博客中會(huì)專門的講解,這里就不多說(shuō)了。而在cassandra表進(jìn)行全表遍歷的時(shí)候就需要用到分頁(yè),因?yàn)楸碇袛?shù)據(jù)量太大,億級(jí)別的數(shù)據(jù)不可能一次全部加載到內(nèi)存中。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java BigDecimal基礎(chǔ)用法詳解

    Java BigDecimal基礎(chǔ)用法詳解

    Java在java.math包中提供的API類BigDecimal,用來(lái)對(duì)超過(guò)16位有效位的數(shù)進(jìn)行精確的運(yùn)算。雙精度浮點(diǎn)型變量double可以處理16位有效數(shù),但在實(shí)際應(yīng)用中,可能需要對(duì)更大或者更小的數(shù)進(jìn)行運(yùn)算和處理
    2022-06-06
  • java虛擬機(jī)jvm方法區(qū)實(shí)例講解

    java虛擬機(jī)jvm方法區(qū)實(shí)例講解

    在本篇文章里小編給大家整理的是一篇關(guān)于java虛擬機(jī)jvm方法區(qū)實(shí)例講解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2021-02-02
  • SpringBoot項(xiàng)目嵌入RocketMQ的實(shí)現(xiàn)示例

    SpringBoot項(xiàng)目嵌入RocketMQ的實(shí)現(xiàn)示例

    本文主要介紹了SpringBoot項(xiàng)目嵌入RocketMQ的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-05-05
  • 淺談spring-boot 允許接口跨域并實(shí)現(xiàn)攔截(CORS)

    淺談spring-boot 允許接口跨域并實(shí)現(xiàn)攔截(CORS)

    本篇文章主要介紹了淺談spring-boot 允許接口跨域并實(shí)現(xiàn)攔截(CORS),具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-08-08
  • 解析SpringBoot @EnableAutoConfiguration的使用

    解析SpringBoot @EnableAutoConfiguration的使用

    這篇文章主要介紹了解析SpringBoot @EnableAutoConfiguration的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Messges Queue消息隊(duì)列詳解

    Messges Queue消息隊(duì)列詳解

    這篇文章主要介紹了Messges Queue消息隊(duì)列詳解,消息隊(duì)列一般簡(jiǎn)稱為 MQ,是指利用高效可靠的消息傳遞機(jī)制進(jìn)行與平臺(tái)無(wú)關(guān)的數(shù)據(jù)交流,并基于數(shù)據(jù)通信來(lái)進(jìn)行分布式系統(tǒng)的集成,是在消息的傳輸過(guò)程中保存消息的容器,需要的朋友可以參考下
    2023-07-07
  • java獲取當(dāng)前時(shí)間并格式化代碼實(shí)例

    java獲取當(dāng)前時(shí)間并格式化代碼實(shí)例

    這篇文章主要介紹了java獲取當(dāng)前時(shí)間并格式化代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • C語(yǔ)言指針數(shù)組案例詳解

    C語(yǔ)言指針數(shù)組案例詳解

    這篇文章主要介紹了C語(yǔ)言指針數(shù)組案例詳解,本文通過(guò)案例詳細(xì)的解釋了指針與數(shù)組的初始化還有關(guān)系與應(yīng)用,需要的朋友可以參考下這篇文章
    2021-07-07
  • SpringBoot集成ElasticSearch實(shí)現(xiàn)minio文件內(nèi)容全文檢索

    SpringBoot集成ElasticSearch實(shí)現(xiàn)minio文件內(nèi)容全文檢索

    這篇文章詳細(xì)介紹了如何在Spring?Boot項(xiàng)目中集成Elasticsearch和Kibana,包括Docker安裝、中文分詞器安裝、后端代碼實(shí)現(xiàn)以及前端查詢組件封裝,需要的朋友可以參考下
    2024-11-11
  • Java函數(shù)式編程(一):你好,Lambda表達(dá)式

    Java函數(shù)式編程(一):你好,Lambda表達(dá)式

    這篇文章主要介紹了Java函數(shù)式編程(一):你好,Lambda表達(dá)式,本文講解了新老函數(shù)式編程的一些變化,需要的朋友可以參考下
    2014-09-09

最新評(píng)論

灌阳县| 永城市| 玉溪市| 汶川县| 十堰市| 虞城县| 石首市| 休宁县| 沁源县| 广南县| 巴彦县| 大冶市| 咸阳市| 苍梧县| 贵德县| 仪征市| 博乐市| 颍上县| 衢州市| 巫山县| 灌南县| 平武县| 孟州市| 云和县| 射阳县| 海淀区| 阿鲁科尔沁旗| 连城县| 遵化市| 新巴尔虎右旗| 新化县| 沙坪坝区| 彭阳县| 祁连县| 兰溪市| 山丹县| 美姑县| 天镇县| 瑞安市| 江阴市| 永善县|