• 高并发之config


    对于config的读取,再熟悉不过了,通常的写法如下:

    //1. read from cache
    string configvalue = GetFromCache(configKey);
    if(!configValue.IsNullOrEmpty()){
        return configValue;
    }
    
    //2. read from db
    configValue = GetFromDb(configKey);
    if(configValue.IsNullOrEmpty()){
        // set to cache 30s
        retrun config;
    }

    这种写法在普通的场景下,完全是可行的 先从cache中读,再从db中读取,设置30s缓存时间

    但当遇到高并发的场景下: 即如果瞬时有10000个或更多的请求,来读取这个config,恰巧碰到,30s过期的临界值。此时全部的请求压力就会转向db,缓存就会miss。

    这里有个概念:

    滑动过期 :即config 从本地内存中读取,同时开启一个定时器,定时从cache中同步config到本地内存中

    public class ConfigFacade
        {
            private const int FRESHEN_INTERVAL = 30 * 1000;
            private static readonly ConcurrentDictionary<string, string> localCache = new ConcurrentDictionary<string, string>();
            private static Timer _timer;
            static ConfigFacade()
            {
                Console.WriteLine("timer start ...");
                _timer = new Timer(state => LoadConfig(), null, FRESHEN_INTERVAL, FRESHEN_INTERVAL);
            }
    
            private static void LoadConfig()
            {
                //sync configvalue to localcache
                foreach (var key in localCache.Keys)
                {
                    var configValue = GetConfigFromClient(key);
                    var tryUpdateValue = localCache.TryUpdate(key, configValue, localCache[key]);
                    Console.WriteLine("now : {0}", DateTime.Now);
                    Console.WriteLine("update key :{0} , {1}", key, tryUpdateValue);
                }
            }
    
            public static string GetConfig(string key)
            {
                string value;
                if (localCache != null && localCache.Count > 0 && localCache.ContainsKey(key))
                {
                    var tryGetValue = localCache.TryGetValue(key, out value);
                    if (tryGetValue)
                    {
                        return value;
                    }
                }
    
                value = GetConfigFromClient(key);
                localCache.TryAdd(key, value);
                return value;
            }
    
            private static string GetConfigFromClient(string key)
            {
                // 1. from redis 
                // 2. from db 
                Console.WriteLine("key => {0} ,get value form client", key);
                return string.Format("{0}_value", key);
            }
        }

    优点

    1. 每次并发的读取都能保证是读取本地内存,定时器会定时的去同步缓存到本地内存
    2. 这种处理问题的思路 类似于将config 放到一个池子里,永远保证这个池子里有值
    六度与心 修行苦 苦修行
  • 相关阅读:
    Flutter——Text组件(文字组件)
    Dart的导包
    Dart 面向对象 类 方法
    Dart中的匿名方法与自执行方法
    Dart的List比较特殊的几个API
    SearchView监听关闭正确方案
    Android选择多图上传
    ListView嵌套ScrollView会出现的问题
    禁用ViewPager的滑动事件
    SQLite相关异常
  • 原文地址:https://www.cnblogs.com/hdtechnology/p/8732671.html
Copyright © 2020-2023  润新知