(四)apache ignite-In-memory caching

到目前為止虽界,我們已經(jīng)介紹了Apache Ignite及其體系結構的基本功能。現(xiàn)在涛菠,是時候深入了解Apache Ignite的實現(xiàn)了莉御,并觀察它如何提高應用程序性能撇吞。在前幾章中,我們已經(jīng)討論了很多關于Ignite特性和體系結構的內(nèi)容礁叔,現(xiàn)在我們將介紹所有最重要的引爆內(nèi)存數(shù)據(jù)網(wǎng)格特性牍颈,并解釋用例,以了解應該如何以及何時使用這些特性琅关。本章的主要目標是演示如何使用Apache Ignite來加速應用程序性能而不改變代碼煮岁。IMDG或內(nèi)存數(shù)據(jù)網(wǎng)格不是內(nèi)存中的關系數(shù)據(jù)庫、NoSQL數(shù)據(jù)庫或關系數(shù)據(jù)庫涣易。但是画机,它是一個分布式鍵值存儲,可以將其想象為一個分布式分區(qū)散列映射都毒,其中集群中的每個節(jié)點都有自己的數(shù)據(jù)部分色罚。數(shù)據(jù)模型分布在單個位置或多個位置的多個服務器上。這種分布稱為數(shù)據(jù)結構账劲。這種分布式模型也稱為共享的無架構戳护。IMDG具有以下特點:

  • 所有服務器都可以在每個節(jié)點上活動。
  • 所有數(shù)據(jù)都存儲在服務器的RAM中瀑焦。
  • 可以不受干擾地添加或刪除服務器腌且,以增加可用的RAM數(shù)量。
  • 數(shù)據(jù)模型是非關系型的榛瓮,并且是基于對象的铺董。
  • 分布式應用程序是用平臺獨立語言編寫的。
  • 數(shù)據(jù)結構具有彈性禀晓,允許對單個服務器或多個服務器進行非破壞性的自動檢測和恢復精续。
    正如我們前面討論的,Apache Ignite實現(xiàn)了JCache規(guī)范來開發(fā)內(nèi)存數(shù)據(jù)網(wǎng)格粹懒。然而重付,Ignite為內(nèi)存數(shù)據(jù)網(wǎng)格提供了許多高級功能。在本章中凫乖,我們將討論以下主題:
  • Apache Ignite 作為一個 2nd 級別的cache确垫。
  • Java方法的緩存。
  • Web sessions集群帽芽。
  • Apache Ignite作為一個 big memory, off-heap memory删掀。

2nd級別緩存

通過避免昂貴的數(shù)據(jù)庫調用,將數(shù)據(jù)保持在應用程序的本地导街,第二級緩存可以提高應用程序的性能披泪。二級緩存由持久性提供程序完全管理,通常對應用程序是透明的搬瑰。也就是說付呕,應用程序在不知道緩存的情況下通過實體管理器讀取计福、寫入和提交數(shù)據(jù)。
還有基于持久性提供者(如MyBatis或Hibernate)的一級緩存徽职。第1級用于緩存當前數(shù)據(jù)庫會話中從數(shù)據(jù)庫檢索的對象象颖。當前端(web頁面或web服務)調用一個服務時,將打開一個HTTP會話并重用它姆钉,直到服務方法返回说订。在服務方法返回之前執(zhí)行的所有操作都將共享L1緩存,因此相同的對象不會從數(shù)據(jù)庫中檢索兩次潮瓶。完成數(shù)據(jù)庫會話后陶冷,從數(shù)據(jù)庫檢索的對象將不可用。在大多數(shù)持久性提供程序中毯辅,默認情況下總是啟用第1級緩存埂伦。


image.png

與第一級緩存不同,二級緩存能夠跨越數(shù)據(jù)庫會話思恐,存儲數(shù)據(jù)庫對象和查詢結果(查詢緩存)沾谜。它位于持久性提供者和數(shù)據(jù)庫之間。持久性上下文共享緩存胀莹,使第二級緩存在整個應用程序中都可用基跑。因此,由于實體被加載到共享緩存中并從共享緩存中可用描焰,因此數(shù)據(jù)庫流量大大減少媳否。因此,簡而言之荆秦,二級緩存提供了以下好處:

  1. 通過避免昂貴的數(shù)據(jù)庫調用來提高性能篱竭。
  2. 數(shù)據(jù)對應用程序保持透明。
  3. CRUD操作可以通過普通的持久性管理器函數(shù)執(zhí)行步绸。
  4. 通過使用二級緩存掺逼,您可以在不更改代碼的情況下加速應用程序的性能。

