Redis

2 篇文章 0 订阅
1 篇文章 0 订阅

Redis_全称(Remote Dictionary Server)远程字典服务

1.Redis的用处与使用场景?

Redis是NOSQL(Not Only SQL 非关系型数据库)中的一种常用的缓存(内存)数据库.

应对高并发时可以进行数据缓存,减轻我们服务器直接操作硬盘的压力.因为当Web获取数据时,是去直接操作数据库的,就等于去直接操作服务器硬盘进行IO操作,而IO操作非常耗费服务器性能,这时我们可以将需要Web需要读取的数据,放到Redis中,而Redis是将数据放到内存中,而内存的效率,比直接访问硬盘的效率高很多,以此来达到减轻服务器压力的目的.

PS: Redis的处理速度,可以达到一秒钟十万的速度.

2.NoSQL数据库的优点与适应场景以及不适应场景?

优点:

1.NoSQL数据库没有关联关系,数据结构简单,拓展表比较容易.
2.NOSQL读取速度快,对较大数据处理快.

适用场景:

1.    数据高并发的读写
2.    海量数据的读写
3.    对扩展性要求高的数据

不适应场景:

1.    需要事务支持(非关系型数据库)
2.    基于sql结构化查询储存,关系复杂
 

Redis的各种用途以及使用场景 - 宋晓华 - 博客园

2.1 Redis优点:

1.    方便扩展
2.    大数据量高性能
3.    数据存储类型多样性
4.    自带分布式存储

2.2 Redis 八种存储类型:

String(字符串)丶List(集合)丶Hash(哈希)丶Set(去重集合)丶Zset(有序的去重集合)丶BitMaps丶HyperLogLoss丶Streams

3. 使用.Net Core5的 控制台程序来了解Redis的存储类型

1.从Nuget管理包中 安装  ServiceStack.Redis 来帮助我们连接Redis.

 3.1  控制台程序测试Redis类型的方法

using Microsoft.VisualBasic;
using Newtonsoft.Json;
using ServiceStack;
using ServiceStack.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
using TechnicalSummary_Core.RedisTest.RedisModel;

