首页 > 代码库 > Redis处理文件日志并发(二)
Redis处理文件日志并发(二)
多线程操作同一个文件时会出现并发问题。解决的一个办法就是给文件加锁(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()); } } }); }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。