예제 #1
0
        /// <summary>
        /// Process synchronized queue of redis
        /// </summary>
        /// <param name="sysnWorkingQueueKey"></param>
        /// <param name="keys"></param>
        /// <param name="values"></param>
        private static bool ProcessRedisSyncQueue(string sysnWorkingQueueKey, byte[][] keys, byte[][] values)
        {
            bool result = false;

            try
            {
                var redisSyncErrorQueue = new List <byte[][]>();
                var entityList          = new List <RedisEntityItem>();
                var entityRemList       = new List <RedisEntityItem>();
                var mutilKeyMapList     = new List <RedisEntityItem>();
                var mutilKeyMapRemList  = new List <RedisEntityItem>();
                var sqlWaitSyncQueue    = new List <KeyValuePair <string, byte[][]> >();

                for (int i = 0; i < keys.Length; i++)
                {
                    byte[] keyBytes   = keys[i];
                    byte[] valueBytes = values[i];
                    try
                    {
                        string[]    queueKey        = RedisConnectionPool.ToStringKey(keyBytes).Split('_');
                        string      entityTypeName  = RedisConnectionPool.DecodeTypeName(queueKey[0]);
                        string      entityParentKey = RedisConnectionPool.GetRedisEntityKeyName(queueKey[0]);
                        byte[]      entityKeyBytes  = RedisConnectionPool.ToByteKey(queueKey[1]);
                        bool        hasMutilKey     = false;
                        bool        isStoreInDb     = true;
                        SchemaTable schema;
                        if (EntitySchemaSet.TryGet(entityTypeName, out schema))
                        {
                            hasMutilKey = RedisConnectionPool.CurrRedisInfo.ClientVersion >= RedisStorageVersion.HashMutilKeyMap &&
                                          schema.EntityType.IsSubclassOf(typeof(BaseEntity)) &&
                                          schema.Keys.Length > 1;
                            isStoreInDb = schema.StorageType.HasFlag(StorageType.WriteOnlyDB) || schema.StorageType.HasFlag(StorageType.ReadWriteDB);
                        }

                        byte[] headBytes;
                        byte[] entityValBytes;
                        int    state;
                        int    identity;
                        DecodeValueBytes(valueBytes, out headBytes, out entityValBytes, out state, out identity);

                        var entityItem = new RedisEntityItem()
                        {
                            HashId      = entityParentKey,
                            UserId      = identity,
                            KeyBytes    = entityKeyBytes,
                            ValueBytes  = entityValBytes,
                            State       = state,
                            HasMutilKey = hasMutilKey
                        };
                        if (entityItem.State == 1)
                        {
                            entityRemList.Add(entityItem);
                            if (hasMutilKey)
                            {
                                mutilKeyMapRemList.Add(entityItem);
                            }
                        }
                        else
                        {
                            entityList.Add(entityItem);
                            if (hasMutilKey)
                            {
                                mutilKeyMapList.Add(entityItem);
                            }
                        }
                        if (_enableWriteToDb && isStoreInDb)
                        {
                            //增加到Sql等待队列
                            string sqlWaitQueueKey = GetSqlWaitSyncQueueKey(identity);
                            sqlWaitSyncQueue.Add(new KeyValuePair <string, byte[][]>(sqlWaitQueueKey, new[] { keyBytes, headBytes }));
                        }
                    }
                    catch
                    {
                        redisSyncErrorQueue.Add(new[] { keyBytes, valueBytes });
                    }
                }
                var redisErrorKeys       = redisSyncErrorQueue.Select(p => p[0]).ToArray();
                var redisErrorValues     = redisSyncErrorQueue.Select(p => p[1]).ToArray();
                var sqlWaitGroups        = sqlWaitSyncQueue.GroupBy(p => p.Key);
                var setGroups            = entityList.GroupBy(p => p.HashId);
                var removeGroups         = entityRemList.GroupBy(p => p.HashId);
                var mutilKeyMapGroups    = mutilKeyMapList.GroupBy(p => p.HashId);
                var mutilKeyMapRemGroups = mutilKeyMapRemList.GroupBy(p => p.HashId);

                RedisConnectionPool.ProcessPipeline(pipeline =>
                {
                    bool hasPost = false;

                    foreach (var g in setGroups)
                    {
                        var entityKeys   = g.Select(p => p.KeyBytes).ToArray();
                        var entityValues = g.Select(p => p.ValueBytes).ToArray();
                        pipeline.QueueCommand(client => ((RedisClient)client).HMSet(g.Key, entityKeys, entityValues));
                        hasPost = true;
                    }
                    foreach (var g in removeGroups)
                    {
                        var keybytes = g.Select(p => p.KeyBytes).ToArray();
                        pipeline.QueueCommand(client => ((RedisClient)client).HDel(g.Key, keybytes));
                        hasPost = true;
                    }
                    foreach (var g in mutilKeyMapGroups)
                    {
                        string hashId = g.Key;
                        var subGroup  = g.GroupBy(t => t.UserId);
                        foreach (var @group in subGroup)
                        {
                            string firstKey = AbstractEntity.EncodeKeyCode(@group.Key.ToString());
                            var keybytes    = @group.Select(p => p.KeyBytes).ToArray();
                            pipeline.QueueCommand(client => RedisConnectionPool.SetMutilKeyMap((RedisClient)client, hashId, firstKey, keybytes));
                            hasPost = true;
                        }
                    }
                    foreach (var g in mutilKeyMapRemGroups)
                    {
                        string hashId = g.Key;
                        var subGroup  = g.GroupBy(t => t.UserId);
                        foreach (var @group in subGroup)
                        {
                            string firstKey = AbstractEntity.EncodeKeyCode(@group.Key.ToString());
                            var keybytes    = @group.Select(p => p.KeyBytes).ToArray();
                            pipeline.QueueCommand(client => RedisConnectionPool.RemoveMutilKeyMap((RedisClient)client, hashId, firstKey, keybytes));
                            hasPost = true;
                        }
                    }

                    if (redisErrorKeys.Length > 0)
                    {
                        pipeline.QueueCommand(client => ((RedisClient)client).HMSet(RedisSyncErrorQueueKey, redisErrorKeys, redisErrorValues));
                        hasPost = true;
                    }
                    foreach (var g in sqlWaitGroups)
                    {
                        var sqlWaitKeys   = g.Select(p => p.Value[0]).ToArray();
                        var sqlWaitValues = g.Select(p => p.Value[1]).ToArray();
                        pipeline.QueueCommand(client => ((RedisClient)client).HMSet(g.Key, sqlWaitKeys, sqlWaitValues));
                        hasPost = true;
                    }
                    if (hasPost)
                    {
                        pipeline.Flush();
                    }
                    result = redisErrorKeys.Length == 0;
                });
            }
            catch (Exception ex)
            {
                TraceLog.WriteError("DoProcessRedisSyncQueue error:{0}", ex);
                try
                {
                    RedisConnectionPool.Process(client => client.HMSet(RedisSyncErrorQueueKey, keys, values));
                }
                catch (Exception er)
                {
                    TraceLog.WriteError("Put RedisSyncErrorQueue error:{0}", er);
                }
            }
            return(result);
        }