MyBatis二級緩存

在Ignite中靡努,MyBatis的第2級緩存存儲的是實體數(shù)據(jù)坪圾,而不是實體或對象本身杂瘸。數(shù)據(jù)以序列化格式存儲赚窃,看起來像hashmap苔咪,其中鍵是實體Id,值是原始值的列表漾月。
在這里,我們的目標是最小化查詢執(zhí)行時間胃珍。接下來梁肿,我們將開發(fā)一個使用MyBatis和Ignite的應用程序蜓陌,以實現(xiàn)計算性能提升。

Step1

創(chuàng)建一個java項目

mvn archetype:generate -DgroupId=com.mycookcode.bigData.ignite -DartifactId=ignite-mybatis -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

Step2

在maven配置文件中添加以下依賴:

    <dependency>
      <groupId>org.apache.ignite</groupId>
      <artifactId>ignite-core</artifactId>
      <version>${ignite.version}</version>
    </dependency>

    <dependency>
      <groupId>org.apache.ignite</groupId>
      <artifactId>ignite-spring</artifactId>
      <version>${ignite.version}</version>
    </dependency>

    <dependency>
      <groupId>org.mybatis.caches</groupId>
      <artifactId>mybatis-ignite</artifactId>
      <version>1.0.6</version>
    </dependency>

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.2</version>
    </dependency>

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.6</version>
    </dependency>


    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.12</version>
    </dependency>

在這個項目中吩蔑,我們將使用spring框架钮热,因此必須添加一些spring相關的依賴項。此外烛芬,我們還添加了MyBatis核心庫和mybatise-ignite庫隧期,以集成Apache Ignite作為二級緩存。在編譯時赘娄,Maven使用這些信息在Maven存儲庫中查找上述所有庫仆潮。Maven首先查看本地計算機上的存儲庫。如果庫不存在遣臼,它將從公共Maven存儲庫下載它們性置,并將它們存儲在本地存儲庫中。

Step3

現(xiàn)在揍堰,我們必須在項目的資源目錄中添加spring上下文XML文件鹏浅,以將其添加到java類路徑中。spring上下文文件的完整版本將類似个榕。讓我們詳細地看一下spring-core.xml文件篡石。