namespace TechnicalSummary_Core.RedisTest
{
    class RedisStringTest
    {
        static void Main(string[] args)
        {

            //    实例化Redis连接      参数:1.IP地址  2.端口号   参数 db可以指定 1-15 中的任意数据库
            using (IRedisClient client = new RedisClient("127.0.0.1", 6379))
            {
                string DaKey = "总KEY";  // 与对象名概念相似
                client.FlushDb();  // 清空Redis中所有数据

                #region Redis_String
                #region String_单个添加与读取
                // 删除 当前数据库中的所有Key 
                ///client.FlushDb();
                // 新增 Key
                ///client.Set<string>("User", "wxh");


                // 获取     指定名称的Key
                // 推荐,因为默认帮我们做了反序列化
                ///client.Get<string>("User");
                ///Console.WriteLine(client.Get<string>("User"));
                // 不建议使用GetValue,因为多了两个双引号,如果使用需要 DeserializeObject 反序列化
                ///client.GetValue("User"); 
                ///Console.WriteLine(JsonConvert.DeserializeObject<string>(client.GetValue("User")));
                #endregion

                #region String_批量操作
                // 批量添加
                ///Dictionary<string, string> keyValues = new Dictionary<string, string>();
                ///keyValues.Add("Name", "晓亨");
                ///keyValues.Add("age", "18");
                ///client.SetAll(keyValues); 

                // 批量获取
                ///IDictionary<string,string> getKeys = client.GetAll<string>(new string[] { "Name", "age" });
                ///foreach (var item in getKeys)
                ///{
                ///Console.WriteLine(item.Value);
                ///}
                #endregion

                #region String_设置过期时间
                // 10秒后过期
                ///client.Set<string>("User", "吴晓亨", TimeSpan.FromSeconds(10));
                // 等待十秒,十秒后获取值
                ///Task.Delay(10000).Wait();
                // 如果没有数据时,则返回 ""
                ///Console.WriteLine(client.Get<string>("User"));



                // 指定日期过期         在明天的这时过期
                client.Set<string>("User", "吴晓亨", DateTime.Now.AddDays(1));

                #endregion

                #region String_往某个指定 Key 后追加内容
                // 往 name 后追加 I,如果找不到则等于新建了name
                ///client.AppendToValue("name", "I");
                ///Console.WriteLine(client.Get<string>("name"));
                ///client.AppendToValue("name", " Love  ");
                ///client.AppendToValue("name", "U");
                ///Console.WriteLine(client.Get<string>("name"));
                #endregion

                #region String_获取 Key 原来的值(Value),并附上新值(Value) GetAndSetValue(),取出来的值需要反序列化,要不然是""
                ///client.Set<string>("Name", "吴晓亨");
                //  GetAndSetValue 需要 反序列化 JsonConvert.DeserializeObject
                ///Console.WriteLine(JsonConvert.DeserializeObject(client.GetAndSetValue("Name","新的吴晓亨")));
                ///Console.WriteLine(client.Get<string>("Name"));
                #endregion、

                #region Int_自增,自减
                // 自增 未新增过Count时,默认从0开始自增
                ///client.Increment("Count", 1);
                ///Console.WriteLine(client.Get<int>("Count")); // 1
                ///client.Increment("Count", 1);
                ///client.IncrementValueBy("Count", 1); // 意思与 Increment 一致.
                /// Console.WriteLine(client.Get<int>("Count")); // 3

                // 自减 未新增过Count时,默认从0开始自减
                ///client.Decrement("Count2", 1);
                ///Console.WriteLine(client.Get<int>("Count2")); // -1
                ///client.Decrement("Count2", 1);
                ///client.Decrement("Count2", 1);
                ///Console.WriteLine(client.Get<int>("Count2")); // -3



                #endregion

                #region Add 与 Set 的区别.
                // Add 返回 True 则为添加成功.如果数据库中有这个 Key 存在,则返回False,新增失败.  我这抛出异常了
                ///Console.WriteLine(client.Add<string>("name", "WXH"));
                ///Console.WriteLine(client.Add<string>("userInfo", "WXH2"));

                // Set 返回 True,如果数据库中有这个 Key 存在则将之前的值给替换了.
                ///Console.WriteLine(client.Set<string>("userInfo", "WXH"));
                ///Console.WriteLine(client.Set<string>("userInfo", "WXH2"));
                #endregion

                #region 查看数据库中是否存在这个Key,返回boolean值
                ///Console.WriteLine(client.ContainsKey("name"));
                ///Console.WriteLine(client.Get<string>("name"));
                #endregion

                #region 传入Key 查看是Redis八种类型的那种类型.
                /// Console.WriteLine(client.GetEntryType("name")); // string 类型
                #endregion
                #endregion

                #region Redis_HashTable_哈希表
                /* 
                 * 注释: Hash表在Redis中存储方式类似于对象,首先有一个大 Key,可以往 大 Key下面, 添加N多个 小Key.
                 */
                #region Hash_新增(选择性新增)与  获取
                // 新增    参数:1.就当成对象名(大Key) 2.小Key名称(属性名) 3.小Key值(属性值) 
                ///client.SetEntryInHash(DaKey, "小key1", "小KeyValue1");

                // 获取           参数:1.就当成对象名(大Key) 2.小Key名称(属性名) 
                ///Console.WriteLine(client.GetValueFromHash(DaKey, "小key1"));

                //  判断大key中是否存在相同的 K/V,如果存在则返回False并且 新增失败,不存在则返回True 并新增成功.
                //  SetEntryInHashIfNotExists 参数:1.大Key名称   2.小Key名  3.小Key值
                ///Console.WriteLine(client.SetEntryInHashIfNotExists(DaKey, "小key1", "小KeyValue1")); // 已经存在 False  
                ///Console.WriteLine(client.SetEntryInHashIfNotExists(DaKey, "小Key2", "小KeyValue2")); // 不存在 true
                ///Console.WriteLine(client.SetEntryInHashIfNotExists(DaKey, "小Key2", "小KeyValue1")); // Key存在Values不存在 False
                #endregion

                #region Hash_批量操作
                // 批量添加
                Dictionary<string, string> dakeys = new Dictionary<string, string>();
                dakeys.Add("Key1", "Value1");
                dakeys.Add("Key2", "Value2");
                dakeys.Add("number", "1");
                client.SetRangeInHash(DaKey, dakeys);

                // 获取 大Key 下的所有值
                ///Dictionary<string,string> dics =  client.GetAllEntriesFromHash(DaKey);
                ///foreach (var item in dics)
                ///{
                ///Console.WriteLine(item.Key);
                /// }
                #endregion

                #region Hash_操作对象,对象与大KEY平级
                /*
                 模拟场景: 存储用户的信息时,如果使用 String 时,我们需要 首先将对象做一个Json序列化(将对象转为Json),然后存储到Redis的String里面.
                 但是如果我们需要改变这个对象其中的一个属性值时,我们需要先把这个对象 Json字符串读取出来进行反序列化(将Json转为对象),然后再修改属性值,
                 修改完成之后,再将用户信息序列化,然后存到Redis的String类型中. 所以我们可以使用 HashTable 直接来操作对象.

                 PS: 用HashTable储存对象时,对象必须要有ID属性.
                 */
                //Console.WriteLine("-------------------对象-----------------------");
                // 将对象写入到Redis的Hash中
                //client.StoreAsHash(new Redis_User_Model() { ID = "01", Age = "18", Name = "吴晓亨" });
                // 获取对象 参数:1.属性ID的值
                //Console.WriteLine(client.GetFromHash<Redis_User_Model>("01").Name);
                //Console.WriteLine(client.GetFromHash<Redis_User_Model>("01").Age);
                //Console.WriteLine(client.GetFromHash<Redis_User_Model>("01").ID);
                //Console.WriteLine("---------------------------------------------");

                #endregion

                #region Hash_统计Key,总数量Count,对象不算
                //Console.WriteLine(client.GetHashCount(DaKey));
                #endregion

                #region  Hash_读取总Key中的所有小Key与Value
                 读取所有Key
                //List<string> list = client.GetHashKeys(DaKey);
                //foreach (var item in list)
                //{
                //    Console.WriteLine(item);
                //}
                 读取所有Values
                //List<string> list2 = client.GetHashValues(DaKey);
                //foreach (var item in list2)
                //{
                //    Console.WriteLine(item);
                //}
                #endregion

                #region Hash_判断 DaKey 中是否存在指定的Key,返回Boolean
                Console.WriteLine(client.HashContainsEntry(DaKey, "Key1")); // True
                Console.WriteLine(client.HashContainsEntry(DaKey, "Redis_User_Model")); // False

                #endregion

                #region Hash_自增_向大Key中的指定key自增Value的值.
                Console.WriteLine(client.IncrementValueInHash(DaKey, "number", 5));
                #endregion
                #endregion

                #region Redis_List_集合操作

                #region List_三种添加方法
                // 顺序添加,如果添加对象需要序列化一下,AddItemToList与PushItemToList 意思一致都是追加.
                //Redis_User_Model xiaoLi = new Redis_User_Model() { ID = "01", Name = "李白" };
                //client.AddItemToList("List1", JsonConvert.SerializeObject(xiaoLi)); //  参数:1集合名称   2序列化后的字符串
                //Redis_User_Model daYe = new Redis_User_Model() { ID = "01", Name = "打野" };
                //client.AddItemToList("List1", JsonConvert.SerializeObject(daYe));
                //Redis_User_Model shangDan = new Redis_User_Model() { ID = "02", Name = "上单" };
                //client.PushItemToList("List1", JsonConvert.SerializeObject(shangDan)); //  参数:1集合名称   2序列化后的字符串

                // 插队,插到第一个,来添加
                //Redis_User_Model sheShou = new Redis_User_Model() { ID = "02", Name = "射手" };
                //client.PrependItemToList("List1", JsonConvert.SerializeObject(sheShou)); //  参数:1集合名称   2序列化后的字符串
                #endregion

                #region List_设置过期时间与 查看Count集合数量方法
                // 设置集合过期时间    五秒过期
                //client.ExpireEntryAt("List1", DateTime.Now.AddSeconds(5));

                // 查看集合数量   参数:集合名称
                //Console.WriteLine(client.GetListCount("List1"));
                #endregion

                #region List_批量操作
                // 批量添加
                //client.AddRangeToList("List1", new List<string>() { "01", "02", "03" });

                // 从集合的第0个开始读取2个数据      02,03
                //List<string> list1 =  client.GetRangeFromList("List1", 0, 1);
                //foreach (var item in list1)
                //{
                //    Console.WriteLine(item);
                //}
                #endregion

                #region List_栈操作,后进先出

                // 移除尾部(最后一个),并返回结果  
                //Console.WriteLine(client.RemoveEndFromList("List1"));

                // 移除头部(第一个),并返回结果
                //Console.WriteLine(client.RemoveEndFromList("List1"));

                #endregion

                #region 扩展操作
                //Redis_User_Model xiaoLi = new Redis_User_Model() { ID = "01", Name = "李白" };
                //client.AddItemToList("List1", JsonConvert.SerializeObject(xiaoLi)); 
                //Redis_User_Model daYe = new Redis_User_Model() { ID = "02", Name = "打野" };
                //client.AddItemToList("List1", JsonConvert.SerializeObject(daYe));
                //Redis_User_Model shangDan = new Redis_User_Model() { ID = "03", Name = "上单" };
                //client.PushItemToList("List1", JsonConvert.SerializeObject(shangDan));

                // 从一个List的尾部移除一个元素,然后将这个数据添加到另一个List的头部,并返回移动的值
                //Console.WriteLine(client.PopAndPushItemBetweenLists("List1","List2"));

                // 获取Key集合的过期时间
                //Console.WriteLine(client.GetTimeToLive("List1"));

                // 根据集合的下标来修改值
                //client.SetItemInList("List1", 0, "李太白");
                #endregion

                #region 删除集合
                //client.RemoveAllFromList("List1");
                #endregion
                #endregion

                #region Redis_Set自动去重集合
                /*
                 * PS : Set也是集合,只不过是自动去除重复的集合,使用场景例如:投票时,记录用户电脑的IP地址来进行判断用户是否投票,
                 * 如果使用平常的方式,我们会需要每次都判断,大大降低我们的程序性能,所以可以使用我们的去重集合.
                 */

                #region Set_添加
                // 添加两次,实际只有一个
                //client.AddItemToSet("SetList", JsonConvert.SerializeObject(new Redis_User_Model() { ID = "01", Age = "60", Name = "吴晓亨" }));
                //client.AddItemToSet("SetList", JsonConvert.SerializeObject(new Redis_User_Model() { ID = "01", Age = "60", Name = "吴晓亨" }));
                #endregion

                #region Set_批量操作
                //client.AddRangeToSet("SetLists", new List<string>() { "01", "02", "03", "01" });
                #endregion

                #region Set_获取
                //foreach (var item in client.GetAllItemsFromSet("SetLists"))
                //{
                //    Console.WriteLine(item);
                //}
                #endregion

                #region Set_删除
                // 根据 Set集合 的Value,来删除这个元素.
                //client.RemoveItemFromSet("SetLists", "01");

                // 将 SetLists 集合的 02 值移除,并将移除的值添加到 ToSetList 集合中
                //client.MoveBetweenSets("SetLists","ToSetList", "02");

                #endregion

                #region Set_交叉并补,查看两个集合里值一样的元素
                //client.AddRangeToSet("SetListA", new List<string>() { "01", "02", "03", "04", "05" });
                //client.AddRangeToSet("SetListB", new List<string>() { "08", "07", "06", "04", "05" });


                // 获取 SetListA 与 SetListB 集合的交集,就是在两个集合中都出现过的元素,并且值一样.
                //foreach (var item in client.GetIntersectFromSets("SetListA", "SetListB"))
                //{
                //    Console.WriteLine(item); // 04 05
                //}


                // 获取 SetListA 与 SetListB 集合的并集,就是这两个集合所组合的一个集合,元素不重复.
                //foreach (var item in client.GetUnionFromSets("SetListA", "SetListB"))
                //{
                //    Console.WriteLine(item); // 01 02 03 04 05 06 07 08
                //}
                #endregion

                #region Set_扩展操作

                // 统计 SetList 的数量
                //Console.WriteLine(client.GetSetCount("SetList"));

                // 模拟随机抽奖,随机获取集合里的任意元素的值
                //Console.WriteLine(client.GetRandomItemFromSet("SetLists"));

                // 可以转为集合来进行一系列操作
                //client.GetAllItemsFromSet("SetLists").ToList().FirstOrDefault(a => a == "01");

                // 随机删除集合里的元素,并返回被删除的值
                //Console.WriteLine(client.PopItemFromSet("SetLists"));
                #endregion

                #endregion

                #region Redis_ZSet有序的去重集合
                /*
                 * ZSet 自动去重,而且多了一个字段 Score 分数的字段,并且从小到大自动排序.
                 */

                #region ZSet_添加

                 当 ZSet的Score分数字段列不写时,在排序时则默认为最大 
                //client.AddItemToSortedSet("ZSetList", "01");
                //client.AddItemToSortedSet("ZSetList", "02", 10);
                //client.AddItemToSortedSet("ZSetList", "03", 90);

                //client.AddItemToSortedSet("ZSetList2", "01");
                //client.AddItemToSortedSet("ZSetList2", "02", 10);
                //client.AddItemToSortedSet("ZSetList2", "03", 90);


                #endregion

                #region ZSet_批量操作

                // 批量添加
                //client.AddRangeToSortedSet("ZSetList",new List<string>() { "11","22"},0);

                #endregion

                #region ZSet_获取数据

                //1. 获取全部操作
                 client.GetAllItemsFromSortedSet("ZSetList")  从小到大 升序  顺序查询,不返回 Score 分数列
                //foreach (var item in client.GetAllItemsFromSortedSet("ZSetList"))
                //{

                //    Console.WriteLine(item);
                //}
                 client.GetAllItemsFromSortedSet("ZSetList")  从大到小 降序   倒序查询,不返回 Score 分数列
                //foreach (var item in client.GetAllItemsFromSortedSetDesc("ZSetList"))
                //{
                //    Console.WriteLine(item);
                //}


                //2. 根据下标获取  顺序 从小到大 , 不返回 Score 分数列
                //foreach (var item in client.GetRangeFromSortedSet("ZSetList", 0, 1))
                //{
                //    Console.WriteLine(item);
                //}
                // 根据下标获取  倒叙 从大到小 , 不返回 Score 分数列
                //foreach (var item in client.GetRangeFromSortedSetDesc("ZSetList", 0, 1))
                //{
                //    Console.WriteLine(item);
                //}


                //3. 根据下标获取,顺序 从小到大 ,返回 Score 分数列
                //foreach (var item in client.GetRangeWithScoresFromSortedSet("ZSetList", 0, 1))
                //{
                //    Console.WriteLine(item.Key+"-"+item.Value);
                //}

                // 根据下标获取  倒叙 从大到小 , 返回 Score 分数列
                //foreach (var item in client.GetRangeWithScoresFromSortedSetDesc("ZSetList", 0, 1))
                //{
                //    Console.WriteLine(item.Key+ "-" + item.Value);
                //}

                #endregion

                #region ZSet_求交集_两个ZSet集合中的共同的数据,返回共有的数量,并创建新的ZSet

                // 当 ZSet的Score分数字段列不写时,在排序时则默认为最大 
                client.AddItemToSortedSet("ZSetList", "01");
                client.AddItemToSortedSet("ZSetList", "02", 10);
                client.AddItemToSortedSet("ZSetList", "03", 90);

                client.AddItemToSortedSet("ZSetList2", "01");
                client.AddItemToSortedSet("ZSetList2", "02", 10);
                client.AddItemToSortedSet("ZSetList2", "03", 90);



                Console.WriteLine(
                    //  求交集,两个集合中都有的数据,来创建第三个集合并将数据存入到新集合里,SCore列会自动将两个集合的SCore值相加.
                    //                           参数:1.新集合名称  2.被求交集的集合们的名称,是个数组
                    client.StoreIntersectFromSortedSets("ZSetList3", "ZSetList", "ZSetList2")
                    );
                #endregion
                #endregion


            }
            // 等待十六秒
            //Task.Delay(16000).Wait();
            Console.WriteLine("OK");
            Console.ReadLine();
        }
    }
}

