.net core 中 Redis 入门

1.Redis基础

1.Redis是REmote DIctionary Servey(远程字典服务的缩写),他是以字典结构储存数据。Redis数据库中的键值除了可以是字符串,还可以还是:字符串,hash,list。set 。zset 类型


2.使用命令行操作

  • string类型 设置值set k1 v1
  • string 类型 获取值 get k1
  • string 类型 设置多个set ,获取多个get。。即
    mset k1 v1 k2 v2 k3 v3
    mget k1 k2 k3
  • hash 类型进行设置
    hset h1 name li
  • 对于hash 值也可以同时设置多个值
    hmset h1 name li age 18
    hgetall 获取所有的值
  • 对于List类型
    lpush L1 v1 :在左边给L1数组添加v1
    lrange L1 0 -1 : 借鉴了Python的用法 -1表示最后一个
  • 对于set 类型
    sadd S1 V1 : 添加值
    smembers S1 : 获取值

订阅者发布者模式:

直接结果如下图(很简单):
发布者只要一发布消息,所有的订阅者都能收到;
在这里插入图片描述

Redis 在.net core 中的使用

1.redis文件夹中相关文件的使用
在这里插入图片描述

引用第三方包:
在这里插入图片描述

2.使用 Redis 中的 string 命令:

  using (RedisClient client=new RedisClient("127.0.0.1",6379))
            {
                //删除所有的key,默认删除的是DB0
                client.FlushDb();
                //删除所有数据库中的key
                //Flush 冲洗所有
                client.FlushAll();
                client.Set<string>("名字", "朝夕教育",TimeSpan.FromSeconds(1));//过期时间一分钟.
                Console.WriteLine("正确的输出如下:");
                Console.WriteLine(client.Get<string>("名字"));

                #region 设置多个key

                //批量的读写:
                client.SetAll(new Dictionary<string, string>
                {
                    { "id","001"},
                    {"name","zhao" }
                });
                var getall =
                    client.GetAll<string>(new string[] { "id", "name", "number" });
                foreach (var item in getall)
                {
                    Console.WriteLine(item);
                } 
                #endregion
            }

3.用 Redis 实现秒杀的小例子

秒杀中存在的困境:要在数据库中获取出售的商品数量。容易超卖

解决方案:

  • 给数据库加锁,相当于把多线程工作改成单线程了
  • Redis 本身就是单线程服务

注意:

  1. 多线程一定比单行程快?(错)
  2. redis 是一个分布式的数据库,数据在多个客户端上共享。

用redis实现秒杀的小例子

public static void Show(string id, int minute)
        {
            Console.WriteLine($"在{minute}分0秒正式开始秒杀");
            bool  flag = true;
            while (flag)
            {
                if (DateTime.Now.Minute==minute)
                {
                    flag = false;
                    for (int i = 0; i < 10; i++)
                    {
                        string name = $"客户端{id}号:{i}";
                        Task.Run(() =>
                        {
                            using (RedisClient client = new RedisClient("127.0.0.1", 6379))
                            {
                                //把取数据和减数量变为同一条指令;
                                var num = client.Decr("number");
                                //var num1 = client.Incr("number");  这个是自增操作;
                                if (num<0)
                                {
                                    Console.WriteLine(name+"**********抢购失败");

                                }
                                else
                                {
                                    Console.WriteLine(name+"************抢购成功");            
                                }
                            }
                        });
                        Thread.Sleep(10);
        }} } }

Redis的使用场景

  • 秒杀场景
  • Redis计数器。。当有人恶意访问时,控制一分钟只能处理1000个请求,
  • 因为关系型数据库是放在磁盘里面的,读取速度过慢,所以可以先用redis记录,然后每隔5分钟,往数据库里面记录一次。
  • set 类型的数据,可以应用于微博点赞

用string做缓存的都是菜鸟。现在都用 hash

1.hash的键值只能是字符串:
在这里插入图片描述

