4

1 秒あたり 5,000 回以上の書き込み速度でデータベースに書き込むことができる必要があります。現時点では、その数の 10% 以上を管理することはできません。

Spring を使用してデータソース (HSQL) を構成し、Hibernate を Jpa プロバイダーとして構成しています。

私のエンティティはすべてフラットで (複雑なオブジェクト ツリーはありません)、Hibernate Second Level Caching (EhCache) を採用し、Concurrency-strategy を ConcurrencyStrategy.READ-WRITE に設定しました。

データソース Bean の Spring-Context は次のとおりです。

 <bean id="commandsTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="commandEmf"/>

<tx:annotation-driven transaction-manager="commandsTransactionManager" />

<!-- Commmands Data Source Configuration -->
<bean id="commandsDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc-commands.driverClassName}"/>
    <property name="url" value="${jdbc-commands.url}"/>
    <property name="username" value="${jdbc-commands.username}"/>
    <property name="password" value="${jdbc-commands.password}"/>
    <property name="initialSize" value="10"/>
    <property name="maxActive" value="100"/>
    <property name="maxWait" value="-1"/>
</bean>

 <bean name="lazyConnectionDataSourceProxy" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
    <property name="targetDataSource" ref="commandsDataSource" />
</bean>

<!-- Commands Container Managed JPA Entity Manager Factory -->
<bean id="commandEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="commandsDataSource"/>
    <property name="persistenceUnitName" value="commands"/>
    <property name="jpaPropertyMap" ref="jpaPropertyMap"/>
    <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
                    p:showSql="false"  p:generateDdl="true" p:database="HSQL" p:databasePlatform="org.hibernate.dialect.HSQLDialect">
            </bean>
    </property>
</bean>

<util:map id="jpaPropertyMap" key-type="java.lang.String" value-type="java.lang.Object">
     <entry key="hibernate.hbm2ddl.auto" value="${jdbc-commands.ddlmode}" />
      <entry key="hibernate.cache.use_second_level_cache" value="true" />
      <entry key="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory"/>
</util:map>

そして、これは私のエンティティクラスの 1 つの例です。「AbstractAnnotatedAggregateRoot」は、Aggregate および Repository 実装フレームワークを提供するAxon Frameworkの Abstract Entity クラスです。集約は基本的に、永続化のために独自の Jpa を実装する必要があるエンティティです。

@Entity
@Table(name = "users")
@Cache(region="usersCache", usage= CacheConcurrencyStrategy.READ_WRITE)
public class User extends AbstractAnnotatedAggregateRoot {

    private static final long serialVersionUID = -6536766172448063298L;

    private String username;

    private String password;

    private Integer subscription;

    private String firstName;

    private String lastName;

    private Calendar subscriptionDate;

    private Date lastAccessTime;

    public User(){}

    public User(StringAggregateIdentifier email){
        super(email);
        registerEvent(new UserCreatedEvent(email.asString()));
    }

    @Column(unique = true)
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
        registerEvent(new UserNameUpdatedEvent(this.username));
    }

    @Column(nullable = false)
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
        registerEvent(new UserPasswordUpdatedEvent(this.password));
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
        registerEvent(new UserFirstNameUpdatedEvent(this.firstName));
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
        registerEvent(new UserLastNameUpdatedEvent(this.lastName));
    }

    public String getEmail() {
        return getIdentifier().asString();
    }

    @Temporal(TemporalType.DATE)
    public Calendar getSubscriptionDate() {
        return subscriptionDate;
    }

    public void setSubscriptionDate(Calendar subscriptionDate) {
        this.subscriptionDate = subscriptionDate;
        registerEvent(new UserSubscriptionDateUpdatedEvent(this.subscriptionDate));
    }

    @Temporal(TemporalType.TIMESTAMP)
    public Date getLastAccessTime() {
        return lastAccessTime;
    }

    public void setLastAccessTime(Date lastAccessTime) {
        this.lastAccessTime = lastAccessTime;
        registerEvent(new UserLastAccessTimeUpdatedEvent(this.lastAccessTime));

    }

    public Integer getSubscription() {
        return subscription;
    }

    public void setSubscription(Integer subscription) {
        this.subscription = subscription;
        registerEvent(new UserSubscriptionUpdatedEvent(this.subscription));
    }

}

完全を期すために、EhCache.xml ファイルのキャッシュ領域構成を次に示します。

  <cache name="usersCache" maxElementsInMemory="10000"
  maxElementsOnDisk="10000" eternal="false" overflowToDisk="false"
  diskSpoolBufferSizeMB="20" timeToIdleSeconds="300"
  timeToLiveSeconds="600" memoryStoreEvictionPolicy="LFU"
  statistics = "true">
  </cache>

Axon フレームワーク内で、コマンドをディスパッチして Aggregate の状態を変更しようとします。これらのコマンドは、Spring の PlatformTransactionManager によって管理されるトランザクションの境界内にあります。

コマンド ディスパッチは同期的に行われ、毎秒 5,000 コマンドを処理する必要があります。各コマンドは、キャッシュから集計をフェッチし、その値を変更してから、次のコマンドがディスパッチされるまで変更を保持します。問題は、行のフェッチ/更新/挿入にかかる時間にしっかりとかかっています。HYSQL や H2 などによって誇示される INSERT レートを考えると、はるかに高速になると思いました。

速度を一桁上げるための考えをいただければ幸いです。

ありがとう

4

2 に答える 2

0

このエンティティが典型的なデータである場合 (つまり、長い文字列を含まない少数の列)、データベース操作が UPDATE である場合、データベースのパフォーマンスは、ここで説明されているものに匹敵し、1 秒あたり 5000 トランザクション (複数の更新、 select およびトランザクションごとに 1 回の挿入) をディスク ベースのテーブルで使用します。

http://hsqldb.org/web/hsqlPerformanceTests.html

データベースには、1 つのテーブルに 4000000 レコードがあります。大きなテーブルでは、特にデータベース サイズが Java nio メモリ マップ ファイルを使用するための事前設定された制限を超えると、パフォーマンスが低下します。

また、.script ファイルのデータベース スキーマを確認し、不要なインデックスが作成されていないかどうかを確認する必要があります。これにより、動作が遅くなる可能性があります。

于 2012-05-19T00:11:12.993 に答える
0

データベースと JDBC、および個々の挿入ステートメントでできることの限界に達していると思います。休止状態は問題ではなく、キャッシュも問題ではありません。しかし、あなたのデータベースはおそらく JDBC 経由の追加の挿入を処理できません。

ただし、一括挿入操作を使用することができれば、はるかに高速になります。バルクとはスタイルを意味しますinsert into your_table select ... from ...。テーブルからデータを読み取り、少し変更してから結果を挿入します。一括挿入が可能な場合があります。

于 2012-05-18T12:25:08.783 に答える