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); }
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); }