贝网博客

我的分类
流水记事
源码下载
Asp.net
其它
数据库
Javascript
.Net技术
我的相册
友情链接
博客园
CSDN博客
Start0
最新回复
fasdfasdf
[:..
lz这个东西好厉害,我..
哈哈,好照片
不错,以前一直用黄色..
终于找到支持ff的修正..
终于找到支持ff的修正..
新鲜性
看看,试试,好不好使。
好东西一起学习[:img0..
分类 =》.Net技术
数据同步代码的时间优化方案一则
发表于:2012-12-14 14:27:52
更新于:2012-12-14 16:22:28

小时候听过一个泡茶的故事,正常的顺序是:烧开水20分钟,准备茶叶1分钟,清洗茶杯5分钟
正常情况下,大家都是先烧开水,在等水烧开的过程中,去准备茶叶和清洗茶杯,而不会等水烧开后,再去准备茶叶和清洗茶杯,这样可以节约6分钟时间。

同样的,最近经常处理一些数据同步的工作,比如把数据从SqlServer同步到Redis或MongoDB里去,很多人的代码都是,先读取SqlServer的数据,经过一番处理,再写入Redis,这里犯了泡茶那样的错误,这些工作都是一步步来的,比如读取数据10秒,处理1秒,写入Redis5秒,每批数据都要耗时16秒,代码简单叙述如下:
while(true){
    // 从SQLServer获取一批数据;
    DataTable dt = "select top(2000) * from tb where id>@lastid order by id"
    if (dt.Rows.Count <= 0)// 没有数据就退出
        break;

    处理数据代码
               
    WriteToRedis(item1.Key, item1.Value);
   
    lastid = (int)dt.Rows[dt.Rows.Count-1]["id"];// 用于获取下一批数据
}

实际上,我们也可以像泡茶那样并行处理,来节约一些时间,微软给我们提供了一个类:System.Threading.ReaderWriterLockSlim
这个类用于管理资源访问的锁定状态,可以实现多线程读取或独占式写入,简单的说,就是对一个数据,读取多个线程一起读取,但是写入只允许独占,也就是在写入时,不允许其它线程来读取或写入,而且必须其它线程的读写操作都完成,才能得到写锁,代码如下:

//全局定义一个读写线程锁
static ReaderWriterLockSlim m_RWLock = new ReaderWriterLockSlim();

while(true){
    // 从SQLServer获取一批数据;
    DataTable dt = "select top(2000) * from tb where id>@lastid order by id"
    if (dt.Rows.Count <= 0)// 没有数据就退出
        break;
    lastid = (int)dt.Rows[dt.Rows.Count-1]["id"];// 用于获取下一批数据

    处理数据代码1(如果SQLServer慢,处理数据代码放入线程)

    //阻塞,直到获取到写锁(写锁只允许一个线程读取数据)
    //只有下面的ReadLock全部释放,这一步才能继续,
    //这样可以读取数据库和写入Redis同步进行,节省读取数据库的时间
    m_RWLock.EnterWriteLock();
    //获取到写锁后,马上释放
    m_RWLock.ExitWriteLock();
   
    // 使用线程写入到Redis
    ThreadPool.UnsafeQueueUserWorkItem(state => {
        try
        {
            //获取读锁, 允许多个线程同时操作Redis
            m_RWLock.EnterReadLock();
            try
            {
                处理数据代码2(如果Redis慢,处理数据代码放EnterWriteLock前面)
               
                WriteToRedis(item1.Key, item1.Value);
            }
            finally
            {
                m_RWLock.ExitReadLock();
            }
        }
        catch (Exception ex)
        {
            LogHelper.WriteException("异常:", ex);
        }
    }, null);
}

 

代码复杂了许多,不过为了效率,忍忍吧,呵呵

发表评论
名称(*):
邮箱:
正文:

©2008 Beinet.cn 版权所有