• 高并发之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 放到一个池子里,永远保证这个池子里有值
    六度与心 修行苦 苦修行
  • 相关阅读:
    2020年封装APP之详解
    Linux 强制卸载硬盘 (Device is busy)
    pacman 非交互状态使用
    Snakemake 修改默认工作目录
    LaTeX 表格排版中遇到 Misplaced oalign
    重启崩溃的 KDE
    python robot.libraries.BuiltIn import BuiltIn库
    logging 常用配置
    paramiko 获取远程服务器文件
    物理时间使用Python脚本转格林卫时间
  • 原文地址:https://www.cnblogs.com/hdtechnology/p/8732671.html
Copyright © 2020-2023  润新知