读写分离实践简单记录 (2)

原创
2016/07/28 11:18
阅读数 129

基于原来的 读写分离实践简单记录 发现有一个问题, 就是数据同步延迟的问题, 一半会延迟800毫秒左右, 目前的改造解决方案是 :

1. 基于线程

记录上一次执行更新操作(包括添加和删除)的时间到线程, 5秒之内的读操作,都从读写库中读取。 发现如果是ajax 请求会有问题。

2. 基于session (目前采用的方案)

记录上一次执行更新操作(包括添加和删除)的时间到Session, 5秒之内的读操作,都从读写库中读取。

3. 基于log(还没有实施)

想法是比较两个库的事务log(sys.dm_hadr_database_replica_states表中的 end_of_log_lsn)是否一致,如果一致说明就是已经同步了 这个方案的问题就是如果主库一直在写, 那么 log就是一直不一致, 那么读库一直不会被命中。

最后上 基于session 方案的 代码:

 /// <summary>
        ///  
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="connectstring"></param>
        /// <param name="isRead">0 unknow, 1 读写, 2 只读,</param>
        /// <returns></returns>
        private static string GetReadConnectstring(string sql, string connectstring, int isRead = 0)
        {
            if (!SqlConnectionString.CheckIsSuportReadonly(connectstring))
            {
                return connectstring;
            }

            bool isquery = false;

            if (isRead == 0)
            {
                isquery = IsSelect(sql);
            }
            if (isRead == 1)
            {
                isquery = false;
            }

            var result = SqlConnectionString.GetReadonlyConnectionstring(connectstring);
            if (isRead == 2)
            {
                return result;
            }
            if (isquery && (DateTime.Now.Subtract(PreExecTime).TotalMilliseconds > DELAY_TIME))
            { 
                //result = ;
            }
            else
            {
                result = connectstring;
            }
            if (!isquery)
            {
                PreExecTime = DateTime.Now;
            } 
            return result;
        }

        private const int DELAY_TIME = 5000;
        // 上一次执行 更新操作的时间
        //private static DateTime _preExecTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
        private const string PREEXECTIME_SESSION_KEY = "PreExecTime";
        /// <summary>
        /// 上一次执行 更新操作的时间
        /// </summary>
        private static DateTime PreExecTime
        {
            get
            {
                if (HttpContext.Current == null  || HttpContext.Current.Session == null)
                {
                    return DateTime.Now;
                }
                else
                {
                    return ConvertHelper.ToDateTime(HttpContext.Current.Session[PREEXECTIME_SESSION_KEY], new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day));
                }
            }
            set
            {
                if (HttpContext.Current != null && HttpContext.Current.Session != null)
                {
                    HttpContext.Current.Session[PREEXECTIME_SESSION_KEY] = value;
                }
            }
        } 
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部