zoukankan      html  css  js  c++  java
  • 《Redis实战》-Josiah L.Carlson 的python的源代码翻译成C# 第二章

        class TestCh02
        {
            public int LIMIT = 10000000;
            public bool QUIT = false;
    
            CSRedisClient _conn;
            public TestCh02()
            {
                _conn = new CSRedis.CSRedisClient("127.0.0.1:6379,defaultDatabase=14,poolsize=500,ssl=false,writeBuffer=10240");
            }
    
            public string check_token(CSRedisClient conn, string token)
            {
                return conn.HGet("login:", token);
            }
    
            public void update_token(CSRedisClient conn, string token, string user, string item = null)
            {
                var timestamp = (DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds;
                conn.HSet("login:", token, user);
                conn.ZAdd("recent:", ((decimal)timestamp, token));
                if (!string.IsNullOrEmpty(item))
                {
                    conn.ZAdd("viewed:" + token, ((decimal)timestamp, item));
                    conn.ZRemRangeByRank("viewed:" + token, 0, -26);
                    conn.ZIncrBy("viewed:", item, -1);
                }
            }
    
            public void clean_sessions(object obj)
            {
                CSRedisClient conn = obj as CSRedisClient;
                while (!QUIT)
                {
                    var size = conn.ZCard("recent:");
                    if (size <= LIMIT)
                    {
                        Thread.Sleep(1000);
                        continue;
                    }
    
                    var end_index = Math.Min(size - LIMIT, 100);
                    var tokens = conn.ZRange("recent:", 0, end_index - 1);
    
                    List<string> session_keys = new List<string>();
                    foreach (var token in tokens)
                    {
                        session_keys.Add("viewed:" + token);
                    }
    
                    conn.Del(session_keys.ToArray());
                    conn.HDel("login:", tokens);
                    conn.ZRem("recent:", tokens);
                }
            }
    
            public void add_to_cart(CSRedisClient conn, string session, string item, int count)
            {
                if (count <= 0)
                    conn.HDel("cart:" + session, item);
                else
                    conn.HSet("cart:" + session, item, count);
            }
    
            public void clean_full_sessions(object obj)
            {
                CSRedisClient conn = obj as CSRedisClient;
                while (!QUIT)
                {
                    var size = conn.ZCard("recent:");
                    if (size <= LIMIT)
                    {
                        Thread.Sleep(1000);
                        continue;
                    }
    
                    var end_index = Math.Min(size - LIMIT, 100);
                    var sessions = conn.ZRange("recent:", 0, end_index - 1);
    
                    List<string> session_keys = new List<string>();
                    foreach (var sess in sessions)
                    {
                        session_keys.Add("viewed:" + sess);
                        session_keys.Add("cart:" + sess);
                    }
    
                    conn.Del(session_keys.ToArray());
                    conn.HDel("login:", sessions);
                    conn.ZRem("recent:", sessions);
                }
            }
    
            public string cache_request(CSRedisClient conn, string request, Func<string, string> callback)
            {
                if (!can_cache(conn, request))
                {
                    return callback(request); ;
                }
    
                var page_key = "cache:" + hash_request(request);
                var content = conn.Get(page_key);
    
                if (string.IsNullOrEmpty(content))
                {
                    content = callback(request);
                    conn.Set(page_key, content, 300);
                }
    
                return content;
            }
    
            public void schedule_row_cache(CSRedisClient conn, string row_id, int delay)
            {
                conn.ZAdd("delay:", (delay, row_id));
                conn.ZAdd("schedule:", ((decimal)(DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds, row_id));
            }
    
            public void cache_rows(object obj)
            {
                CSRedisClient conn = obj as CSRedisClient;
                while (!QUIT)
                {
                    var next = conn.ZRangeWithScores("schedule:", 0, 0);
                    var now = (DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds;
                    if (next != null && next[0].score > (decimal)now)
                    {
                        Thread.Sleep(50);
                        continue;
                    }
    
                    var row_id = next[0].member;
                    var delay = conn.ZScore("delay:", row_id) ?? 0;
                    if (delay <= 0)
                    {
                        conn.ZRem("delay:", row_id);
                        conn.ZRem("schedule:", row_id);
                        conn.Del("inv:" + row_id);
                    }
    
                    var row = new Inventory(row_id);
                    conn.ZAdd("schedule:", ((decimal)now + delay, row_id));
                    conn.Set("inv:" + row_id, Newtonsoft.Json.JsonConvert.SerializeObject(row.to_dict()));
                }
            }
    
            public void rescale_viewed(CSRedisClient conn)
            {
                while (!QUIT)
                {
                    conn.ZRemRangeByRank("viewed:", 20000, -1);
                    conn.ZInterStore("viewed:", new decimal[] { (decimal)0.5 }, RedisAggregate.Max, "viewed:");
                    Thread.Sleep(300000);
                }
            }
    
            public bool can_cache(CSRedisClient conn, string request)
            {
                var item_id = extract_item_id(request);
                if (string.IsNullOrEmpty(item_id) || is_dynamic(request))
                    return false;
    
                var rank = conn.ZRank("viewed:", item_id);
    
                return rank.HasValue && rank.Value < 10000;
            }
    
            public string extract_item_id(string request)
            {
                NameValueCollection nameValueCollection;
                string url;
                UrlHelper.ParseUrl(request, out url, out nameValueCollection);
                return nameValueCollection.Get("item");
            }
    
            public bool is_dynamic(string request)
            {
                NameValueCollection nameValueCollection;
                string url;
                UrlHelper.ParseUrl(request, out url, out nameValueCollection);
                return !string.IsNullOrEmpty(nameValueCollection.Get("_"));
            }
    
            public string hash_request(string request)
            {
                return request.GetHashCode().ToString();
            }
    
            public void tearDown()
            {
                var conn = _conn;
                var to_del = conn.Keys("login:*").Union(conn.Keys("recent:*")).Union(conn.Keys("viewed:*")).Union(conn.Keys("cart:*")).Union(conn.Keys("cache:*")).Union(conn.Keys("delay:*")).Union(conn.Keys("schedule:*")).Union(conn.Keys("inv:*")).ToArray();
                conn.Del(to_del);
    
                QUIT = false;
                LIMIT = 10000000;
            }
    
            public void test_login_cookies()
            {
                var conn = _conn;
                var token = Guid.NewGuid().ToString();
    
                update_token(conn, token, "username", "itemX");
                Console.WriteLine("We just logged-in/updated token:" + token);
                Console.WriteLine("For user:" + "username");
                Console.WriteLine();
    
                Console.WriteLine("What username do we get when we look-up that token?");
                var r = check_token(conn, token);
                Console.WriteLine(r);
                Console.WriteLine();
    
                Console.WriteLine("Let's drop the maximum number of cookies to 0 to clean them out");
                Console.WriteLine("We will start a thread to do the cleaning, while we stop it later");
    
                LIMIT = 0;
                Thread thread = new Thread(new ParameterizedThreadStart(clean_sessions));//创建线程
                thread.Start(conn);                                                           //启动线程
                Thread.Sleep(1000);
                QUIT = true;
                Thread.Sleep(2000);
    
                var s = conn.HLen("login:");
                Console.WriteLine("The current number of sessions still available is:" + s);
            }
    
            public void test_shopping_cart_cookies()
            {
                var conn = _conn;
                var token = Guid.NewGuid().ToString();
    
                Console.WriteLine("We'll refresh our session...");
                update_token(conn, token, "username", "itemX");
                Console.WriteLine("And add an item to the shopping cart");
                add_to_cart(conn, token, "itemY", 3);
                var r = conn.HGetAll("cart:" + token);
                Console.WriteLine("Our shopping cart currently has:" + PrintHelper.Dictionary2String(r));
                Console.WriteLine();
    
                Console.WriteLine("Let's clean out our sessions and carts");
    
                LIMIT = 0;
                Thread thread = new Thread(new ParameterizedThreadStart(clean_full_sessions));//创建线程
                thread.Start(conn);                                                           //启动线程
                Thread.Sleep(1000);
                QUIT = true;
                Thread.Sleep(2000);
    
                r = conn.HGetAll("cart:" + token);
                Console.WriteLine("Our shopping cart now contains:" + PrintHelper.Dictionary2String(r));
            }
    
            public void test_cache_request()
            {
                var conn = _conn;
                var token = Guid.NewGuid().ToString();
    
                Func<string, string> callback = (request) => { return "content for " + request; };
    
                update_token(conn, token, "username", "itemX");
                var url = "http://test.com/?item=itemX";
                Console.WriteLine("We are going to cache a simple request against" + url);
                var result = cache_request(conn, url, callback);
                Console.WriteLine("We got initial content:" + result);
                Console.WriteLine();
    
                Console.WriteLine("To test that we've cached the request, we'll pass a bad callback");
                var result2 = cache_request(conn, url, null);
                Console.WriteLine("We ended up getting the same response!" + result2);
    
            }
    
            public void test_cache_rows()
            {
                var conn = _conn;
    
                Console.WriteLine("First, let's schedule caching of itemX every 5 seconds");
                schedule_row_cache(conn, "itemX", 5);
                Console.WriteLine("Our schedule looks like:");
                var s = conn.ZRangeWithScores("schedule:", 0, -1);
                Console.WriteLine(PrintHelper.ValueTuple2String(s));
    
                Console.WriteLine("We'll start a caching thread that will cache the data...");
                Thread thread = new Thread(new ParameterizedThreadStart(cache_rows));
                thread.Start(conn);
                Thread.Sleep(1000);
                Console.WriteLine("Our cached data looks like:");
                var r = conn.Get("inv:itemX");
                Console.WriteLine(r);
                Console.WriteLine();
                Console.WriteLine("We'll check again in 5 seconds...");
                Thread.Sleep(5000);
                Console.WriteLine("Notice that the data has changed...");
                var r2 = conn.Get("inv:itemX");
                Console.WriteLine(r2);
                Console.WriteLine();
    
                Console.WriteLine("Let's force un-caching");
                schedule_row_cache(conn, "itemX", -1);
                Thread.Sleep(1000);
                r = conn.Get("inv:itemX");
                Console.WriteLine("The cache was cleared?" + r);
                Console.WriteLine();
    
                QUIT = true;
                Thread.Sleep(2000);
            }
    
        }
    
        public class Inventory
        {
            public string id { get; set; }
            public string data { get; set; }
            public decimal cached { get; set; }
            public Inventory(string id)
            {
                this.id = id;
            }
    
            public Inventory get(string id)
            {
                return new Inventory(id);
            }
    
            public Dictionary<string, object> to_dict()
            {
                return new Dictionary<string, object>()
                {
                    { "id", this.id },
                    { "data", "data to cache..."},
                    { "cached", (decimal)(DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds },
                };
            }
    
    
    
        }
    
        public class UrlHelper
        {
            /// <summary>
            /// 分析 url 字符串中的参数信息
            /// </summary>
            /// <param name="url">输入的 URL</param>
            /// <param name="baseUrl">输出 URL 的基础部分</param>
            /// <param name="nvc">输出分析后得到的 (参数名,参数值) 的集合</param>
            public static void ParseUrl(string url, out string baseUrl, out NameValueCollection nvc)
            {
                if (url == null)
                    throw new ArgumentNullException("url");
                nvc = new NameValueCollection();
                baseUrl = "";
                if (url == "")
                    return;
                int questionMarkIndex = url.IndexOf('?');
                if (questionMarkIndex == -1)
                {
                    baseUrl = url;
                    return;
                }
                baseUrl = url.Substring(0, questionMarkIndex);
                if (questionMarkIndex == url.Length - 1)
                    return;
                string ps = url.Substring(questionMarkIndex + 1);
                // 开始分析参数对  
                Regex re = new Regex(@"(^|&)?(w+)=([^&]+)(&|$)?", RegexOptions.Compiled);
                MatchCollection mc = re.Matches(ps);
                foreach (Match m in mc)
                {
                    nvc.Add(m.Result("$2").ToLower(), m.Result("$3"));
                }
            }
    
        }
    View Code

    源码码下载地址 AIStudio.ConSole.Redis (gitee.com)

    作者:竹天笑
    互相学习,提高自己。
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    一个简单的knockout.js 和easyui的绑定
    knockoutjs + easyui.treegrid 可编辑的自定义绑定插件
    Knockout自定义绑定my97datepicker
    去除小数后多余的0
    Windows Azure Web Site (15) 取消Azure Web Site默认的IIS ARR
    Azure ARM (1) UI初探
    Azure Redis Cache (3) 创建和使用P级别的Redis Cache
    Windows Azure HandBook (7) 基于Azure Web App的企业官网改造
    Windows Azure Storage (23) 计算Azure VHD实际使用容量
    Windows Azure Virtual Network (11) 创建VNet-to-VNet的连接
  • 原文地址:https://www.cnblogs.com/akwkevin/p/14064146.html
Copyright © 2011-2022 走看看