public OperationalDatabases GetOperationalDatabases(Statement statement)
        {
            OperationalDatabases databases = new OperationalDatabases
            {
                OtherCandidates = new List <Database>()
            };

            try
            {
                String databaseSet = statement.DatabaseSet;
                var    master      = DALBootstrap.DatabaseSets[databaseSet].DatabaseWrappers.Where(item => item.DatabaseType == DatabaseType.Master).Single();
                var    slaves      = DALBootstrap.DatabaseSets[databaseSet].DatabaseWrappers.Where(item => item.DatabaseType == DatabaseType.Slave)
                                     .OrderByDescending(p => p.Ratio).ToList();

                if (slaves != null && slaves.Count > 0)
                {
                    databases.FirstCandidate = slaves[0].Database;
                    slaves.RemoveAt(0);
                    slaves.ForEach(p => databases.OtherCandidates.Add(p.Database));
                    databases.OtherCandidates.Add(master.Database);
                }
            }
            catch
            {
                throw;
            }

            return(databases);
        }
        /// <summary>
        ///  读写分离规则
        /// </summary>
        /// <param name="statement"></param>
        /// <returns></returns>
        public OperationalDatabases GetOperationalDatabases(Statement statement)
        {
            OperationalDatabases databases = new OperationalDatabases
            {
                OtherCandidates = new List <Database>()
            };

            try
            {
                String databaseSet = statement.DatabaseSet;

                var master = DALBootstrap.DatabaseSets[databaseSet].DatabaseWrappers.Single(item => item.DatabaseType == DatabaseType.Master);

                var slaves = DALBootstrap.DatabaseSets[databaseSet].DatabaseWrappers.Where(item => item.DatabaseType == DatabaseType.Slave)
                             .ToList();
                Int32 count = slaves.Count();
                if (statement.OperationType == OperationType.Read && count > 0)
                {
                    Random random = new Random();
                    //如果多于1个Slave,随机选择一个
                    int index = random.Next(0, count);
                    for (Int32 i = 0; i < count; i++)
                    {
                        if (i == index)
                        {
                            databases.FirstCandidate = slaves.ElementAt(index).Database;
                        }
                        else
                        {
                            databases.OtherCandidates.Add(slaves.ElementAt(i).Database);
                        }
                    }
                    //将主库加入作为最后的备选
                    databases.OtherCandidates.Add(master.Database);
                }
                else
                {
                    databases.FirstCandidate = master.Database;
                    databases.OtherCandidates.Add(count > 0 ? slaves.ElementAt(0).Database:null);
                }
            }
            catch (Exception ex)
            {
                throw new DalException(ex.Message + Environment.NewLine + ex.StackTrace);
            }

            return(databases);
        }
Пример #3
0
        public T ExecuteWithHa <T>(Func <Database, T> func, OperationalDatabases databases)
        {
            T        result   = default(T);
            BitArray bitArray = (databases.OtherCandidates != null && databases.OtherCandidates.Count > 0) ? new BitArray(databases.OtherCandidates.Count) : null;
            var      currentOperateDatabase = databases.FirstCandidate;
            Int32    retryTimes             = RetryFailOverTimes;

            try
            {
                ExecutorManager.Executor.Daemon();

                //被Mark Down了,且当前Request没有放行
                while (haBean.EnableHA && retryTimes > 0 && !currentOperateDatabase.Available)
                {
                    var fallbackDatabase = FallToNextDatabase(currentOperateDatabase, databases.OtherCandidates, bitArray);
                    if (fallbackDatabase == currentOperateDatabase)
                    {
                        throw new DalMarkDownException(String.Format(Resources.DBMarkDownException, currentOperateDatabase.AllInOneKey));
                    }
                    currentOperateDatabase = fallbackDatabase;
                    retryTimes--;
                }

                if (!currentOperateDatabase.Available)
                {
                    throw new DalMarkDownException(String.Format(Resources.DBMarkDownException, currentOperateDatabase.AllInOneKey));
                }
                result = func(currentOperateDatabase);
            }
            catch (DalMarkDownException)
            {
                throw;
            }
            catch (DbException ex)
            {
                if (!haBean.EnableHA)
                {
                    throw;
                }

                var     exception       = ex;
                Boolean failoverSucceed = false;
                String  databaseSet     = currentOperateDatabase.DatabaseSetName;
                String  allInOneKey     = currentOperateDatabase.AllInOneKey;

                while (retryTimes > 0)
                {
                    retryTimes--;

                    try
                    {
                        Boolean failoverNecessary = SatisfyRetryFailOverCondition(exception);
                        if (!failoverNecessary)
                        {
                            throw;
                        }

                        var failoverDatabase = FallToNextDatabase(currentOperateDatabase, databases.OtherCandidates, bitArray);
                        if (failoverDatabase == null)
                        {
                            throw;
                        }

                        allInOneKey     = failoverDatabase.AllInOneKey;
                        result          = func(failoverDatabase);
                        failoverSucceed = true;
                    }
                    catch (DbException exp)
                    {
                        exception       = exp;
                        failoverSucceed = false;
                    }

                    if (failoverSucceed)
                    {
                        LogManager.Logger.MetricsFailover(databaseSet, allInOneKey);
                        break;
                    }
                }

                if (!failoverSucceed)
                {
                    throw;
                }
            }

            return(result);
        }