Multi-cache transactions & persistent store

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Multi-cache transactions & persistent store

irudyak
Hi guys,

Playing with Ignite multi-cache transactions(transactions involving
multiple caches) we run into the lack of proper/easy mechanism to support
such transactions on persistent store side (while implementing particular
*CacheStore*).

The problem is there is no easy way for *CacheStore *implementation to get
information about caches involved in the transaction.

Here are more details:

When committing multi-cache transaction, Ignite produces multiple
*sessionEnd(...)* calls (in *CacheStore *implementation) - one for each
cache. Thus to support multi-cache transaction in persistent store, we need
to accumulate all the changes made to multiple caches (by
*write/writeAll/delete/deleteAll* operations) and apply them as one
transaction/batch to a persistent store in the final(last) *sessionEnd *call.
To do this we need to know exact number of caches participating in the
transaction. Having this number we can skip all *sessionEnd *calls except
the last - which we will use to commit/persist all the changes we
previously accumulated.

As for now, the only way to get the number of caches participating in a
transaction is to register *CacheStoreSessionListener *and count number of
caches in its "*onSessionStart*" method. Such approach doesn't look very
elegant cause we always need to keep in mind that specifying "
*cacheStoreFactory*" in cache configuration is not enough. In addition to
this we also need to specify appropriate "
*cacheStoreSessionListenerFactories*" property - otherwise it will not work
for multi-cache transactions.

Here is an example chunk from cache configuration:

* <property name="cacheStoreFactory">*
* <bean
class="org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory">*
* <property name="dataSourceBean" value="cassandraDataSource"/>*
* <property name="persistenceSettingsBean"
value="cache1_persistence_settings"/>*
* </bean>*
* </property>*
* <property name="cacheStoreSessionListenerFactories">*
* <list>*
* <bean class="org.apache.ignite.tests.MyCacheStoreSessionListener"/>*
* </list>*
* </property>*

We see that, instead of specifying only one property "*cacheStoreFactory*"
for a cache we should always specify two properties in case we need
multi-cache transactions support in persistent store. Conceptually it
doesn't look good, cause users thinking about *CacheStore *implementation
like something self-contained - once it specified in cache configuration
everything should be smooth. But in case of multi-cache transactions
support we always need to remember about registering some strange
"listener".

In Ignite we already have such concept as "
*org.apache.ignite.transactions.Transaction*" which defines our
transaction. It looks logical if it will also provide information about
transaction boundaries (caches involved into transaction). Such approach
can simplify persistent store implementation for multi-cache transactions.

Any thoughts?


Igor Rudyak
Reply | Threaded
Open this post in threaded view
|

Re: Multi-cache transactions & persistent store

yzhdanov
Igor, you factory should return the same instance for all caches started
locally. This way Ignite should call sessionEnd() once. Can you please
check?

--Yakov

2016-07-30 4:40 GMT+03:00 Igor Rudyak <[hidden email]>:

