您的位置:新葡亰496net > 奥门新萄京娱乐场 > 新葡亰496net:NET分布式缓存Redis从入门到实战,第

新葡亰496net:NET分布式缓存Redis从入门到实战,第

发布时间:2019-07-28 07:25编辑:奥门新萄京娱乐场浏览(51)

    这段时间一直在研究学习Redis的相关知识,现在大概做下总结吧
    首先,Redis的基础方面,不说配置,就单单说下Redis数据类型:
    Redis 五大数据类型有String 类型,Hash 类型,List 类型,Set 类型,Zset(Sortedset)类型。其中常用的是前三个。
    String 是 redis 最基本的类型,一个key对应一个value。

    一、课程介绍

    今天阿笨给大家带来一堂NOSQL的课程,本期的主角是Redis。希望大家学完本次分享课程后对redis有一个基本的了解和认识,并且熟悉和掌握 Redis在.NET中的使用。本次分享课程包含以下知识点:

    1、StackExchange.Redis (简称:SE)驱动在C#中Redis几种数据结构学习和使用。 

    2、ServiceStack.Redis ( 简称: SS) 驱动在C#中Redis几种数据结构学习和使用。

    3、Redis主从集群服务器搭建和学习。

    4、在ASP.NET中Redis如何进行Session托管。

    5、在C#中如何使用Redis的生产者/消费者。

    6、在C#中如何使用Redis的发布/订阅功能。

    7、在C#中如何使用Redis的事务、锁。

    如果您同样对本次分享《.NET分布式缓存Redis从入门到实战》课程感兴趣的话,那么请跟着阿笨一起学习吧。

    新葡亰496net:NET分布式缓存Redis从入门到实战,第三方帮衬组件总括。废话不多说,直接上干货,我们不生产干货,我们只是干货的搬运工。

    分布式中使用Redis实现Session共享

      上一篇介绍了如何使用 Nginx IIS实现负载均衡 部署一个简单的分布式系统,文章结尾留下了几个问题,其中一个是"如何解决多站点下Session共享"。这篇文章将会介绍如何使用Redis,下一篇在此基础上实现Session。

      这里特别说明一下,其实没有必要使用Redis来解决Session共享。Asp.net提供了StateServer模式来共享Session,这里重复造轮子的目的1:熟悉Redis的基本知识和使用 2.学习和巩固Session的实现原理。3.学习Redis应用场景

    阅读目录

    • Redis安装配置
    • 五种数据类型使用
    • 封装拓展
    • 总结 

      上一篇介绍了如何使用nginx iis部署一个简单的分布式系统,文章结尾留下了几个问题,其中一个是"如何解决多站点下Session共享"。这篇文章将会介绍如何使用Redis,下一篇在此基础上实现Session。

    1. 简介

    hash 是一个键值对集合,和C# 的Dictionary 类似。
    Redis hash 是一个String 类型的 field 和 value 的映射表

    二、概念名称含义解释

    2.1、什么是Redis?

    Redis是一个开源的,使用C语言编写,面向“键/值”对类型数据的分布式NoSQL数据库系统,Redis纯粹为应用而产生,它是一个高性能的key-value数据库,特点是高性能,持久存储,适应高并发的应用场景,并且提供了多种语言的API。

    Redis官网:

    多语言客户端驱动下载:

    2.2、Redis特点

    Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。 与其他 key - value 缓存产品有以下三个特点:

    ● Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。

    ● Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。

    ● Redis支持数据的备份,即master-slave模式的数据备份。

    Redis安装配置

        redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

      最新版本的redis版本为3.0.3,支持集群功能。我这下载的是window版本的,实际场景都是安装在linux系统下的。下载地址:redis-2.8.19.rar 。更多下载地址: 

        官网 :  MSOpenTech:  dmajkic:

        下载完成之后解压运行redis-server.exe就启动了redis了,启动后会在进程里面看到reids。

    新葡亰496net 1

      1.读写分离配置

      redis的读写分离需要修改配置文件,把解压的文件复制了一份。两份文件是一样的,分别命名为MasterRedis-2.8.19(主redis服务),SlaveRedis-2.8.19(从redis服务)。redis默认绑定的是6379端口,

     我们保持主服务配置不变,修改从服务配置。

     新葡亰496net 2

    • 修改从服务绑定端口(修改时可以直接搜索port关键字)

    新葡亰496net 3

    • 修改从服务对应的主服务地址(修改时可以直接搜索slaveof关键字)

     新葡亰496net 4

    • 配置文件修改完成以后,分别启动主服务和从服务

      新葡亰496net 5新葡亰496net 6

        从服务启动以后,主服务会发送一条同步的sync命令,同步从服务器的缓存数据。

      这里特别说明一下,其实没有必要使用Redis来解决Session共享。Asp.net提供了StateServer模式来共享Session,这里重复造轮子的目的1:熟悉Redis的基本知识和使用 2.学习和巩固Session的实现原理。

    Redis简介

    Redis是一个key-value的nosql产品,和memcached类似,但她存储的value类型相对更加丰富,包括string/list(链表)/set(集合)/zset(有序集合)/hash.与memcached一样,为保证效率,数据都是缓存在内存中,区别是redis会周期性把内存中的数据写入到硬盘(数据持久化,安全),由于redis支持的value类型众多,也被称之为结构化的nosql数据库.

    国内社区 www.redis.cn

    List 类型
    Redis列表是采用来链表来存储的简单字符串列表,按照插入顺序排序。添加元素一般从链表两端开始。一般消息队列的应用可以直接使用Redis的List数据类型来做处理。获取最新的10个用户的信息,在list链表中只保留最新的10个数据,每次进来一个新数据就删除一条旧数据,从而实现节约数据资源,减少服务器压力。

    三、Redis For Windows安装手册

    3.1、Redis 在Windows系统上的安装

    官网只提供linux版本的下载官网下载地址:

    windows 版本的github下载地址:

    推荐大家下面几个学习Redis的网站:

    Redis中文网:

    可以在线编写Redis指令的网站:  

    3.2、Redis服务器主从集群的搭建

     

    五种数据类型使用

      服务搭建好以后可以使用.net版本redis操作类库ServiceStack.Redis来操作redis,本文会用到以下三个dll。

    新葡亰496net 7

      初始化RedisClient对象

    var client = new RedisClient("120.26.197.185", 6379);
    

     

    1.String

        String是最常用的一种数据类型,普通的key/value存储都可以归为此类,value其实不仅是String,也可以是数字:比如想知道什么时候封锁一个IP地址(访问超过几次)。INCRBY命令让这些变得很容易,通过原子递增保持计数。 

    #region "字符串类型"
    client.Set<string>("name", "laowang");
    string userName = client.Get<string>("name");
    Console.WriteLine(userName);
    
    //访问次数
    client.Set<int>("IpAccessCount", 0);
    //次数递增
    client.Incr("IpAccessCount");
    Console.WriteLine(client.Get<int>("IpAccessCount"));
    #endregion
    

    新葡亰496net 8

    2.Hash

    一个hashid可以存储多项信息,每一项信息也有自己的key

    client.SetEntryInHash("userInfoId", "name", "zhangsan");
    client.SetEntryInHash("userInfoId", "name1", "zhangsan1");
    client.SetEntryInHash("userInfoId", "name2", "zhangsan2");
    client.SetEntryInHash("userInfoId", "name3", "zhangsan3");
    client.GetHashKeys("userInfoId").ForEach(e => Console.WriteLine(e));
    client.GetHashValues("userInfoId").ForEach(e => Console.WriteLine(e));
    

    新葡亰496net 9

    3.List

      应用场景:  

    •  Redis list的应用场景非常多,也是Redis最重要的数据结构之一。 
    •  我们可以轻松地实现最新消息排行等功能。 
    •  Lists的另一个应用就是消息队列,可以利用Lists的PUSH操作,将任务存在Lists中,然后工作线程再用POP操作将任务取出进行执行。 
     #region "List类型"
    
    client.AddItemToList("userInfoId1", "123");
    client.AddItemToList("userInfoId1", "1234");
    
    Console.WriteLine("List数据项条数:"   client.GetListCount("userInfoId1"));
    Console.WriteLine("List数据项第一条数据:"   client.GetItemFromList("userInfoId1", 0));
    Console.WriteLine("List所有数据");
    client.GetAllItemsFromList("userInfoId1").ForEach(e => Console.WriteLine(e));
    #endregion
    
    #region "List类型做为队列和栈使用"
    Console.WriteLine(client.GetListCount("userInfoId1"));
    //队列先进先出
    //Console.WriteLine(client.DequeueItemFromList("userInfoId1"));
    //Console.WriteLine(client.DequeueItemFromList("userInfoId1"));
    
    //栈后进先出
    Console.WriteLine("出栈" client.PopItemFromList("userInfoId1"));
    Console.WriteLine("出栈" client.PopItemFromList("userInfoId1"));
    #endregion
    

    新葡亰496net 10

    4.Set

      应用场景: 

    • Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。 
    • 比如在微博应用中,每个人的好友存在一个集合(set)中,这样求两个人的共同好友的操作,可能就只需要用求交集命令即可。 
    • Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实 
    client.AddItemToSet("A", "B");
    client.AddItemToSet("A", "C");
    client.AddItemToSet("A", "D");
    client.AddItemToSet("A", "E");
    client.AddItemToSet("A", "F");
    
    client.AddItemToSet("B", "C");
    client.AddItemToSet("B", "F");
    
    //求差集
    Console.WriteLine("A,B集合差集");
    client.GetDifferencesFromSet("A", "B").ToList<string>().ForEach(e => Console.Write(e   ","));
    
    //求集合交集
    Console.WriteLine("nA,B集合交集");
    client.GetIntersectFromSets(new string[] { "A", "B" }).ToList<string>().ForEach(e => Console.Write(e   ","));
    
    //求集合并集
    Console.WriteLine("nA,B集合并集");
    client.GetUnionFromSets(new string[] { "A", "B" }).ToList<string>().ForEach(e => Console.Write(e   ","));
    

    新葡亰496net 11

    5.Sort Set(排序)

      应用场景:

    • 以某个条件为权重,比如按顶的次数排序. 
    • ZREVRANGE命令可以用来按照得分来获取前100名的用户,ZRANK可以用来获取用户排名,非常直接而且操作容易。 
    • Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。 
    • 比如:twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。 
    • 比如:全班同学成绩的SortedSets,value可以是同学的学号,而score就可以是其考试得分,这样数据插入集合的,就已经进行了天然的排序。 
    • 另外还可以用Sorted Sets来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。 
     #region "有序Set操作"
    client.AddItemToSortedSet("SA", "B", 2);
    client.AddItemToSortedSet("SA", "C", 1);
    client.AddItemToSortedSet("SA", "D", 5);
    client.AddItemToSortedSet("SA", "E", 3);
    client.AddItemToSortedSet("SA", "F", 4);
    
    //有序集合降序排列
    Console.WriteLine("n有序集合降序排列");
    client.GetAllItemsFromSortedSetDesc("SA").ForEach(e => Console.Write(e   ","));
    Console.WriteLine("n有序集合升序序排列");
    client.GetAllItemsFromSortedSet("SA").ForEach(e => Console.Write(e   ","));
    
    client.AddItemToSortedSet("SB", "C", 2);
    client.AddItemToSortedSet("SB", "F", 1);
    client.AddItemToSortedSet("SB", "D", 3);
    
    Console.WriteLine("n获得某个值在有序集合中的排名,按分数的升序排列");
    Console.WriteLine(client.GetItemIndexInSortedSet("SB", "D"));
    
    Console.WriteLine("n获得有序集合中某个值得分数");
    Console.WriteLine(client.GetItemScoreInSortedSet("SB", "D"));
    
    Console.WriteLine("n获得有序集合中,某个排名范围的所有值");
    client.GetRangeFromSortedSet("SA", 0, 3).ForEach(e => Console.Write(e   ","));
    
    #endregion
    

    新葡亰496net 12

      3.学习Redis应用场景

    Nosql简介

    web2.0时代,nosql产品非常火热,常见产品如redis/memcached/mongodb.

    nosql产品的特点:不使用严格的表结构,数据查询一般都不再使用sql查询

    世界上正在使用的nosql产品 新葡亰496net:NET分布式缓存Redis从入门到实战,第三方帮衬组件总括。www.nosql-database.org

    Set 类型
    Redis 的 Set 是String类型的无序集合。它是通过HashTable实现实现的,用法和 List类型很相似。因为我们可以根据集合类型来做一些处理比如交并补集,具体应用场景:QQ好友的推荐

    四、Redis几种数据结构

    1、String( 字符串 )

    这是最简单的Redis类型。如果只使用这种类型,Redis就像一个可持久化的Memcached服务器。

    2、List(列表)

    Redis的List是基于双向链表实现的,可以支持反向查找和遍历。

    常用案例:聊天系统、社交网络中获取用户最新发表的帖子、简单的消息队列、新闻的分页列表、博客的评论系统。

    3、Hash( 哈希 )

    Hash是一个String类型的field和value之间的映射表,请见下图,类似于.NET中的Hashtable和Dictionary。主要用来存储对象,可以避免序列化的开销和并发修改控制的问题。

    4、Set( 集合 )

    Set也是一个列表,不过它的特殊之处在于它是可以自动排重的:当需要存储一个列表数据,而又不希望出现重复的时候,Set是一个很好的选择(比如ID的集合)。并且Set提供了判断某个成员是否在一个Set集合内的接口,这也是List所没有的。

    5、Sorted Set(有序集合)

    Sorted Set和Set的使用场景类似,区别是Sorted Set会根据提供的score参数来进行自动排序。当你需要一个有序的并且不重复的集合列表,那么就可以选择Sorted Set数据结构。常用案例:游戏中的排行榜。

    封装拓展

      最后提供一份别人写好的Redis操作的帮助类,用到了PooledRedisClientManager连接池来获取RedisClient,同时用到了读写分离的概念,可以直接拿来使用

    新葡亰496net 13

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using ServiceStack.Redis;
    
    namespace Com.Redis
    {
        /// <summary>
        /// 来源:http://blog.wx6.org/2013/349.htm
        /// </summary>
        public class RedisBase
        {
            private static string[] ReadWriteHosts = System.Configuration.ConfigurationSettings.AppSettings["readWriteHosts"].Split(new char[] { ';' });
            private static string[] ReadOnlyHosts = System.Configuration.ConfigurationSettings.AppSettings["readOnlyHosts"].Split(new char[] { ';' });
    
            #region -- 连接信息 --
            public static PooledRedisClientManager prcm = CreateManager(ReadWriteHosts, ReadOnlyHosts);
    
            private static PooledRedisClientManager CreateManager(string[] readWriteHosts, string[] readOnlyHosts)
            {
                // 支持读写分离,均衡负载  
                return new PooledRedisClientManager(readWriteHosts, readOnlyHosts, new RedisClientManagerConfig
                {
                    MaxWritePoolSize = 5, // “写”链接池链接数  
                    MaxReadPoolSize = 5, // “读”链接池链接数  
                    AutoStart = true,
                });
            }
            #endregion
    
            #region -- Item --
            /// <summary> 
            /// 设置单体 
            /// </summary> 
            /// <typeparam name="T"></typeparam> 
            /// <param name="key"></param> 
            /// <param name="t"></param> 
            /// <param name="timeSpan"></param> 
            /// <returns></returns> 
            public static bool Item_Set<T>(string key, T t)
            {
                try
                {
                    using (IRedisClient redis = prcm.GetClient())
                    {
                        return redis.Set<T>(key, t, new TimeSpan(1, 0, 0));
                    }
                }
                catch (Exception ex)
                {
                    // LogInfo 
                }
                return false;
            }
    
            /// <summary> 
            /// 获取单体 
            /// </summary> 
            /// <typeparam name="T"></typeparam> 
            /// <param name="key"></param> 
            /// <returns></returns> 
            public static T Item_Get<T>(string key) where T : class
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    return redis.Get<T>(key);
                }
            }
    
            /// <summary> 
            /// 移除单体 
            /// </summary> 
            /// <param name="key"></param> 
            public static bool Item_Remove(string key)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    return redis.Remove(key);
                }
            }
    
            #endregion
    
            #region -- List --
    
            public static void List_Add<T>(string key, T t)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    var redisTypedClient = redis.GetTypedClient<T>();
                    redisTypedClient.AddItemToList(redisTypedClient.Lists[key], t);
                }
            }
    
    
    
            public static bool List_Remove<T>(string key, T t)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    var redisTypedClient = redis.GetTypedClient<T>();
                    return redisTypedClient.RemoveItemFromList(redisTypedClient.Lists[key], t) > 0;
                }
            }
            public static void List_RemoveAll<T>(string key)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    var redisTypedClient = redis.GetTypedClient<T>();
                    redisTypedClient.Lists[key].RemoveAll();
                }
            }
    
            public static int List_Count(string key)
            {
                using (IRedisClient redis = prcm.GetReadOnlyClient())
                {
                    return redis.GetListCount(key);
                }
            }
    
            public static List<T> List_GetRange<T>(string key, int start, int count)
            {
                using (IRedisClient redis = prcm.GetReadOnlyClient())
                {
                    var c = redis.GetTypedClient<T>();
                    return c.Lists[key].GetRange(start, start   count - 1);
                }
            }
    
    
            public static List<T> List_GetList<T>(string key)
            {
                using (IRedisClient redis = prcm.GetReadOnlyClient())
                {
                    var c = redis.GetTypedClient<T>();
                    return c.Lists[key].GetRange(0, c.Lists[key].Count);
                }
            }
    
            public static List<T> List_GetList<T>(string key, int pageIndex, int pageSize)
            {
                int start = pageSize * (pageIndex - 1);
                return List_GetRange<T>(key, start, pageSize);
            }
    
            /// <summary> 
            /// 设置缓存过期 
            /// </summary> 
            /// <param name="key"></param> 
            /// <param name="datetime"></param> 
            public static void List_SetExpire(string key, DateTime datetime)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    redis.ExpireEntryAt(key, datetime);
                }
            }
            #endregion
    
            #region -- Set --
            public static void Set_Add<T>(string key, T t)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    var redisTypedClient = redis.GetTypedClient<T>();
                    redisTypedClient.Sets[key].Add(t);
                }
            }
            public static bool Set_Contains<T>(string key, T t)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    var redisTypedClient = redis.GetTypedClient<T>();
                    return redisTypedClient.Sets[key].Contains(t);
                }
            }
            public static bool Set_Remove<T>(string key, T t)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    var redisTypedClient = redis.GetTypedClient<T>();
                    return redisTypedClient.Sets[key].Remove(t);
                }
            }
            #endregion
    
            #region -- Hash --
            /// <summary> 
            /// 判断某个数据是否已经被缓存 
            /// </summary> 
            /// <typeparam name="T"></typeparam> 
            /// <param name="key"></param> 
            /// <param name="dataKey"></param> 
            /// <returns></returns> 
            public static bool Hash_Exist<T>(string key, string dataKey)
            {
                using (IRedisClient redis = prcm.GetReadOnlyClient())
                {
                    return redis.HashContainsEntry(key, dataKey);
                }
            }
    
            /// <summary> 
            /// 存储数据到hash表 
            /// </summary> 
            /// <typeparam name="T"></typeparam> 
            /// <param name="key"></param> 
            /// <param name="dataKey"></param> 
            /// <returns></returns> 
            public static bool Hash_Set<T>(string key, string dataKey, T t)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    string value = ServiceStack.Text.JsonSerializer.SerializeToString<T>(t);
                    return redis.SetEntryInHash(key, dataKey, value);
                }
            }
            /// <summary> 
            /// 移除hash中的某值 
            /// </summary> 
            /// <typeparam name="T"></typeparam> 
            /// <param name="key"></param> 
            /// <param name="dataKey"></param> 
            /// <returns></returns> 
            public static bool Hash_Remove(string key, string dataKey)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    return redis.RemoveEntryFromHash(key, dataKey);
                }
            }
            /// <summary> 
            /// 移除整个hash 
            /// </summary> 
            /// <typeparam name="T"></typeparam> 
            /// <param name="key"></param> 
            /// <param name="dataKey"></param> 
            /// <returns></returns> 
            public static bool Hash_Remove(string key)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    return redis.Remove(key);
                }
            }
            /// <summary> 
            /// 从hash表获取数据 
            /// </summary> 
            /// <typeparam name="T"></typeparam> 
            /// <param name="key"></param> 
            /// <param name="dataKey"></param> 
            /// <returns></returns> 
            public static T Hash_Get<T>(string key, string dataKey)
            {
                using (IRedisClient redis = prcm.GetReadOnlyClient())
                {
                    string value = redis.GetValueFromHash(key, dataKey);
                    return ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(value);
                }
            }
            /// <summary> 
            /// 获取整个hash的数据 
            /// </summary> 
            /// <typeparam name="T"></typeparam> 
            /// <param name="key"></param> 
            /// <returns></returns> 
            public static List<T> Hash_GetAll<T>(string key)
            {
                using (IRedisClient redis = prcm.GetReadOnlyClient())
                {
                    var list = redis.GetHashValues(key);
                    if (list != null && list.Count > 0)
                    {
                        List<T> result = new List<T>();
                        foreach (var item in list)
                        {
                            var value = ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(item);
                            result.Add(value);
                        }
                        return result;
                    }
                    return null;
                }
            }
            /// <summary> 
            /// 设置缓存过期 
            /// </summary> 
            /// <param name="key"></param> 
            /// <param name="datetime"></param> 
            public static void Hash_SetExpire(string key, DateTime datetime)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    redis.ExpireEntryAt(key, datetime);
                }
            }
            #endregion
    
            #region -- SortedSet --
            /// <summary> 
            ///  添加数据到 SortedSet 
            /// </summary> 
            /// <typeparam name="T"></typeparam> 
            /// <param name="key"></param> 
            /// <param name="t"></param> 
            /// <param name="score"></param> 
            public static bool SortedSet_Add<T>(string key, T t, double score)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    string value = ServiceStack.Text.JsonSerializer.SerializeToString<T>(t);
                    return redis.AddItemToSortedSet(key, value, score);
                }
            }
            /// <summary> 
            /// 移除数据从SortedSet 
            /// </summary> 
            /// <typeparam name="T"></typeparam> 
            /// <param name="key"></param> 
            /// <param name="t"></param> 
            /// <returns></returns> 
            public static bool SortedSet_Remove<T>(string key, T t)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    string value = ServiceStack.Text.JsonSerializer.SerializeToString<T>(t);
                    return redis.RemoveItemFromSortedSet(key, value);
                }
            }
            /// <summary> 
            /// 修剪SortedSet 
            /// </summary> 
            /// <param name="key"></param> 
            /// <param name="size">保留的条数</param> 
            /// <returns></returns> 
            public static int SortedSet_Trim(string key, int size)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    return redis.RemoveRangeFromSortedSet(key, size, 9999999);
                }
            }
            /// <summary> 
            /// 获取SortedSet的长度 
            /// </summary> 
            /// <param name="key"></param> 
            /// <returns></returns> 
            public static int SortedSet_Count(string key)
            {
                using (IRedisClient redis = prcm.GetReadOnlyClient())
                {
                    return redis.GetSortedSetCount(key);
                }
            }
    
            /// <summary> 
            /// 获取SortedSet的分页数据 
            /// </summary> 
            /// <typeparam name="T"></typeparam> 
            /// <param name="key"></param> 
            /// <param name="pageIndex"></param> 
            /// <param name="pageSize"></param> 
            /// <returns></returns> 
            public static List<T> SortedSet_GetList<T>(string key, int pageIndex, int pageSize)
            {
                using (IRedisClient redis = prcm.GetReadOnlyClient())
                {
                    var list = redis.GetRangeFromSortedSet(key, (pageIndex - 1) * pageSize, pageIndex * pageSize - 1);
                    if (list != null && list.Count > 0)
                    {
                        List<T> result = new List<T>();
                        foreach (var item in list)
                        {
                            var data = ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(item);
                            result.Add(data);
                        }
                        return result;
                    }
                }
                return null;
            }
    
    
            /// <summary> 
            /// 获取SortedSet的全部数据 
            /// </summary> 
            /// <typeparam name="T"></typeparam> 
            /// <param name="key"></param> 
            /// <param name="pageIndex"></param> 
            /// <param name="pageSize"></param> 
            /// <returns></returns> 
            public static List<T> SortedSet_GetListALL<T>(string key)
            {
                using (IRedisClient redis = prcm.GetReadOnlyClient())
                {
                    var list = redis.GetRangeFromSortedSet(key, 0, 9999999);
                    if (list != null && list.Count > 0)
                    {
                        List<T> result = new List<T>();
                        foreach (var item in list)
                        {
                            var data = ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(item);
                            result.Add(data);
                        }
                        return result;
                    }
                }
                return null;
            }
    
            /// <summary> 
            /// 设置缓存过期 
            /// </summary> 
            /// <param name="key"></param> 
            /// <param name="datetime"></param> 
            public static void SortedSet_SetExpire(string key, DateTime datetime)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    redis.ExpireEntryAt(key, datetime);
                }
            }
            #endregion
        }
    }
    

      View Code

     使用很简单,几行代码

    //会往主服务里面写入
    RedisBase.Hash_Set<string>("PooledRedisClientManager", "one", "123");
    
    //从服务里面读取信息
    RedisBase.Hash_Get<string>("PooledRedisClientManager", "one");
    

      连接池的初始化

            private static string[] ReadWriteHosts = System.Configuration.ConfigurationSettings.AppSettings["readWriteHosts"].Split(new char[] { ';' });
            private static string[] ReadOnlyHosts = System.Configuration.ConfigurationSettings.AppSettings["readOnlyHosts"].Split(new char[] { ';' });
    
            #region -- 连接信息 --
            public static PooledRedisClientManager prcm = CreateManager(ReadWriteHosts, ReadOnlyHosts);
    
            private static PooledRedisClientManager CreateManager(string[] readWriteHosts, string[] readOnlyHosts)
            {
                // 支持读写分离,均衡负载  
                return new PooledRedisClientManager(readWriteHosts, readOnlyHosts, new RedisClientManagerConfig
                {
                    MaxWritePoolSize = 5, // “写”链接池链接数  
                    MaxReadPoolSize = 5, // “读”链接池链接数  
                    AutoStart = true,
                });
            } 
    

      配置文件

    新葡亰496net 14

    阅读目录

    Nosql产品的比较

    • KV存储 redis/memcached

    • 文档存储 mongoDB(JSON)

    Redis是一个KV的nosql产品,数据是在内存中存储,同时支持数据持久化操作,所以这个产品对数据完整性更加的友好.

    Zset 类型
    Redis的zset(sortedset)和set一样也是string类型元素的集合,且不允许有重复的成员。由于是已序集合,可以应用到热门帖子的场景,排序好之后,返回最新的最热的前10个帖子。

    五、Redis应用场景介绍

    总结

      1.其实php,java等多种语言都能使用redis,在我接触的项目中见到使用redis做为消息队列和缓存组件,当然它的功能远不止于此。后面的文章将详细介绍redis的几个使用案例。

          2.可以使用redis desktop manager管理工具查看服务器缓存中的数据

    新葡亰496net 15

          本篇文章用到的redis_demo资源打包下载地址:

    百度网盘下载:

    或者

    ------------------------------------------分割线------------------------------------------

    免费下载地址在

    用户名与密码都是www.bkjia.com

    具体下载目录在 /2015年资料/8月/17日/Nginx IIS实现负载均衡/

    下载方法见

    ------------------------------------------分割线------------------------------------------

    svn下载地址:

    更多详情见请继续阅读下一页的精彩内容:

    • 1
    • 2
    • 下一页

    上一篇介绍了如何使用Nginx IIS实现负载均衡 部署一个简单的分布式系统,文章结尾留下了几个问题,其中...

    • Redis安装配置
    • 五种数据类型使用
    • 封装拓展
    • 总结

    2. Redis的安装

    ubuntu安装redis

    方式1:

    下载地址: https://redis.io/download

    $ wget http://download.redis.io/releases/redis-2.8.17.tar.gz
    $ tar xzf redis-2.8.17.tar.gz
    $ cd redis-2.8.17
    $ make
    
    //启动redis服务
    $ cd src
    $ ./redis-server
    
    //通过启动参数告诉redis使用指定配置文件使用下面命令启动
    $ cd src
    $ ./redis-server redis.conf
    
    //测试客户端程序redis-cli和redis服务交互
    $ cd src
    $ ./redis-cli
    

    方式2:

    //在 Ubuntu 系统安装 Redi 可以使用以下命令:
    $sudo apt-get update
    $sudo apt-get install redis-server
    
    //启动 Redis
    $ redis-server
    
    //查看 redis 是否启动?
    $ redis-cli
    
    //以上命令将打开以下终端:
    redis 127.0.0.1:6379>
    //127.0.0.1 是本机 IP ,6379 是 redis 服务端口。现在我们输入 PING 命令。
    
    redis 127.0.0.1:6379> ping
    PONG
    //以上说明我们已经成功安装了redis。
    

    要在Ubuntu上安装Redis桌面管理器,可从 http://redisdesktop.com/download 下载该软件包

    Redis可视化管理工具 Redis Desktop Manager

    //测试是否启动
    ps aux|grep redis
    
    netstat -tunple|grep 6379
    
    //重启redis
    sudo service redis-server start
    
    //进入redis客户端
    redis-cli
    
    //关闭redis-server
    pkill -9 redis-server
    
    //关闭redis-server服务
    service redis-server stop
    

    ubuntu下为php添加redis扩展

    wget https://github.com/nicolasff/phpredis/zipball/master -o php-redis.zip
    
    
    unzip php-redis.zip
    
    
    cd php-redis
    
    
    phpize
    
    
    sudo apt-get install php-dev
    
    
    makefile:./configure
    
    
    make
    
    
    make install
    

    配置redis-server后台运行

    // 修改redis的配置文件
    sudo vim /etc/redis/redis.conf
    
    // 将守护进程配置项打开
    daemonize yes
    

    对redis的数据类型有足够的了解,可以应用到开发的很多场景,比如消息队列,优先队列,秒杀,最新博客的显示等等。

    六、Redis在.NET中的使用

    回到顶部

    3. Redis数据类型

    .NET对Redis的支持还是很好的。一般我们用Redis来存储Session数据,微软给我们提供了一个第三方组件:RedisSessionStateProvider。微软官方还给我们提供了一个基于redis的内存输出缓存的组件:RedisOutputCacheProvider。所以的第三方redis组件一般都是基于Redis客户端实现的,一般是StackExchange.Redis或是其余的客户端。网上有很多人封装好了基于各个客户端的类,我们可以自己去了解。

    六、Redis实战演练分享

    1、StackExchange.Redis (SE)驱动在C#中Redis几种数据结构学习和使用。 

    2、ServiceStack.Redis (SS) 驱动在C#中Redis几种数据结构学习和使用。

    3、 Redis主从集群服务器搭建和学习。

    4、在ASP.NET中Redis如何进行Session托管。

    5、在C#中如何使用Redis的生产者/消费者。

    6、在C#中如何使用Redis的发布/订阅功能。

    7、在C#中如何使用Redis的事务、锁。

        redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

    3.1 String 字符串类型

    redis中的字符串是一个字节序列,redis中的字符串是二进制安全的,这意味着他们的长度不由任何特殊的终止字符决定.因此可在一个字符串中存储高达512MB的任何内容.

    set name junchow
    
    get name
    

    set和get是redis命令,name是redis中使用的键名

    • set 设置键值对
    • get 通过键名获取键值
    • incr 可对某个key的value进行 1
    • decr 可对某个key的value进行-1
    set age 20
    
    get age
    
    incr age
    
    decr age
    

    incrby 指定键名进行增加

    incrby age 20
    
    get age
    

    decrby 指定键名进行减少

    decrby age 20
    
    get age
    

    keys * 获取所有字键名

    keys *
    

    redis的key是如何设计的呢?

    思考原先在mysql中数据是如何存储的

    • 将mysql表名换成key的前缀
    • 将mysql主键放在前缀后面,一般使用冒号分割.
    • 将对应记录的主键值作为key的值
    • 将mysql其他字段作为key的第四部分

    例如:

    // 将主键id为1名为junchow的用户保存到it表
    it_user:id:1:username junchow
    it_user:id:1:gender 1
    it_user:id:1:email junchow520@gmail.com
    
    // 获取所有字段
    keys it_user:id:1*
    
    // 获取1号用户的姓名
    get it_user:id:1:username
    

    我一开始是使用RedisSessionStateProvider来存储Session的,其实也还是可以的。不过,后来改变了一种方式,我直接调用封装好的StackExchange.Redis类来做Session处理。

    七、源码在线学习和演示

      最新版本的redis版本为3.0.3,支持集群功能。我这下载的是window版本的,实际场景都是安装在linux系统下的。下载地址:redis-2.8.19.rar 。更多下载地址: 

    3.2 Hash 数据类型

    //设置值
    hset userinfo name junchow
    
    //解析
    hset : cmd
    key: userinfo
    value: name junchow
    
    //等价于
    $userinfo = array('name'=>'junchow')
    
    //获取值
    hget userinfo name
    

    redis中的hash类型php中的关联数组

    //设置多个hash值
    hmset userinfo age 30 email junchow520@gmail.com
    
    //获取单个
    hget userinfo age
    hget userinfo email
    
    //获取所有
    hgetall userinfo
    

    源码地址:
    链接: 密码:jeqi

        官网 :  MSOpenTech:  dmajkic:

    3.3 List 链表数据

    链表类型类似于队列或栈的数据结构,链表可视为存储数据的容器.链表的左侧被称为头部,右侧被称为尾部.

    链表可模拟出队列(先进先出),也可以模拟栈(先进后出).

    //从左侧装入 lpush
    lpush link1 A
    lpush link1 B
    

    新葡亰496net 16

    lpush.png

    //从右侧转入 rpush
    rpush link2 A
    rpush link2 B
    

    新葡亰496net 17

    rpush.png

    //获取数据
    lrange link1 0 -1
    //lrange 表示从左侧开始获取link1中,0表示开始位置, -1表示结束位置.
    B A
    
    //从左侧弹出 lpop
    lpop link1
    // 从右侧弹出 rpop
    rpop link1
    

    链表数据结构在实际项目中有那些地方可以使用呢?

    应用场景

    后台要统计一下最近登录的10个用户,使用mysql来完成,形成这样一条sql.

    SELECT * FROM user ORDER BY login_time DESC LIMIT 10;
    

    若使用redis中的链表实现,将用户登录组件的id从左侧存入链表.

    lpush loginuser alice
    lpush loginuser ben
    lpush loginuser carl
    lpush loginuser deny
    lpush loginuser elva
    ...
    

    当链表中存储数据超过10个后

    rpop
    

    参考资料:
    用redis来实现Session保存的一个简单Demo
    Redis 快速入门

        下载完成之后解压运行redis-server.exe就启动了redis了,启动后会在进程里面看到reids。

    3.4 Set 无序集合类型

    集合是数学里面常见概念,是一类无序数据的归总.集合满足三个特点:

    • 无序性:集合中的元素是没有顺序之分的
    • 唯一性:集合中的元素彼此是不能重复的
    • 确定性:集合中的元素个数是确定的

    集合运算

    • 交集:集合之间公共的部分
    • 并集:集合全部的元素
    • 差集

    集合命令

    //向集合setvar添加元素
    sadd setvar 1
    sadd setvar 2
    sadd setvar 3
    
    //从集合setvar中获取元素
    smembers setvar
    
    //判断元素1是否在集合setvar中,成功返回1,失败返回0
    sismember setvar 1
    
    //从集合中移除元素,成功返回1,失败返回0
    srem setvar 1
    
    //从集合中随机弹出元素
    spop setvar
    
    //使用sunion求集合并集
    sunion setvar myset
    

    应用场景

    • QQ中好友标签
    • 社交类型网站中好友关系展示,例如好友推荐,共同好友

    案例分析

    1.设计4个用户

    set sns_user:id:1:username alice
    set sns_user:id:1:email alice520@gmail.com
    
    set sns_user:id:2:username ben
    set sns_user:id:2:email ben520@gmail.com
    
    set sns_user:id:3:username carl
    set sns_user:id:3:email carl520@gmail.com
    
    set sns_user:id:4:username deny
    set sns_user:id:4:email deny520@gmail.com
    
    keys sns_user:id*
    

    2.设计好友的集合

    sadd set:user:id:3:friend 1
    sadd set:user:id:3:friend 2
    
    smembers set:user:id:3:friend
    
    
    sadd set:user:id:2:friend 1
    smembers set:user:id:2:friend
    

    3.获取共同好友

    sinter set:user:id:2:friend set:user:id:3:friend
    

    4.获取所有好友

    sunion set:user:id:2:friend set:user:id:3:friend
    

    5.推荐好友

    sdiff set:user:id:3:friend set:user:id:2:friend
    

    新葡亰496net 18

    3.5 Zset 有序集合类型

    三大特点:

    • 有序性
    • 唯一性
    • 确定性

    有序集合需要给集合中每个元素权重值

    操作命令:

    //添加集合元素
    zadd class:php 1 asion
    zadd class:php 2 mark
    zadd class:php 3 lily
    zadd class:php 4 jack
    
    //获取集合元素
    zrange class:php 0 -1
    
    //获取集合内容时显示权重信息
    zrange class:php 0 -1 withscores
    

    【新手总结】在.Net项目中使用Redis作为缓存服务
    Session分布式共享 = Session Redis Nginx

       1.读写分离配置

    4. PHP操作Redis

    <?php
    $host = '127.0.0.1';
    $port = 6379;
    
    //创建redis连接
    $redis = new redis();
    $connect = $redis->connect($host, $port) or die('redis connect fail!');
    
    //存取KV值
    $key = 'username';
    $val = 'junchow';
    $redis->set($key,$val);
    $val = $redis->get($key);
    
    //删除指定键
    $redis->delete($key);
    
    //若不存在键设置值
    $val = 'zhoujun';
    $redis->setnx($key,$val);
    
    //判断指定键是否存在
    $redis->exists($key);
    
    //递增递减
    $key = 'age';
    $val = 20;
    $redis->incr($key);
    $redis->decr($key);
    
    //打印测试
    var_dump($redis->get($key));
    ?>
    

       redis的读写分离需要修改配置文件,把解压的文件复制了一份。两份文件是一样的,分别命名为MasterRedis-2.8.19(主redis服务),SlaveRedis-2.8.19(从redis服务)。redis默认绑定的是6379端口,

    5. Redis安全问题

    操作redis时,默认无需客户端提供认证信息,即无需密码即可对redis实现操作,这本身是非常危险的,因此有必要开启redis的认证功能.

    1. 修改/etc/redis/redis.conf
    2. 开启 requirepass foobared,默认密码为foobared
    3. 重启redis服务
    sudo pkill -9 redis-server
    
    sudo redis-server /etc/redis/redis.conf
    
    sudo redis-cli -h 127.0.0.1 -p 6379
    //成功登录后认证
    auth foobared
    
    //连接时认证
    sudo redis-cli -h 127.0.0.1 -p 6379 -a foorbared
    

    注意:由于redis.conf中的requirepass保存的是明文,所以要注意redis.conf文件的权限.

    PHP操作Redis - 连接并认证

    <?php
    $host = '127.0.0.1';
    $port = 6379;
    $pass = 'foobared';
    //创建redis连接
    $redis = new redis();
    $redis->connect($host, $port);
    $redis->auth($pass) or die('redis connected fail, please check password!');
    ?>
    

     我们保持主服务配置不变,修改从服务配置。

    6. Redis 的持久化

    redis为了本身数据安全和完整性,会把内存中的数据按一定方式同步到磁盘中,这个过程被称之为持久化操作.当下次再启动redis时会把磁盘上保存的数据重新加载到内存中.
    常见持久化方式由两种:

    • 基于快照的方式 : redis按一定周期将内存中的数据同步到磁盘文件中
    • 基于日志文件的追加 : redis会把数据造成更改的命令记录到日志文件中,再次重启时执行日志文件中的命令,达到数据的还原.

     新葡亰496net 19

    基于快照的持久化

    1. 修改/etc/redis/redis.conf配置文件
    # 若900秒内对键key进行过1次操作,则将内存数据同步到磁盘文件
    save 900 1
    # 若300秒内对键key进行过10次操作,则将内存数据同步到磁盘文件
    save 300 10
    # 若60秒内对键key进行过10000次操作,则将内存数据同步到磁盘文件
    save 60 10000
    

    redis持久化文件保存在哪里呢?

    # The filename where to dump the DB
    dbfilename dump.rdb
    
    # The working directory.
    #
    # The DB will be written inside this directory, with the filename specified
    # above using the 'dbfilename' configuration directive.
    #
    # The Append Only File will also be created inside this directory.
    #
    # Note that you must specify a directory here, not a file name.
    dir /var/lib/redis
    

    保存在 /var/lib/redis/dump.rdb

    可使用bgsave命令手工出发快照持久化

    • 修改从服务绑定端口(修改时可以直接搜索port关键字)

    基于日志追加方式持久化

    修改/etc/redis/redis.conf配置文件,开启基于文件追加模式的持久化.

    appendonly no
    
    # The name of the append only file (default: "appendonly.aof")
    
    appendfilename "appendonly.aof"
    

    appendonly 设置为yes,设置appendfilename追加文件的名称.

    备份文件的周期

    # 只要存在对redis数据造成更改的操作,都要记录到磁盘文件上
    # appendfsync always
    # 每秒进行一次把对redis数据造成更改的操作记录到磁盘
    appendfsync everysec
    # 完全交给操作系统来完成,即操作系统不繁忙的时候会把对redis进行数据造成更改的操作记录到磁盘
    # appendfsync no
    

    重启redis服务

    service redis-server restart
    

    新葡亰496net 20

    • 修改从服务对应的主服务地址(修改时可以直接搜索slaveof关键字)

    新葡亰496net 21

    • 配置文件修改完成以后,分别启动主服务和从服务

      新葡亰496net 22新葡亰496net 23

         从服务启动以后,主服务会发送一条同步的sync命令,同步从服务器的缓存数据。

    回到顶部

       服务搭建好以后可以使用.net版本redis操作类库ServiceStack.Redis来操作redis,本文会用到以下三个dll。

    新葡亰496net 24

      初始化RedisClient对象

    var client = new RedisClient("120.26.197.185", 6379);
    

     

    1.String

        String是最常用的一种数据类型,普通的key/value存储都可以归为此类,value其实不仅是String,也可以是数字:比如想知道什么时候封锁一个IP地址(访问超过几次)。INCRBY命令让这些变得很容易,通过原子递增保持计数。 

    新葡亰496net 25;)

    #region "字符串类型"
    client.Set<string>("name", "laowang");
    string userName = client.Get<string>("name");
    Console.WriteLine(userName);
    
    //访问次数
    client.Set<int>("IpAccessCount", 0);
    //次数递增
    client.Incr("IpAccessCount");
    Console.WriteLine(client.Get<int>("IpAccessCount"));
    #endregion
    

    新葡亰496net 26;)

    新葡亰496net 27

    2.Hash

    一个hashid可以存储多项信息,每一项信息也有自己的key

    client.SetEntryInHash("userInfoId", "name", "zhangsan");
    client.SetEntryInHash("userInfoId", "name1", "zhangsan1");
    client.SetEntryInHash("userInfoId", "name2", "zhangsan2");
    client.SetEntryInHash("userInfoId", "name3", "zhangsan3");
    client.GetHashKeys("userInfoId").ForEach(e => Console.WriteLine(e));
    client.GetHashValues("userInfoId").ForEach(e => Console.WriteLine(e));
    

    新葡亰496net 28

    3.List

      应用场景:

    • Redis list的应用场景非常多,也是Redis最重要的数据结构之一。 
    • 我们可以轻松地实现最新消息排行等功能。 
    • Lists的另一个应用就是消息队列,可以利用Lists的PUSH操作,将任务存在Lists中,然后工作线程再用POP操作将任务取出进行执行。 

    新葡亰496net 29;)

     #region "List类型"
    
    client.AddItemToList("userInfoId1", "123");
    client.AddItemToList("userInfoId1", "1234");
    
    Console.WriteLine("List数据项条数:"   client.GetListCount("userInfoId1"));
    Console.WriteLine("List数据项第一条数据:"   client.GetItemFromList("userInfoId1", 0));
    Console.WriteLine("List所有数据");
    client.GetAllItemsFromList("userInfoId1").ForEach(e => Console.WriteLine(e));
    #endregion
    
    #region "List类型做为队列和栈使用"
    Console.WriteLine(client.GetListCount("userInfoId1"));
    //队列先进先出
    //Console.WriteLine(client.DequeueItemFromList("userInfoId1"));
    //Console.WriteLine(client.DequeueItemFromList("userInfoId1"));
    
    //栈后进先出
    Console.WriteLine("出栈" client.PopItemFromList("userInfoId1"));
    Console.WriteLine("出栈" client.PopItemFromList("userInfoId1"));
    #endregion
    

    新葡亰496net 30;)

    新葡亰496net 31

    4.Set

      应用场景: 

    • Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。 
    • 比如在微博应用中,每个人的好友存在一个集合(set)中,这样求两个人的共同好友的操作,可能就只需要用求交集命令即可。 
    • Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实 

    新葡亰496net 32;)

    client.AddItemToSet("A", "B");
    client.AddItemToSet("A", "C");
    client.AddItemToSet("A", "D");
    client.AddItemToSet("A", "E");
    client.AddItemToSet("A", "F");
    
    client.AddItemToSet("B", "C");
    client.AddItemToSet("B", "F");
    
    //求差集
    Console.WriteLine("A,B集合差集");
    client.GetDifferencesFromSet("A", "B").ToList<string>().ForEach(e => Console.Write(e   ","));
    
    //求集合交集
    Console.WriteLine("nA,B集合交集");
    client.GetIntersectFromSets(new string[] { "A", "B" }).ToList<string>().ForEach(e => Console.Write(e   ","));
    
    //求集合并集
    Console.WriteLine("nA,B集合并集");
    client.GetUnionFromSets(new string[] { "A", "B" }).ToList<string>().ForEach(e => Console.Write(e   ","));
    

    新葡亰496net 33;)

    新葡亰496net 34

    5.Sort Set(排序)

      应用场景:

    • 以某个条件为权重,比如按顶的次数排序. 
    • ZREVRANGE命令可以用来按照得分来获取前100名的用户,ZRANK可以用来获取用户排名,非常直接而且操作容易。 
    • Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。 
    • 比如:twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。 
    • 比如:全班同学成绩的SortedSets,value可以是同学的学号,而score就可以是其考试得分,这样数据插入集合的,就已经进行了天然的排序。 
    • 另外还可以用Sorted Sets来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。 

    新葡亰496net 35;)

     #region "有序Set操作"
    client.AddItemToSortedSet("SA", "B", 2);
    client.AddItemToSortedSet("SA", "C", 1);
    client.AddItemToSortedSet("SA", "D", 5);
    client.AddItemToSortedSet("SA", "E", 3);
    client.AddItemToSortedSet("SA", "F", 4);
    
    //有序集合降序排列
    Console.WriteLine("n有序集合降序排列");
    client.GetAllItemsFromSortedSetDesc("SA").ForEach(e => Console.Write(e   ","));
    Console.WriteLine("n有序集合升序序排列");
    client.GetAllItemsFromSortedSet("SA").ForEach(e => Console.Write(e   ","));
    
    client.AddItemToSortedSet("SB", "C", 2);
    client.AddItemToSortedSet("SB", "F", 1);
    client.AddItemToSortedSet("SB", "D", 3);
    
    Console.WriteLine("n获得某个值在有序集合中的排名,按分数的升序排列");
    Console.WriteLine(client.GetItemIndexInSortedSet("SB", "D"));
    
    Console.WriteLine("n获得有序集合中某个值得分数");
    Console.WriteLine(client.GetItemScoreInSortedSet("SB", "D"));
    
    Console.WriteLine("n获得有序集合中,某个排名范围的所有值");
    client.GetRangeFromSortedSet("SA", 0, 3).ForEach(e => Console.Write(e   ","));
    
    #endregion
    

    新葡亰496net 36;)

    新葡亰496net 37

    回到顶部

      最后提供一份别人写好的Redis操作的帮助类,用到了PooledRedisClientManager连接池来获取RedisClient,同时用到了读写分离的概念,可以直接拿来使用

    新葡亰496net 38新葡亰496net 39

    新葡亰496net 40;)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using ServiceStack.Redis;
    
    namespace Com.Redis
    {
        /// <summary>
        /// 来源:http://blog.wx6.org/2013/349.htm
        /// </summary>
        public class RedisBase
        {
            private static string[] ReadWriteHosts = System.Configuration.ConfigurationSettings.AppSettings["readWriteHosts"].Split(new char[] { ';' });
            private static string[] ReadOnlyHosts = System.Configuration.ConfigurationSettings.AppSettings["readOnlyHosts"].Split(new char[] { ';' });
    
            #region -- 连接信息 --
            public static PooledRedisClientManager prcm = CreateManager(ReadWriteHosts, ReadOnlyHosts);
    
            private static PooledRedisClientManager CreateManager(string[] readWriteHosts, string[] readOnlyHosts)
            {
                // 支持读写分离,均衡负载  
                return new PooledRedisClientManager(readWriteHosts, readOnlyHosts, new RedisClientManagerConfig
                {
                    MaxWritePoolSize = 5, // “写”链接池链接数  
                    MaxReadPoolSize = 5, // “读”链接池链接数  
                    AutoStart = true,
                });
            }
            #endregion
    
            #region -- Item --
            /// <summary> 
            /// 设置单体 
            /// </summary> 
            /// <typeparam name="T"></typeparam> 
            /// <param name="key"></param> 
            /// <param name="t"></param> 
            /// <param name="timeSpan"></param> 
            /// <returns></returns> 
            public static bool Item_Set<T>(string key, T t)
            {
                try
                {
                    using (IRedisClient redis = prcm.GetClient())
                    {
                        return redis.Set<T>(key, t, new TimeSpan(1, 0, 0));
                    }
                }
                catch (Exception ex)
                {
                    // LogInfo 
                }
                return false;
            }
    
            /// <summary> 
            /// 获取单体 
            /// </summary> 
            /// <typeparam name="T"></typeparam> 
            /// <param name="key"></param> 
            /// <returns></returns> 
            public static T Item_Get<T>(string key) where T : class
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    return redis.Get<T>(key);
                }
            }
    
            /// <summary> 
            /// 移除单体 
            /// </summary> 
            /// <param name="key"></param> 
            public static bool Item_Remove(string key)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    return redis.Remove(key);
                }
            }
    
            #endregion
    
            #region -- List --
    
            public static void List_Add<T>(string key, T t)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    var redisTypedClient = redis.GetTypedClient<T>();
                    redisTypedClient.AddItemToList(redisTypedClient.Lists[key], t);
                }
            }
    
    
    
            public static bool List_Remove<T>(string key, T t)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    var redisTypedClient = redis.GetTypedClient<T>();
                    return redisTypedClient.RemoveItemFromList(redisTypedClient.Lists[key], t) > 0;
                }
            }
            public static void List_RemoveAll<T>(string key)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    var redisTypedClient = redis.GetTypedClient<T>();
                    redisTypedClient.Lists[key].RemoveAll();
                }
            }
    
            public static int List_Count(string key)
            {
                using (IRedisClient redis = prcm.GetReadOnlyClient())
                {
                    return redis.GetListCount(key);
                }
            }
    
            public static List<T> List_GetRange<T>(string key, int start, int count)
            {
                using (IRedisClient redis = prcm.GetReadOnlyClient())
                {
                    var c = redis.GetTypedClient<T>();
                    return c.Lists[key].GetRange(start, start   count - 1);
                }
            }
    
    
            public static List<T> List_GetList<T>(string key)
            {
                using (IRedisClient redis = prcm.GetReadOnlyClient())
                {
                    var c = redis.GetTypedClient<T>();
                    return c.Lists[key].GetRange(0, c.Lists[key].Count);
                }
            }
    
            public static List<T> List_GetList<T>(string key, int pageIndex, int pageSize)
            {
                int start = pageSize * (pageIndex - 1);
                return List_GetRange<T>(key, start, pageSize);
            }
    
            /// <summary> 
            /// 设置缓存过期 
            /// </summary> 
            /// <param name="key"></param> 
            /// <param name="datetime"></param> 
            public static void List_SetExpire(string key, DateTime datetime)
            {
                using (IRedisClient redis = prcm.GetClient())
                {
                    redis.ExpireEntryAt(key, datetime);
                }
            }
            #endregion
    

    本文由新葡亰496net发布于奥门新萄京娱乐场,转载请注明出处:新葡亰496net:NET分布式缓存Redis从入门到实战,第

    关键词:

上一篇:新葡亰496net:递归解法

下一篇:没有了