Trusted Dictionary Search

I need to create a web API search function for all users on my system. The client (using the phone) sends me requests using the endpoint:

HTTP 1.1 GET http://sf.cluster:80/ Path /search/users?q=Aa&take=10 

Where q is the string entered by the user in the search field. accept - how many entries the phone wants to show.

I uploaded 89,000 items from the Azure storage table to my trusted dictionary. It has the structure:

 IReliableDictionary<Guid, string> 

My search method is as follows:

  public async Task<IEnumerable<UserInfo>> Search(string q, int take) { var usersDictionary = await GetUsersDictionary(); IEnumerable<UserInfo> results; using (var tx = StateManager.CreateTransaction()) { var searchResults = (from r in (await usersDictionary.CreateEnumerableAsync(tx)).ToEnumerable() where r.Value.StartsWith(q, StringComparison.InvariantCultureIgnoreCase) select new UserInfo() { Id = r.Key, Name = r.Value }).Take(take); results = new List<UserInfo>(searchResults); await tx.CommitAsync(); } return results; } 

Problem: This works well on the phone, I got what I expected. But when I started pushing my endpoint with a bunch of requests (about ~ 60 threads at a time using the Soap UI tool ), the timeout started to grow from 1s to 35s! It seems like I was mistaken somewhere or chose the wrong implementation method.

If someone implemented some features? Can someone help with a proper search?

UPD: A stateless service is implemented where I store a List<string> with names and do the same (search through a list). Results: 150-300 ms. It looks like I should keep List in state (in the state service) and get it on request.

0
source share
2 answers

I don't know what the implementation of your ToEnumerable method ToEnumerable , but most of the ones I've seen are a pretty lazy implementation, just listing async and copying it to a list. Now, with a reliable dictionary of 890,000 elems, this is pretty inefficient. In addition, transactions act as mutexes, so while you copy this huge list, you are blocking the base collection. I would suggest checking out the linq implementation in AsyncEnumerable in this library , since it implements an efficient way to use linq with AsyncEnumerable service fabrics. Using this, your search will look something like this:

  using (var tx = StateManager.CreateTransaction()) { var enumerable = await usersDictionary.CreateEnumerableAsync(tx); results = await enumerable.Where(kvp=>kvp.Value.StartsWith(q, StringComparison.InvariantCultureIgnoreCase)) .Select(kvp=> new UserInfo() { Id = r.Key, Name = r.Value }) .Take(take) .ToListAsync(tx); } 

In addition, as a side note, since you are not modifying the base collection in any way, you do not need to commit a transaction. Transaction reconciliation is simply a way to tell the state manager that you have changed state and you have finished making your changes, and then pass the changed values ​​to the secondary ones. You could even call this method on the secondary, if this is a read-heavy part of the state, but note that the records are not yet distributed.

+3
source

ReliableDictinonary returns an IAsyncEnumerable because ReliableDictionary pages go out of some values. This means that you may need an IO drive to read some values. IAsyncEnumerable allows us to block multiple threads as much as possible.

If read latency is a problem, you can use notifications to create a completely secondary index in memory. You can also order an additional index by value to increase the efficiency of prefix matching. Below is the relevant documentation: https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-notifications

Minor correction for pdylanross: CreateEnumerableAsync response provides isolation of snapshots using the mvcc model, which does not block collection. Therefore, other transactions may continue to read and write while snapshot transactions are in flight. For more information about isolation levels: https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-reliable-collections

Hope this helps,

+1
source

Source: https://habr.com/ru/post/1241134/


All Articles