> Hi guys,
>
> Playing with Ignite multi-cache transactions(transactions involving
> multiple caches) we run into the lack of proper/easy mechanism to support
> such transactions on persistent store side (while implementing particular
> *CacheStore*).
>
> The problem is there is no easy way for *CacheStore *implementation to get
> information about caches involved in the transaction.
>
> Here are more details:
>
> When committing multi-cache transaction, Ignite produces multiple
> *sessionEnd(...)* calls (in *CacheStore *implementation) - one for each
> cache. Thus to support multi-cache transaction in persistent store, we need
> to accumulate all the changes made to multiple caches (by
> *write/writeAll/delete/deleteAll* operations) and apply them as one
> transaction/batch to a persistent store in the final(last) *sessionEnd
> *call.
> To do this we need to know exact number of caches participating in the
> transaction. Having this number we can skip all *sessionEnd *calls except
> the last - which we will use to commit/persist all the changes we
> previously accumulated.
>
> As for now, the only way to get the number of caches participating in a
> transaction is to register *CacheStoreSessionListener *and count number of
> caches in its "*onSessionStart*" method. Such approach doesn't look very
> elegant cause we always need to keep in mind that specifying "
> *cacheStoreFactory*" in cache configuration is not enough. In addition to
> this we also need to specify appropriate "
> *cacheStoreSessionListenerFactories*" property - otherwise it will not work
> for multi-cache transactions.
>
> Here is an example chunk from cache configuration:
>
> * <property name="cacheStoreFactory">*
> * <bean
>
> class="org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory">*
> * <property name="dataSourceBean" value="cassandraDataSource"/>*
> * <property name="persistenceSettingsBean"
> value="cache1_persistence_settings"/>*
> * </bean>*
> * </property>*
> * <property name="cacheStoreSessionListenerFactories">*
> * <list>*
> * <bean class="org.apache.ignite.tests.MyCacheStoreSessionListener"/>*
> * </list>*
> * </property>*
>
> We see that, instead of specifying only one property "*cacheStoreFactory*"
> for a cache we should always specify two properties in case we need
> multi-cache transactions support in persistent store. Conceptually it
> doesn't look good, cause users thinking about *CacheStore *implementation
> like something self-contained - once it specified in cache configuration
> everything should be smooth. But in case of multi-cache transactions
> support we always need to remember about registering some strange
> "listener".
>
> In Ignite we already have such concept as "
> *org.apache.ignite.transactions.Transaction*" which defines our
> transaction. It looks logical if it will also provide information about
> transaction boundaries (caches involved into transaction). Such approach
> can simplify persistent store implementation for multi-cache transactions.
>
> Any thoughts?
>
>
> Igor Rudyak
>
Reply | Threaded
Open this post in threaded view
|

Re: Multi-cache transactions & persistent store

Valentin Kulichenko
In reply to this post by irudyak
Hi Igor,

In a multi-cache transaction there can several different stores involved,
that's why store is not considered to be self-contained. That's why
transaction callbacks moved to a separate entity - store session listener.

Can you please clarify how do you suggest to use Transaction for this? This
interface is not implemented by a user, so it's not clear to me.

-Val

On Fri, Jul 29, 2016 at 6:40 PM, Igor Rudyak <[hidden email]> wrote:

> Hi guys,
>
> Playing with Ignite multi-cache transactions(transactions involving
> multiple caches) we run into the lack of proper/easy mechanism to support
> such transactions on persistent store side (while implementing particular
> *CacheStore*).
>
> The problem is there is no easy way for *CacheStore *implementation to get
> information about caches involved in the transaction.
>
> Here are more details:
>
> When committing multi-cache transaction, Ignite produces multiple
> *sessionEnd(...)* calls (in *CacheStore *implementation) - one for each
> cache. Thus to support multi-cache transaction in persistent store, we need
> to accumulate all the changes made to multiple caches (by
> *write/writeAll/delete/deleteAll* operations) and apply them as one
> transaction/batch to a persistent store in the final(last) *sessionEnd
> *call.
> To do this we need to know exact number of caches participating in the
> transaction. Having this number we can skip all *sessionEnd *calls except
> the last - which we will use to commit/persist all the changes we
> previously accumulated.
>
> As for now, the only way to get the number of caches participating in a
> transaction is to register *CacheStoreSessionListener *and count number of
> caches in its "*onSessionStart*" method. Such approach doesn't look very
> elegant cause we always need to keep in mind that specifying "
> *cacheStoreFactory*" in cache configuration is not enough. In addition to
> this we also need to specify appropriate "
> *cacheStoreSessionListenerFactories*" property - otherwise it will not work
> for multi-cache transactions.
>
> Here is an example chunk from cache configuration:
>
> * <property name="cacheStoreFactory">*
> * <bean
>
> class="org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory">*
> * <property name="dataSourceBean" value="cassandraDataSource"/>*
> * <property name="persistenceSettingsBean"
> value="cache1_persistence_settings"/>*
> * </bean>*
> * </property>*
> * <property name="cacheStoreSessionListenerFactories">*
> * <list>*
> * <bean class="org.apache.ignite.tests.MyCacheStoreSessionListener"/>*
> * </list>*
> * </property>*
>
> We see that, instead of specifying only one property "*cacheStoreFactory*"
> for a cache we should always specify two properties in case we need
> multi-cache transactions support in persistent store. Conceptually it
> doesn't look good, cause users thinking about *CacheStore *implementation
> like something self-contained - once it specified in cache configuration
> everything should be smooth. But in case of multi-cache transactions
> support we always need to remember about registering some strange
> "listener".
>
> In Ignite we already have such concept as "
> *org.apache.ignite.transactions.Transaction*" which defines our
> transaction. It looks logical if it will also provide information about
> transaction boundaries (caches involved into transaction). Such approach
> can simplify persistent store implementation for multi-cache transactions.
>
> Any thoughts?
>
>
> Igor Rudyak
>
Reply | Threaded
Open this post in threaded view
|