要想批量读取或者写入 hash ,要先建立一个 字典
使用hash记录数据,具体代码如下:

 using (RedisClient client = new RedisClient("127.0.0.1", 6379))
            {
                client.FlushDb();
                client.FlushAll();

                string people = "zhao de peng";
                client.SetEntryInHash(people,"id","001");
                Console.WriteLine("下边是进来以后的打印结果");
                Console.WriteLine(client.GetValuesFromHash(people,"id").FirstOrDefault());

                client.SetEntryInHash(people,"age","20"); 
                Console.WriteLine(client.GetValuesFromHash(people,"age").FirstOrDefault());

                client.SetEntryInHash(people,"score","100");
                Console.WriteLine(client.GetValuesFromHash(people,"score").FirstOrDefault());
                Console.WriteLine("@@@@@@@@@@@@@@@@@@@@@@@@@@@@");


                #region 批量新增 Key 值
                string www = "zhao_peng";
                Dictionary<string, string> pairs = new Dictionary<string, string>();
                pairs.Add("id01","008");
                pairs.Add("name01", "zhao");
                client.SetRangeInHash(www,pairs);
                //如果要带s的话就加上这句话
                Console.WriteLine(client.GetValuesFromHash(www,"id01").FirstOrDefault());
                Console.WriteLine(client.GetValueFromHash(www,"name01"));
                var list = client.GetValuesFromHash(www, "id01", "name01");
                Console.WriteLine("****************");
                foreach (var item in list)
                {
                    Console.WriteLine(item);
                }
                #endregion
            }

使用hash后的结果:

在这里插入图片描述

Set 类型的数据

可用于防止微博或者朋友圈重复点赞,

set设置以后是这样的
在这里插入图片描述

交集和并集 关于 set 具体代码如下:

  public static void Show()
        {
            #region  Set 不重复的集合
            using (RedisClient client = new RedisClient("127.0.0.1", 6379))
            {
                client.FlushDb();
                client.FlushAll();
                string key = "set_name";

                var litaibai = new UserInfo() { Id = 1, Name = "李白" };
                client.AddItemToSet(key, JsonConvert.SerializeObject(litaibai));
                Console.WriteLine("已经写成功了");

                Console.WriteLine("set 开始了");
                client.AddRangeToSet
                (key, new List<string>() { "001", "001", "002", "003", "004", "005", "005", "006" });
                
                Console.WriteLine(client.GetSetCount(key));
            }
            #endregion

            #region 并集
            using (RedisClient client = new RedisClient("127.0.0.1", 6379))
            {
                client.FlushDb();
                client.FlushAll();
                string keyone = "keyOne";
                string keyTwo = "keyTwo";
                client.AddRangeToSet(keyone, new List<string>() { "001", "002", "003", "004" });
                client.AddRangeToSet(keyTwo, new List<string>() { "001", "002", "003", "005" });
                var unionlist = client.GetUnionFromSets("keyOne", "keyTwo");
                Console.WriteLine("返回并集结果");
                foreach (var item in unionlist)
                {
                    Console.WriteLine(item);
                }
                Console.WriteLine(client.GetSetCount(keyone));
            }
            #endregion

            #region 交集
            using (RedisClient client = new RedisClient("127.0.0.1", 6379))
            {
                client.FlushDb();
                client.FlushAll();
                string keyone = "keyOne";
                string keyTwo = "keyTwo";
                
                client.AddRangeToSet
                (keyone, new List<string>() { "001", "002", "003", "004" });
                
                client.AddRangeToSet
                (keyTwo, new List<string>() { "001", "002", "003", "005" });
                //核心就是下边这一句
                var unionlist = client.GetIntersectFromSets("keyOne", "keyTwo");
                Console.WriteLine("返回并集结果");
                
                foreach (var item in unionlist)
                {
                    Console.WriteLine(item);
                }
                Console.WriteLine(client.GetSetCount(unionlist.ToString()));
            }
            #endregion    }
    }