4. 你应该知道的Redis底层数据结构存储方式.

Redis_String在存储数据时的操作概念:
在存储数据时的keyValue如果不超过41字节,则使用RAW编码,超过则使用Embstr编码.
RAW编码:会开辟两次空间,性能较差,使用场景 存储值的时候,值不超过41字节,Redis会默认使用RAW编码
Embstr编码:开辟一次空间,性能较好,使用场景 存储值的时候,值超过41字节,Redis会默认使用Embstr编码,
Embstr编码在开辟空间时,会默认预留一些空间,浪费我们的数据空间与内存,所以比较推荐Hash.

Redis_Hash在存储数据时的操作概念:
当大Key(对象)中的小Key(属性)与Value(值)的长度大于64个字节时 或 大Key(对象)下的小Key(属性)的数量超过512个时会使用 HashTable来存储.
HashTable通过Hash算法来计算出下标,查找速度比数组方式快多了.

当大Key(对象)中的小Key(属性)与Value(值)的长度小于64个字节时 或 大Key(对象)下的小Key(属性)的数量未超过512个时会使用 ZipList来存储.
这个限制,我们可以在 Redis.conf 文件中进行修改,如下两列:
hash-max-zipmap-entries 512  hash-max-zipmap-value 64
但不建议更改,因为默认已经一个性能的瓶颈了.

 

PS:后续持续更新,Redis差的还多呢,这只是基本语法,后续会持续更新,一起加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值