Re: Multi-cache transactions & persistent store

irudyak
In reply to this post by yzhdanov
Thanks Yakov! It could be used as a possible solution for multi-cache
transactions, which persistent stores implementation sharing the same data
source/session.

Igor Rudyak

On Mon, Aug 1, 2016 at 1:32 AM, Yakov Zhdanov <[hidden email]> wrote:

> Igor, you factory should return the same instance for all caches started
> locally. This way Ignite should call sessionEnd() once. Can you please
> check?
>
> --Yakov
>
> 2016-07-30 4:40 GMT+03:00 Igor Rudyak <[hidden email]>:
>
> > Hi guys,
> >
> > Playing with Ignite multi-cache transactions(transactions involving
> > multiple caches) we run into the lack of proper/easy mechanism to support
> > such transactions on persistent store side (while implementing particular
> > *CacheStore*).
> >
> > The problem is there is no easy way for *CacheStore *implementation to
> get
> > information about caches involved in the transaction.
> >
> > Here are more details:
> >
> > When committing multi-cache transaction, Ignite produces multiple
> > *sessionEnd(...)* calls (in *CacheStore *implementation) - one for each
> > cache. Thus to support multi-cache transaction in persistent store, we
> need
> > to accumulate all the changes made to multiple caches (by
> > *write/writeAll/delete/deleteAll* operations) and apply them as one
> > transaction/batch to a persistent store in the final(last) *sessionEnd
> > *call.
> > To do this we need to know exact number of caches participating in the
> > transaction. Having this number we can skip all *sessionEnd *calls except
> > the last - which we will use to commit/persist all the changes we
> > previously accumulated.
> >
> > As for now, the only way to get the number of caches participating in a
> > transaction is to register *CacheStoreSessionListener *and count number
> of
> > caches in its "*onSessionStart*" method. Such approach doesn't look very
> > elegant cause we always need to keep in mind that specifying "
> > *cacheStoreFactory*" in cache configuration is not enough. In addition to
> > this we also need to specify appropriate "
> > *cacheStoreSessionListenerFactories*" property - otherwise it will not
> work
> > for multi-cache transactions.
> >
> > Here is an example chunk from cache configuration:
> >
> > * <property name="cacheStoreFactory">*
> > * <bean
> >
> >
> class="org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory">*
> > * <property name="dataSourceBean" value="cassandraDataSource"/>*
> > * <property name="persistenceSettingsBean"
> > value="cache1_persistence_settings"/>*
> > * </bean>*
> > * </property>*
> > * <property name="cacheStoreSessionListenerFactories">*
> > * <list>*
> > * <bean class="org.apache.ignite.tests.MyCacheStoreSessionListener"/>*
> > * </list>*
> > * </property>*
> >
> > We see that, instead of specifying only one property
> "*cacheStoreFactory*"
> > for a cache we should always specify two properties in case we need
> > multi-cache transactions support in persistent store. Conceptually it
> > doesn't look good, cause users thinking about *CacheStore *implementation
> > like something self-contained - once it specified in cache configuration
> > everything should be smooth. But in case of multi-cache transactions
> > support we always need to remember about registering some strange
> > "listener".
> >
> > In Ignite we already have such concept as "
> > *org.apache.ignite.transactions.Transaction*" which defines our
> > transaction. It looks logical if it will also provide information about
> > transaction boundaries (caches involved into transaction). Such approach
> > can simplify persistent store implementation for multi-cache
> transactions.
> >
> > Any thoughts?
> >
> >
> > Igor Rudyak
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: Multi-cache transactions & persistent store