<!--在本節(jié)中,我們聲明了所有必需的XML名稱空間西采,我們將在這個XML配置文件中使用這些名稱空間凰萨。所有這些名稱空間和URI都是標準的spring名稱空間。-->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/cache
        http://www.springframework.org/schema/cache/spring-cache-3.1.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- Enable annotation-driven caching. -->
    <cache:annotation-driven/>

    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!-- beans -->

    <bean id="servicesBean" class="com.mycookcode.bigData.ignite.WebServices">
        <property name="dao" ref="userServicesBean"/>
    </bean>

    <!--聲明了soap服務bean和user mapper bean械馆,這個類和接口的源代碼將在稍后解釋胖眷。-->
    <bean id="userServicesBean" class="com.mycookcode.bigData.ignite.dao.UserServices">
        <property name="userMapper" ref="userMapper"/>
    </bean>


    <!--Ignite-->
    <bean id="cacheManager" class="org.apache.ignite.cache.spring.SpringCacheManager">
        <property name="configuration" ref="ignite.cfg" />
    </bean>

     <!--這是Ignite節(jié)點的主要配置部分。這里我們聲明了名為myBatisCache的緩存名稱霹崎,將緩存模式配置為分區(qū)珊搀。
     注意,緩存模式也可以復制尾菇。另外境析,我們?yōu)榫彺媾渲昧艘粋€備份副本,并啟用了緩存統(tǒng)計數(shù)據(jù)派诬。
     屬性name= " backup "value= " 1 "表示緩存項在另一個節(jié)點上總是有一個冗余副本劳淆。
     在稍后的配置中,我們添加了SPI discovery來查找集群中的節(jié)點成員默赂。
     在我們的例子中沛鸵,我們使用多播TCP/IP查找程序。如果您有自己的Ignite集群運行,不要忘記在配置文件中添加或更新IP地址曲掰,如下所示疾捍。
     -->
    <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
        <!-- Set to true to enable distributed class loading for examples, default is false. -->
        <property name="peerClassLoadingEnabled" value="false"/>
        <property name="gridName" value="TestGrid"/>
        <property name="clientMode" value="false"/>

        <property name="cacheConfiguration">
            <list>
                <bean class="org.apache.ignite.configuration.CacheConfiguration">
                    <!-- Set a cache name. -->
                    <property name="name" value="myBatisCache"/>
                    <!--<property name="atomicityMode" value="ATOMIC"/>-->
                    <!-- Set cache mode. -->
                    <property name="cacheMode" value="PARTITIONED"/>
                    <property name="backups" value="1"/>
                    <property name="statisticsEnabled" value="true" />
                </bean>
            </list>
        </property>
        <!-- Explicitly configure TCP discovery SPI to provide list of initial nodes. -->
        <property name="discoverySpi">
            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
                <property name="ipFinder">
                    <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">
                        <property name="addresses">
                            <list>
                                <!-- In distributed environment, replace with actual host IP address. -->
                                <value>127.0.0.1:47500..47509</value>
                            </list>
                        </property>
                    </bean>
                </property>
            </bean>
        </property>

    </bean>


    <!--配置了MyBatis SQL mapper bean。使用SQL session factory指定映射器接口栏妖,并在XML中添加所有SQL映射器文件的類路徑乱豆。-->
    <bean id="userMapper" autowire="byName" class="org.mybatis.spring.mapper.MapperFactoryBean">
        <property name="mapperInterface" value="com.mycookcode.bigData.ignite.mapper.UserMapper" />
        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="mapperLocations" value="classpath*:mapper/*Mapper.xml"/>
    </bean>

    <!--為MySQL服務器設置了JDBC數(shù)據(jù)源。我們還添加了帶有JDBC URL吊趾、用戶名和密碼的標準數(shù)據(jù)源連接咙鞍,沒有任何連接池。-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.mycookcode.bigData.ignite.mapper" />
    </bean>


 </beans>

Step4

現(xiàn)在趾徽,我們將添加UserMapper.xml到類路徑中续滋。注意,以下xml文件是位于絕對類路徑(/resources/mapper/ usermap.xml)中孵奶。

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mycookcode.bigData.ignite.mapper.UserMapper">
    <cache type="org.mybatis.caches.ignite.IgniteCacheAdapter" />
    <select id="getEmploee" parameterType="String" resultType="com.mycookcode.bigData.ignite.dto.Employee" useCache="true">
        SELECT * FROM emp WHERE ename = #{ename}
    </select>
</mapper>

映射器名稱空間(mapper namespace)和緩存類型是配置中最重要的部分疲酌。注意,對于每個映射器名稱空間了袁,在Ignite集群中將創(chuàng)建一個復制緩存朗恳。在這種情況下,緩存名稱將是com.mycookcode.bigData.ignite.mapper.UserMapper载绿。對于緩存類型粥诫,我們聲明了Ignite cache適配器的接口。接下來崭庸,我們添加了SQL查詢怀浆,它是參數(shù)類型和返回值的類型。我們使用非常簡單的SQL查詢來通過雇員名獲取雇員怕享。在這里执赡,我們已經(jīng)通過XML完成了所有聲明性配置。現(xiàn)在我們準備向應用程序添加業(yè)務邏輯函筋。

Step5

從文件夾腳本中執(zhí)行以下DDL和DML腳本沙合,以創(chuàng)建數(shù)據(jù)庫表,并向表中插入幾行跌帐。為了簡單起見首懈,我們使用Oracle數(shù)據(jù)庫中著名的emp和dept實體。我稍微修改了DDL/DML腳本谨敛,讓它們運行到MySQL中究履。department (dept)和employee (emp)表的結構非常簡單,它們彼此之間有一對多的關系佣盒。

