Redis处理文件日志并发(2)

多线程操作同一个文件时会出现并发问题。解决的一个办法就是给文件加锁(lock),但是这样的话,一个线程操作文件时,其它的都得等待,这样的话性能非常差。另外一个解决方案,就是先将数据放在队列中,然后开启一个线程,负责从队列中取出数据,再写到文件中。
 public class MyExceptionAttribute : HandleErrorAttribute
    {
        public static IRedisClientsManager ClientManager = new PooledRedisClientManager(new string[] {"127.0.0.1:6379"});
        public static IRedisClient RedisClient = ClientManager.GetClient();
        public override void OnException(ExceptionContext filterContext)
        {
            RedisClient.EnqueueItemOnList("errorException", filterContext.Exception.ToString());//将异常信息存储到Redis队列中了。
            filterContext.HttpContext.Response.Redirect("/error.html");
            base.OnException(filterContext);
        }
    }
 [MyException]
    public class HomeController : Controller
    {
        //
        // GET: /Default1/

        public ActionResult Index()
        {
            int a = 2;
            int b = 0;
            int c = a / b;
            return View();
        }

    }

Global文件

 protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            //通过线程开启一个线程,然后不停的从队列中或数据
            string filePath = Server.MapPath("/Log/");
            ThreadPool.QueueUserWorkItem(x =>
            {
                while (true)
                {
                    try
                    {
                      
                        if (MyExceptionAttribute.RedisClient.GetListCount("errorException") > 0)
                        {
                            string errorMsg = MyExceptionAttribute.RedisClient.DequeueItemFromList("errorException");//从Redis队列中取出异常数据
                            if(!string.IsNullOrEmpty(errorMsg))
                            {
                                //构建成一个完整的路径
                                string fileName = filePath + DateTime.Now.ToString("yyyy-MM-dd").ToString() + ".txt";
                                File.AppendAllText(fileName, errorMsg, Encoding.Default);//将异常写到文件中。
                            }
                            else
                            {
                                Thread.Sleep(30);
                            }
                        }
                        else
                        {
                            Thread.Sleep(30);//避免了CPU空转。
                        }
                    }
                    catch (Exception ex)
                    {

                        MyExceptionAttribute.RedisClient.EnqueueItemOnList("errorException", ex.ToString());
                    }
                }
            });
        }

 

posted @ 2014-06-16 17:13  学亮  阅读(488)  评论(0编辑  收藏  举报