irudyak
In reply to this post by yzhdanov
By the way Yakov. How should we handle multi-cache transactions for
"write-behind" caches? For different caches (participated in transaction)
we can receive several separate sessionEnd calls.

Igor

On Mon, Aug 1, 2016 at 1:32 AM, Yakov Zhdanov <[hidden email]> wrote:

> Igor, you factory should return the same instance for all caches started
> locally. This way Ignite should call sessionEnd() once. Can you please
> check?
>
> --Yakov
>
> 2016-07-30 4:40 GMT+03:00 Igor Rudyak <[hidden email]>:
>
> > Hi guys,
> >
> > Playing with Ignite multi-cache transactions(transactions involving
> > multiple caches) we run into the lack of proper/easy mechanism to support
> > such transactions on persistent store side (while implementing particular
> > *CacheStore*).
> >
> > The problem is there is no easy way for *CacheStore *implementation to
> get
> > information about caches involved in the transaction.
> >
> > Here are more details:
> >
> > When committing multi-cache transaction, Ignite produces multiple
> > *sessionEnd(...)* calls (in *CacheStore *implementation) - one for each
> > cache. Thus to support multi-cache transaction in persistent store, we
> need
> > to accumulate all the changes made to multiple caches (by
> > *write/writeAll/delete/deleteAll* operations) and apply them as one
> > transaction/batch to a persistent store in the final(last) *sessionEnd
> > *call.
> > To do this we need to know exact number of caches participating in the
> > transaction. Having this number we can skip all *sessionEnd *calls except
> > the last - which we will use to commit/persist all the changes we
> > previously accumulated.
> >
> > As for now, the only way to get the number of caches participating in a
> > transaction is to register *CacheStoreSessionListener *and count number
> of
> > caches in its "*onSessionStart*" method. Such approach doesn't look very
> > elegant cause we always need to keep in mind that specifying "
> > *cacheStoreFactory*" in cache configuration is not enough. In addition to
> > this we also need to specify appropriate "
> > *cacheStoreSessionListenerFactories*" property - otherwise it will not
> work
> > for multi-cache transactions.
> >
> > Here is an example chunk from cache configuration:
> >
> > * <property name="cacheStoreFactory">*
> > * <bean
> >
> > class="org.apache.ignite.cache.store.cassandra.
> CassandraCacheStoreFactory">*
> > * <property name="dataSourceBean" value="cassandraDataSource"/>*
> > * <property name="persistenceSettingsBean"
> > value="cache1_persistence_settings"/>*
> > * </bean>*
> > * </property>*
> > * <property name="cacheStoreSessionListenerFactories">*
> > * <list>*
> > * <bean class="org.apache.ignite.tests.MyCacheStoreSessionListener"/>*
> > * </list>*
> > * </property>*
> >
> > We see that, instead of specifying only one property
> "*cacheStoreFactory*"
> > for a cache we should always specify two properties in case we need
> > multi-cache transactions support in persistent store. Conceptually it
> > doesn't look good, cause users thinking about *CacheStore *implementation
> > like something self-contained - once it specified in cache configuration
> > everything should be smooth. But in case of multi-cache transactions
> > support we always need to remember about registering some strange
> > "listener".
> >
> > In Ignite we already have such concept as "
> > *org.apache.ignite.transactions.Transaction*" which defines our
> > transaction. It looks logical if it will also provide information about
> > transaction boundaries (caches involved into transaction). Such approach
> > can simplify persistent store implementation for multi-cache
> transactions.
> >
> > Any thoughts?
> >
> >
> > Igor Rudyak
> >
>