create table dept(
  deptno integer,
  dname  text,
  loc    text,
  constraint pk_dept primary key (deptno)
);
create table emp(
  empno    integer,
  ename    text,
  job      text,
  mgr      integer,
  hiredate date,
  sal      integer,
  comm     integer,
  deptno   integer,
  constraint pk_emp primary key (empno),
  constraint fk_deptno foreign key (deptno) references dept (deptno)
);

Step6

既然已經(jīng)設置了項目和構建系統(tǒng)挎袜,就可以繼續(xù)創(chuàng)建web服務了顽聂。
此時肥惭,soap web服務只包含一個web方法getEmployee盯仪。

package com.mycookcode.bigData.ignite;

import com.mycookcode.bigData.ignite.dao.UserServices;
import com.mycookcode.bigData.ignite.dto.Employee;

import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService(name="BusinessRulesServices",
            serviceName = "BusinessRulesServices",
            targetNamespace = "http://com.ignite.rules/services")
public class WebServices {


    private UserServices userServices;

    @WebMethod(exclude = true)
    public void setDao(UserServices userServices){
        this.userServices = userServices;
    }

    @WebMethod(operationName = "getEmploee")
    public Employee getEmploee(String ename) {return userServices.getEmploee(ename);}
}

您可以從源代碼中獲得其他所有的類,比如DTO蜜葱。

Step7

要運行web服務全景,我們將使用帶有maven構建的one-jar插件。通過以下命令構建項目牵囤。

mvn clean install

Step8

運行web服務爸黄。

java -jar ./target/ignite-mybatis-1.0-SNAPSHOT.one-jar.jar

如果一切順利,您應該會在控制臺上看到以下日志:

image.png

web service服務運行在本地的7001端口上揭鳞】还螅可以通過這個URL web服務http://localhost:7001/invokeRules?wsdl發(fā)現(xiàn)web服務WSDL。現(xiàn)在可以使用soap客戶機調用web服務野崇,我將使用chrome瀏覽器中的開發(fā)者工具控制臺來測試服務称开。當我第一次調用服務時,調用時間大約是259毫秒乓梨,因為查詢結果還沒有在緩存中鳖轰。
image.png

再次調用Web方法。
image.png

這一次扶镀,響應時間是79毫秒蕴侣,響應速度明顯提高。MyBatis只返回Ignite緩存的結果臭觉。它幾乎是實時的響應昆雀。讓我們來看一下Ignite緩存中的緩存條目。Ignitevisor命令掃描可以幫助您找到緩存中的所有條目蝠筑。
image.png

Cache Key = org.apache.ibatis.cache.CacheKey [idHash=1538632341, hash=872929822, checksum=\
2936898376, count=6, multiplier=37, hashcode=872929822, updateList=[com.blu.imdg.mapper.Us\
erMapper.getEmploee, 0, 2147483647, SELECT * FROM emp WHERE ename = ?, KING, SqlSessionFac\
toryBean]]
Key Value = [com.blu.imdg.dto.Employee [idHash=545458831, hash=342167489, date=null, ename\ =KING, mgr=null, empno=7839, job=PRESIDENT, deptno=10, sal=5000]]

在emp表中有一些行(總共12行)忆肾,并且在字段ename上沒有任何索引。讓我們在表emp的字段ename上創(chuàng)建唯一的索引菱肖,并重新執(zhí)行服務調用客冈。

CREATE UNIQUE INDEX ename_idx ON emp (ename);

在字段ename上創(chuàng)建一個btree索引。現(xiàn)在稳强,在SOAP消息中更改雇員表的ename字段场仲,例如,F(xiàn)ORD并再次執(zhí)行web方法退疫。


image.png

現(xiàn)在的響應時間是84毫秒渠缕,你可能會認為差別不大。但是在生產(chǎn)系統(tǒng)中褒繁,將擁有數(shù)百萬行亦鳞,而不是數(shù)據(jù)庫表中的13行。此外,當表上有索引時燕差,DML操作每次都會重新索引數(shù)據(jù)庫表遭笋,這也會降低應用程序的性能。大多數(shù)時候徒探,Ignite緩存的響應時間不會改變瓦呼,因為沒有額外的開銷來消耗DB連接、SQL查詢的軟/硬解析测暗。