Zset 设置的时候会有个分数,最后会根据分数进行排序

  #region Zset
            using (RedisClient client = new RedisClient("127.0.0.1", 6379))
            {
                client.FlushDb();
                client.FlushAll();
                string Zset_key = "keyOne";
                //Zset 会有个默认的分数,最后会根据分数来排序
                client.AddItemToSortedSet(Zset_key,"ccc",33);
                Console.WriteLine("ok");           
            }
            #endregion

List 的使用

list也是只有值(只有string是一行,其他的都是表)
在这里插入图片描述

list可以根据其特性,实现秒杀的功能(分布式缓存,就算是后台挂了也没事)

(1)Client 端的使用

 public static void Show(string id, int  minute)
        {
            Console.WriteLine($"在{minute}分0秒进行秒杀");
            var flag = true;
            while (flag)
            {
                // if (DateTime.Now.Minute == minute)
                Console.WriteLine(DateTime.Now.Minute);
                if (DateTime.Now.Minute==minute)
                {
                    flag = false;
                    for (int i = 0; i < 100; i++)
                    {
                        string name = $"id为{id}客户端的第{i}次抢购";
                        Console.WriteLine(name);
                        Task.Run(() =>
                        {
                            using (RedisClient client = new RedisClient("127.0.0.1", 6379))
                            {
                                OrderInfo orderInfo = new OrderInfo()
                                {
                                    ID = name,
                                    OrderTime = DateTime.Now.ToString("yyyy-mm-dd-hh:mm:ss:fff")
                                };

                                string YonghuList = "User";
                                //加到队列里面;
                                client.AddItemToList(YonghuList, JsonConvert.SerializeObject(orderInfo));
                                Console.WriteLine($"{name}恭喜你,已经下单成功了");
                            }
                        } );
                        Thread.Sleep(1000);
     }} } }

2.Server端:

using (RedisClient client = new RedisClient("127.0.0.1", 6379))
                    {
                        OrderInfo orderInfo = new OrderInfo();
                        while (true)
                        {
                            string YonghuList = "User";
                            //是移除,start 注意
                            var listvalue = client.RemoveStartFromList(YonghuList);
                            if (!string.IsNullOrWhiteSpace(listvalue))
                            {
                                //串行化是指:把对象存储到介质中(比如文件),以二进制的方式通过网络传输;
                                //反串行化指:从这些连续的数据中重构一个与原始对象相同的对象;
                                var order = JsonConvert.DeserializeObject<OrderInfo>(listvalue);
                                //下班 就可以做业务处理了。
                                Console.WriteLine("已经处理完的单子" + listvalue);
                                //Console.WriteLine($"消费完成:{order.ID}消费的时间{order.OrderTime}");
                            }
                            else
                            {
                                break;
                            }
                            Thread.Sleep(1000);
                        }
                    } 

题外话

  1. using 的用法: 在某个代码片段中使用了类的实例,但是希望无论何时什么原因,只要离开了代码段。这个类的实例就会被 dispose 掉

using(建立一个新类)
{
对类做点东西
}

  1. JsonConvert.SerialixeObject () 是序列化成Json格式,但是本质依然是字符串格式:

  2. 3.字典类型:字典名字就是个 table 的表明: 里面存放的还是键值对,想要取出来,无论往里放什么东西,都是键值对的格式,用JsonConvert.SerialixeObject()也一样,就要用 foreach 循环。

  3. Hash 的话有 key - value 的键值对,如果没有的话,只有一个value。用redis Desktop Manager工具看到的最前边的序号,是自动生成的。什么用处我还不清楚;

  4. 匿名类的话,是 new 后边直接加 { }; 后边带()的这种 new class () ,是在声明类的同时给他赋值.。

参考文献

https://www.bilibili.com/video/BV1kg4y1i7mN/

posted @ 2020-07-26 10:57  沧海一声笑rush  阅读(104)  评论(0编辑  收藏  举报