StackExchange Redis在使用异步插入/读取数据时丢失了一些键

ale*_*exx 6 c# asynchronous azure redis stackexchange.redis

我相信我们在这里缺少一些非常重要的东西,所以希望有人可以指出我正确的方向.先感谢您 :)

我们目前遇到的问题:有时异步操作(读取)不会从通过异步操作写入的db返回我们的哈希值.例如,一次操作可以返回600个键,下一次键的数量可以是598,下一个是596,依此类推.我们也遇到了与短集相同的问题(当我们在集合中有多达10个键并且在批处理中读取10个哈希对象时:有时我们可以获得8个对象,有时是6个,一旦我们只得到2个.我们遇到了异步方法问题大约30-40%的运营,迁移到同步操作解决了一些情况 - 我们已经失去了性能.

我们的创建/读取批处理操作的示例

protected void CreateBatch(Func<IBatch, List<Task>> action)
    {
        IBatch batch = Database.CreateBatch();

        List<Task> tasks = action(batch);

        batch.Execute();

        Task.WaitAll(tasks.ToArray());
    }

    protected IEnumerable<T> GetBatch<T, TRedis>(
        IEnumerable<RedisKey> keys, 
        Func<IBatch, RedisKey, Task<TRedis>> invokeBatchOperation, 
        Func<TRedis, T> buildResultItem)
    {
        IBatch batch = Database.CreateBatch();
        List<RedisKey> keyList = keys.ToList();
        List<Task> tasks = new List<Task>(keyList.Count);
        List<T> result = new List<T>(keyList.Count);

        foreach (RedisKey key in keyList)
        {
            Task task = invokeBatchOperation(batch, key).ContinueWith(
                t =>
                    {
                        T item = buildResultItem(t.Result);
                        result.Add(item);
                    });

            tasks.Add(task);
        }

        batch.Execute();
        Task.WaitAll(tasks.ToArray());

        return result;
    }
Run Code Online (Sandbox Code Playgroud)

我们下一步使用写操作:

private void CreateIncrementBatch(IEnumerable<DynamicDTO> dynamicDtos)
    {
        CreateBatch(
            batch =>
                {
                    List<Task> tasks = new List<Task>();

                    foreach (DynamicDTO dynamicDto in dynamicDtos)
                    {
                        string dynamicKey = KeysBuilders.Live.Dynamic.BuildDetailsKeyByIdAndVersion(
                            dynamicDto.Id, 
                            dynamicDto.Version);
                        HashEntry[] dynamicFields = _dtoMapper.MapDynamicToHashEntries(dynamicDto);

                        Task task = batch.HashSetAsync(dynamicKey, dynamicFields, CommandFlags.HighPriority);
                        tasks.Add(task);
                    }

                    return tasks;
                });
    }
Run Code Online (Sandbox Code Playgroud)

我们使用下一个代码示例批量读取数据

IEnumerable<RedisKey> userKeys =
                        GetIdsByUserId(userId).Select(x => (RedisKey) KeysBuilders.Live.Dynamic.BuildDetailsKeyByUserId(x));

                    return GetBatch(userKeys, (batch, key) => batch.HashGetAllAsync(key), _dtoMapper.MapToDynamic);
Run Code Online (Sandbox Code Playgroud)

我们知道batch.Execute不是同步/不是真正的异步操作,同时我们需要稍后检查每个操作的状态.我们计划在redis服务器上进行更多的读写操作,但是使用这个问题,我们不确定我们是否走在正确的道路上.

任何建议/样品和指向正确方向的人都非常感谢!

一些附加信息:我们在asp.mvc/worker角色(.NET版本4.5)中使用StackExchange redis客户端(最新稳定版本:1.0.481)来连接和使用Azure redis缓存(C1,标准版).目前,在小测试流程中我们在数据库中有大约10万个密钥(主要是哈希 - 基于redis.io中提供的建议(每个密钥最多可存储10个不同对象的字段,哈希中不存储大数据或文本字段)和设置(主要是映射,最大的一个可以占用父母的10 000个密钥)).我们有大约20个小写入缓存(每个编写器实例写入它自己的数据子集,不与另一个重叠,每个操作写入的密钥数量最多为100(散列)).我们还有一个"大个子"

小智 0

也许你可以用

  List<T> result = new List<T>(keyList.Count);
Run Code Online (Sandbox Code Playgroud)

像这样的东西吗?

 ConcurrentBag<T>result = new ConcurrentBag<T>();
Run Code Online (Sandbox Code Playgroud)

ConcurrentBag 表示线程安全的、无序的对象集合。