Calculate application speedup計算應用加速:

可以使用Amdahl's law計算應用程序的加速比央串。公式:1/((1 - Proportion speed up) + Proportion speed up / speed up)


image.png
  • P是可以并行的比例
  • S是這部分并行可以加速S倍 (S可以理解是CPU核的個數(shù),即新代碼的執(zhí)行時間為原來執(zhí)行時間的1/S)
    另外碗啄,請注意质和,對于web應用程序,系統(tǒng)應該包括瀏覽器展現(xiàn)時間和網(wǎng)絡延遲稚字。
    在使用緩存時侦另,應用程序的性能至少取決于以下兩個因素:
  • 應用程序檢索緩存數(shù)據(jù)片段的次數(shù);
  • 緩存減少了響應時間的比例。
    假設我們有一個web應用程序尉共,未加緩存的整個頁面呈現(xiàn)時間是259毫秒“担現(xiàn)在,讓我們從數(shù)據(jù)庫級緩存計算速度袄友。在我們的例子中:
  • 打開頁面時間:259毫秒殿托。
  • 數(shù)據(jù)庫時間:84毫秒。
  • 緩存檢索時間:79毫秒剧蚣。
  • 比例:84/259~32.4%
    預期的系統(tǒng)加速率應該是:
    1/((1-0.324)+0.324/(84/79))=1/(0.676+0.305)~1.01倍的系統(tǒng)加速支竹。
    雖然1.01倍的系統(tǒng)速度不是很令人印象深刻,但在生產(chǎn)環(huán)境中鸠按,緩存后的結果將與沒緩存前的結果有很大不同礼搁。
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市目尖,隨后出現(xiàn)的幾起案子馒吴,更是在濱河造成了極大的恐慌,老刑警劉巖瑟曲,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饮戳,死亡現(xiàn)場離奇詭異,居然都是意外死亡洞拨,警方通過查閱死者的電腦和手機扯罐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烦衣,“玉大人歹河,你說我怎么就攤上這事掩浙。” “怎么了秸歧?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵厨姚,是天一觀的道長。 經(jīng)常有香客問我寥茫,道長,這世上最難降的妖魔是什么矾麻? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任纱耻,我火速辦了婚禮,結果婚禮上险耀,老公的妹妹穿的比我還像新娘弄喘。我一直安慰自己,他們只是感情好甩牺,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布蘑志。 她就那樣靜靜地躺著,像睡著了一般贬派。 火紅的嫁衣襯著肌膚如雪急但。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天搞乏,我揣著相機與錄音波桩,去河邊找鬼。 笑死请敦,一個胖子當著我的面吹牛镐躲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播侍筛,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼萤皂,長吁一口氣:“原來是場噩夢啊……” “哼匣椰!你這毒婦竟也來了裆熙?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤禽笑,失蹤者是張志新(化名)和其女友劉穎弛车,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蒲每,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡纷跛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了邀杏。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贫奠。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡唬血,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出唤崭,到底是詐尸還是另有隱情拷恨,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布谢肾,位于F島的核電站腕侄,受9級特大地震影響,放射性物質發(fā)生泄漏芦疏。R本人自食惡果不足惜冕杠,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望酸茴。 院中可真熱鬧分预,春花似錦、人聲如沸薪捍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽酪穿。三九已至凳干,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間被济,已是汗流浹背纺座。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留溉潭,地道東北人净响。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像喳瓣,于是被迫代替她去往敵國和親馋贤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 關于Mongodb的全面總結 MongoDB的內(nèi)部構造《MongoDB The Definitive Guide》...
    中v中閱讀 31,930評論 2 89
  • 為了更好地理解Apache Ignite和用例的功能畏陕,理解它的體系結構和拓撲結構非常重要配乓。通過更好地理解Ignit...
    席夢思閱讀 7,629評論 1 8
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)惠毁,斷路器犹芹,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,097評論 25 707
  • 西門慶一回到家的話,就開始問自己小老婆的病情鞠绰。吳月娘責怪的說腰埂,你整天都是不回家,在外面閑游浪蕩吳月娘的眼里蜈膨,對西門...
    原野草閱讀 95評論 0 1