reids介绍和多路复用原理
redis 有windows 版本 和linux 版本
基础可以参考:https://www.cnblogs.com/ysocean/p/9074353.html
Redis 由四个可执行文件:redis-benchmark、redis-cli、redis-server、redis-stat 这四个文件,加上一个redis.conf就构成了整个redis的最终可用包。它们的作用如下:
- redis-server:Redis服务器的daemon启动程序
- redis-cli:Redis命令行操作工具。当然,你也可以用telnet根据其纯文本协议来操作
- redis-benchmark:Redis性能测试工具,测试Redis在你的系统及你的配置下的读写性能
- redis-stat:Redis状态检测工具,可以检测Redis当前状态参数及延迟状况
如何在linux 环境用docker安装redis 前提是已经安装好docker
直接运行命令 docker run -p 6379:6379 -d redis 可以默认安装最新版本
docker ps -a 可以查看当前容器已经有redis
进入redis 容器 docker exec -it xxx(容器Id) /bin/bash
如何命令 redis-cli 就可以通过命令操作redis了
例如 redis-cli --raw flushall 清楚redis 目前的缓存数据
如何设置redis 的登录密码 :
windows下的 找到redis 安装目录下的配置危机 redis.conf 或者redis.windows.conf 找到 requirepass 添加密码 eg: requirepass admin123
然后重启redis ,用cmd命令 redis-server.exe redis.windows.conf 重启后就要使用密码登录了
登录命令 redis-cli.exe -a admin1234
linux 下设置密码:
第一种:永久方式
redis设置密码访问
你的redis在真是环境中不可以谁想访问就可以访问,所以必须要设置密码
设置密码的流程如下:
vim /etc/redis.conf
找到 #requirepass foobared去掉注释,foobared改为自己的密码,我在这里改为
requirepass 123456
然后保存,重启服务
cd /usr/local/bin
./redis-server /etc/redis.conf
测试连接:./redis-cli
输入命令config get requirepass 会提示(error) NOAUTH Authentication required. 这是属于正常现象。
我们输入 auth 123456#你刚才设置的密码
第二种:临时方式
1.开启服务端
2.链接客户端,使用config get requirepass查看当前redis有没有设置密码
3.上图表示没有设置密码,那么现在来设置密码:
命令:config set requirepass asdfgh
4.再次查看redis密码,则表示密码已存在
redis 其实也是一种数据库,它是内存数据库,然后提供了好多种数据类型,来解决我们不同业务的问题,nosql数据库的一种数据库,如果做缓存,优先选择redis;
1.为什么在大数据高并发业务中,会要有redis?
如果是在高并发的情况下 普通的关系型数据库是由IO阻塞的问题的;
BIO和NIO?===》多路复用:也就是说当多个线程过来创建多个异步线程出处理! 正式环境redis最好用linux系统下的;其实多路复用,就是把监听和阻塞
Redis 九大数据结构:
using (RedisClient client = new RedisClient("127.0.0.1", 6379)) { //删除当前数据库中的所有Key 默认删除的是select 0 client.FlushDb(); //删除所有数据库中的key client.FlushAll(); //统计网站访问数量、当前在线人数、微博数、粉丝数等,全局递增ID等 // 如果你要学号redis,第一步要灵活使用,要非常非常了解各种api // office ,各种数据结构就是代表你是操作execl的还是word,还是ppt .. #region 设置key的value client.Set<string>("name", "拉拉"); Console.WriteLine("错误输出"); Console.WriteLine(client.GetValue("name")); Console.WriteLine(JsonConvert.DeserializeObject<string>(client.GetValue("name"))); Console.WriteLine("正确输出"); // 代码的底层,也是做了反序列化,只是我们看不到 Console.WriteLine(client.Get<string>("name")); //Console.WriteLine(JsonConvert.DeserializeObject<string>(client.GetValue("name"))); #endregion }
using (RedisClient client = new RedisClient("127.0.0.1", 6379)) { //删除当前数据库中的所有Key 默认删除的是select 0 client.FlushDb(); //删除所有数据库中的key client.FlushAll(); #region 设置key的value并设置过期时间 client.Set<string>("name", "拉拉", TimeSpan.FromSeconds(1)); Task.Delay(1 * 1000).Wait(); //等一秒后就没有数据了 Console.WriteLine(client.Get<string>("name")); #endregion }
using (RedisClient client = new RedisClient("127.0.0.1", 6379)) { //删除当前数据库中的所有Key 默认删除的是select 0 client.FlushDb(); //删除所有数据库中的key client.FlushAll(); #region 设置多个key的value // 批量的写入redis key client.SetAll(new Dictionary<string, string> { { "id", "001" }, { "name", "clay" } }); //批量读取内存中多个key的结果 如果我们获取的key不存在,程序会返回一个空的字符串 // 来判断当前用户是否是老用户 老师建议你们如果经济允许搞一个vpn var getall = client.GetAll<string>(new string[] { "id", "name", "number" }); foreach (var item in getall) { Console.WriteLine(item); } #endregion }
using (RedisClient client = new RedisClient("127.0.0.1", 6379)) { //删除当前数据库中的所有Key 默认删除的是select 0 client.FlushDb(); //删除所有数据库中的key client.FlushAll(); #region 设置key的value并设置过期时间 client.Set<string>("name", "朝夕教育", DateTime.Now.AddSeconds(1)); //client.Set<string>("name", "朝夕教育", DateTime.Now.AddMonths(15)); Console.WriteLine("刚写进去的结果"); Console.WriteLine(client.Get<string>("name")); Task.Delay(1 * 1000).Wait(); Console.WriteLine("1秒钟之后的结果"); Console.WriteLine(client.Get<string>("name")); client.Set<string>("class", "优秀班级", TimeSpan.FromSeconds(10)); Task.Delay(1 * 1000).Wait(); Console.WriteLine(client.Get<string>("class")); #endregion #region 在原有key的value值之后追加value client.AppendToValue("name", "I"); client.AppendToValue("name", " "); client.AppendToValue("name", "LOVE YOU"); Console.WriteLine(client.Get<string>("name")); #endregion #region 获取旧值赋上新值 client.Set("name", "朝夕教育"); //获取当前key的之前的值,然后把新的结果替换进入 var value = client.GetAndSetValue("name", "clay"); Console.WriteLine("原先的值" + value); Console.WriteLine("新值" + client.GetValue("name")); #endregion #region 自增1,返回自增后的值 //给key为sid的键自增1 ,返回了自增之后的结果 Console.WriteLine(client.Incr("sid")); //Console.WriteLine(client.Incr("sid")); //Console.WriteLine(client.Incr("sid")); //Console.WriteLine("华丽丽的结束"); //Console.WriteLine(client.GetValue("sid")); //每次通过传递的count累计,count就是累加的值 //client.IncrBy("sid", 2); //Console.WriteLine(client.Get<string>("sid")); //client.IncrBy("sid", 100); //Console.WriteLine("最后的结果***" + client.GetValue("sid")); #endregion #region 自减1,返回自减后的值 //Console.WriteLine(client.Decr("sid")); //Console.WriteLine(client.Decr("sid")); //Console.WriteLine(client.Decr("sid")); //Console.WriteLine("最后的结果"+client.GetValue("sid")); ////通过传入的count去做减肥 之前的结果-count //client.DecrBy("sid", 2); //Console.WriteLine("最终的结果"+client.GetValue("sid")); #endregion }
#region add 和set 的区别? //add 只能做新增,如果已经有了key则返回失败 // set 如果有key就替换,如果没有就写入 //当使用add 方法去操作redis的时候,如果key存在的话,则不会再次进行操作 返回false 如果操作成功返回true Console.WriteLine(client.Add("name", "clay")); //用add的时候帮你去判断如果有则不进行操作,如果没有则写,它只能写新值,不能修改 Console.WriteLine(client.Add("name", "你很好clay")); Console.WriteLine(client.Get<string>("name")); //使用set去操作 redis的时候,如果key不存在则写入当前值,并且返回true,通过存在,则对之前的值进行了一个替换 返回操作的结果 Console.WriteLine(client.Set("name", "clay")); Console.WriteLine(client.Set("name", "你很好clay")); Console.WriteLine(client.Get<string>("name")); #endregion
public static void Show() { using (RedisClient client = new RedisClient("127.0.0.1", 6379)) { //删除当前数据库中的所有Key 默认删除的是db0 client.FlushDb(); //删除所有数据库中的key client.FlushAll(); ///大key string hashid = "mykey"; #region 向hashid集合中添加key/value client.SetEntryInHash(hashid, "id", "001"); Console.WriteLine(client.GetValuesFromHash(hashid, "id").FirstOrDefault()); client.SetEntryInHash(hashid, "name", "clay"); Console.WriteLine(client.GetValuesFromHash(hashid, "name").FirstOrDefault()); client.SetEntryInHash(hashid, "socre", "100"); Console.WriteLine(client.GetValuesFromHash(hashid, "socre").FirstOrDefault()); #endregion #region 批量新增key的值 Dictionary<string, string> pairs = new Dictionary<string, string>(); pairs.Add("id", "001"); pairs.Add("name", "clay"); client.SetRangeInHash(hashid, pairs); //获取当前key的值 Console.WriteLine(client.GetValueFromHash(hashid, "id")); Console.WriteLine(client.GetValueFromHash(hashid, "name")); //一次性的获取所有想要获取的小key(属性的)值 如果key不存在,则返回空,不抛出异常 var list = client.GetValuesFromHash(hashid, "id", "name", "abc"); Console.WriteLine("*********"); foreach (var item in list) { Console.WriteLine(item); } #endregion #region 如果hashid集合中存在key/value则不添加返回false,如果不存在在添加key/value,返回true Console.WriteLine(client.SetEntryInHashIfNotExists(hashid, "name", "你好美")); Console.WriteLine(client.SetEntryInHashIfNotExists(hashid, "name", "你好美 哈哈哈")); Console.WriteLine(client.GetValuesFromHash(hashid, "name").FirstOrDefault()); #endregion #region 存储对象T t到hash集合中 //urn: 类名: id的值 、、如果使用对象操作,一定要有id client.StoreAsHash<UserInfo>(new UserInfo() { Id = 1, Name = "clay", number = 0 }); var olduserinfo = client.GetFromHash<UserInfo>(1); ////如果id存在的话,则覆盖之前相同的id 他帮助我们序列化或者反射了一些事儿 //client.StoreAsHash<UserInfo>(new UserInfo() { Id = 2, Name = "clay2" }); //获取对象T中ID为id的数据。 必须要有属性id,不区分大小写 //Console.WriteLine(client.GetFromHash<UserInfo>(1).Name); //var olduserinfo = client.GetFromHash<UserInfo>(1); //olduserinfo.number = 4; //client.StoreAsHash<UserInfo>(olduserinfo); //Console.WriteLine("最后的结果"+client.GetFromHash<UserInfo>(1).number); //client.StoreAsHash<UserInfoTwo>(new UserInfoTwo() { Id = "001", Name = "clay2" }); //Console.WriteLine(client.GetFromHash<UserInfoTwo>("001").Name); //client.StoreAsHash<UserInfoTwo>(new UserInfoTwo() { Id = "002", Name = "clay" }); //Console.WriteLine(client.GetFromHash<UserInfoTwo>("002").Name); //UserInfo lisi = new UserInfo() { Id = 1, Name = "李四", number = 0 }; //client.StoreAsHash<UserInfo>(lisi); //Console.WriteLine(client.GetFromHash<UserInfo>(1).number); ////做个自增 //var oldzhang = client.GetFromHash<UserInfo>(1); //oldzhang.number++; //client.StoreAsHash<UserInfo>(oldzhang); #endregion #region 获取所有hashid数据集的key/value数据集合 //Dictionary<string, string> pairs = new Dictionary<string, string>(); //pairs.Add("id", "001"); //pairs.Add("name", "clay"); //client.SetRangeInHash(hashid, pairs); //var dics = client.GetAllEntriesFromHash(hashid); //foreach (var item in dics) //{ // Console.WriteLine(item.Key + ":" + item.Value); //} #endregion #region 获取hashid数据集中的数据总数 //Dictionary<string, string> pairs = new Dictionary<string, string>(); //pairs.Add("id", "001"); //pairs.Add("name", "clay"); //client.SetRangeInHash(hashid, pairs); //你们自己做到心中有数 //Console.WriteLine(client.GetHashCount(hashid)); #endregion #region 获取hashid数据集中所有key的集合 //Dictionary<string, string> pairs = new Dictionary<string, string>(); //pairs.Add("id", "001"); //pairs.Add("name", "clay"); //client.SetRangeInHash(hashid, pairs); //var keys = client.GetHashKeys(hashid); //foreach (var item in keys) //{ // Console.WriteLine(item); //} #endregion #region 获取hashid数据集中的所有value集合 //Dictionary<string, string> pairs = new Dictionary<string, string>(); //pairs.Add("id", "001"); //pairs.Add("name", "clay"); //client.SetRangeInHash(hashid, pairs); //var values = client.GetHashValues(hashid); //foreach (var item in values) //{ // Console.WriteLine(item); //} #endregion #region 删除hashid数据集中的key数据 //Dictionary<string, string> pairs = new Dictionary<string, string>(); //pairs.Add("id", "001"); //pairs.Add("name", "clay"); //client.SetRangeInHash(hashid, pairs); //client.RemoveEntryFromHash(hashid, "id"); //var values = client.GetHashValues(hashid); //foreach (var item in values) //{ // Console.WriteLine(item); //} #endregion #region 判断hashid数据集中是否存在key的数据 //Dictionary<string, string> pairs = new Dictionary<string, string>(); //pairs.Add("id", "001"); //pairs.Add("name", "clay"); //client.SetRangeInHash(hashid, pairs); //Console.WriteLine(client.HashContainsEntry(hashid, "id")); //T F //Console.WriteLine(client.HashContainsEntry(hashid, "number"));// T F #endregion #region 给hashid数据集key的value加countby,返回相加后的数据 //Dictionary<string, string> pairs = new Dictionary<string, string>(); //pairs.Add("id", "001"); //pairs.Add("name", "clay"); //pairs.Add("number", "2"); //client.SetRangeInHash(hashid, pairs); //Console.WriteLine(client.IncrementValueInHash(hashid, "number", 2)); //注意,存的值必须是数字类型,否则抛出异常 #endregion } }
自定义方式:
public class UserInfo { public int Id { get; set; } public string Name { get; set; } public int number { get; set; } } public class UserInfoTwo { public string Id { get; set; } public string Name { get; set; } }
public static class HashTool { public static void StoreAsHash<T>(T model) where T : class, new() { //获取当前类型的所有字段 Type type = model.GetType(); var fields = type.GetProperties(); // urn: 类名: id的值 var hashid = type.FullName; Dictionary<string, string> pairs = new Dictionary<string, string>(); var IdValue = string.Empty; for (int i = 0; i < fields.Length; i++) { if (fields[i].Name.ToLower() == "id") { //如果你真的把两个相同的id的对象存进去,我可能只改其中一个 //不可能,如果有两个相同的id的对象存进去,则后面的会把前面的替换掉 IdValue = fields[i].GetValue(model).ToString(); } else { // 获取字段的值 pairs.Add(fields[i].Name, fields[i].GetValue(model).ToString()); } } if (IdValue == string.Empty) { IdValue = DateTime.Now.ToString("yyyyMMdd"); } RedisClient client = new RedisClient("127.0.0.1"); client.SetRangeInHash(hashid + IdValue, pairs); } public static T GetFromHash<T>(object id) where T : class, new() { //获取当前类型的所有字段 Type type = typeof(T); // urn: 类名: id的值 var hashid = type.FullName; RedisClient client = new RedisClient("127.0.0.1"); var dics = client.GetAllEntriesFromHash(hashid + id.ToString()); if (dics.Count == 0) { return new T(); } else { var model = Activator.CreateInstance(type); var fields = type.GetProperties(); foreach (var item in fields) { if (item.Name.ToLower() == "id") { item.SetValue(model, id); } if (dics.ContainsKey(item.Name)) { item.SetValue(model, dics[item.Name]); } } return (T)model; } } }
using (RedisClient client = new RedisClient("127.0.0.1", 6379)) { //删除当前数据库中的所有Key 默认删除的是db0 client.FlushDb(); //删除所有数据库中的key client.FlushAll(); #region 自定义 HashTool.StoreAsHash<UserInfoTwo>(new UserInfoTwo() { Id = "10001", Name = "clay" }); var user = HashTool.GetFromHash<UserInfoTwo>("10001"); Console.WriteLine("结束"); #endregion }
hash 底层它的数据结构式ziplist? ziplist:压缩版的list ..(动态的数组,数组的每一个元素的空间是一样的)
如果Filed的个数超过512或者Filed中的任意一个键或者值得长度大于64个字节的时候 使用得是HashTable,其他情况默认ZipList
第一问题:每次插入都有开辟空间,连续的
第二问题:你要查询的时候,你要从头来计算,--查询的速度变慢。。。
hash的数据结果,它的时间复杂度是O(1);
hash快速的查询结果,而且节省空间,一上来就是一个小量的hash。。
问题:如果hash后面链表越来越长的时候,时间复杂度是不是又变高。。。
解决了这个问题?? 扩容:是一开始的时候,redis有两个hash结构在存储数据,第一次只有一个是有长度,一个是没有长度。。
数据迁移问题来了,因为如果不小心操作的时候,刚好触发了瓶颈,要扩容,
解决迁移问题: 第一个:不是一次性迁移完成,是每一次操作只会迁移一部分。 第二个:是一个后台任务,后台任务给你偷偷摸摸的迁移数据: 非常重要:数据一致的问题,自己有机会了解一下
using (RedisClient client = new RedisClient("127.0.0.1", 6379)) { //删除当前数据库中的所有Key 默认删除的是db0 client.FlushDb(); //删除所有数据库中的key client.FlushAll(); string listid = "clay_list"; #region 顺序添加 var caocao = new UserInfo() { Id = 1, Name = "李太白" }; client.AddItemToList(listid, JsonConvert.SerializeObject(caocao)); var jiaxu = new UserInfo() { Id = 2, Name = "贾诩" }; client.AddItemToList(listid, JsonConvert.SerializeObject(jiaxu)); #endregion #region 从左侧向list中添加值 追加 var liubei = new UserInfo() { Id = 1, Name = "刘备" }; client.PushItemToList(listid, JsonConvert.SerializeObject(liubei)); #endregion #region 从左侧向list中添加值,并设置过期时间 var caocao = new UserInfo() { Id = 1, Name = "李太白" }; client.AddItemToList(listid, JsonConvert.SerializeObject(caocao)); var liubei = new UserInfo() { Id = 2, Name = "刘备" }; client.PushItemToList(listid, JsonConvert.SerializeObject(liubei)); //只在内存中存储一秒 client.ExpireEntryAt(listid, DateTime.Now.AddSeconds(1)); Console.WriteLine(client.GetListCount(listid)); Task.Delay(1 * 1000).Wait(); Console.WriteLine("1秒之后"); Console.WriteLine(client.GetListCount(listid)); //雪崩 问题:瞬间大量的数据消失-》大量的数据不要一下的全部消失 #endregion #region 从右侧向list中添加值,并设置过期时间 插队 var caocao = new UserInfo() { Id = 1, Name = "李太白" }; client.AddItemToList(listid, JsonConvert.SerializeObject(caocao)); var jiaxu = new UserInfo() { Id = 2, Name = "贾诩" }; client.AddItemToList(listid, JsonConvert.SerializeObject(jiaxu)); var gaunyu = new UserInfo() { Id = 3, Name = "关羽" }; //向右追加就是插队 client.PrependItemToList(listid, JsonConvert.SerializeObject(gaunyu)); Console.WriteLine("ok"); var caomegndeng = new UserInfo() { Id = 3, Name = "曹孟德" }; client.PrependItemToList(listid, JsonConvert.SerializeObject(caomegndeng)); client.ExpireEntryAt(listid, DateTime.Now.AddSeconds(1)); Console.WriteLine(client.GetListCount(listid)); Task.Delay(1 * 1000).Wait(); Console.WriteLine("1秒之后"); Console.WriteLine(client.GetListCount(listid)); #endregion #region 为key添加多个值 client.AddRangeToList(listid, new List<string>() { "001", "002", "003", "004" }); //批量去读取list中的元素 var lists = client.GetAllItemsFromList(listid); foreach (var item in lists) { Console.WriteLine(item); } #endregion #region 获取key中下标为star到end的值集合 client.AddRangeToList(listid, new List<string>() { "001", "002", "003", "004" }); var lists = client.GetRangeFromList(listid, 0, 1);//从下标0到1的值 foreach (var item in lists) { Console.WriteLine(item); } #endregion #region list 队列和集合操作 mq var caocao = new UserInfo() { Id = 1, Name = "李太白" }; client.AddItemToList(listid, JsonConvert.SerializeObject(caocao)); var jiaxu = new UserInfo() { Id = 2, Name = "贾诩" }; client.AddItemToList(listid, JsonConvert.SerializeObject(jiaxu)); var gaunyu = new UserInfo() { Id = 3, Name = "关羽" }; client.AddItemToList(listid, JsonConvert.SerializeObject(gaunyu)); //移除尾部 并返回移除的数据 先删再给数据 Console.WriteLine(client.RemoveEndFromList(listid)); foreach (var item in client.GetAllItemsFromList(listid)) { Console.WriteLine(JsonConvert.DeserializeObject<UserInfo>(item).Name); } // 移除头部并返回移除的数据 Console.WriteLine(client.RemoveStartFromList(listid)); foreach (var item in client.GetAllItemsFromList(listid)) { Console.WriteLine(JsonConvert.DeserializeObject<UserInfo>(item).Name); } // 从一个list的尾部移除一个数据,添加到另外一个list的头部,并返回移动的值 Console.WriteLine(client.PopAndPushItemBetweenLists(listid, "newlist")); Console.WriteLine("移动之后新队列的元素结果"); Console.WriteLine(client.GetItemFromList("newlist", 0)); //根据下标获取想要的集合元素,不做移除操作 var userstr = client.GetItemFromList(listid, 0); Console.WriteLine(JsonConvert.DeserializeObject<UserInfo>(userstr).Name); //修改当前下标的结果 client.SetItemInList(listid, 0, "new value"); #endregion }
public static void Show() { using (RedisClient client = new RedisClient("127.0.0.1", 6379)) { //删除当前数据库中的所有Key 默认删除的是db0 client.FlushDb(); //删除所有数据库中的key client.FlushAll(); #region Set 不重复集合 string key = "clay_set"; //投票 #region 添加键值 //就是自动去重,再带去重的功能 var litaibai = new UserInfo() { Id = 1, Name = "李太白" }; //client.AddItemToList(key, JsonConvert.SerializeObject(litaibai)); //client.AddItemToList(key, JsonConvert.SerializeObject(litaibai)); //client.AddItemToSet(key, JsonConvert.SerializeObject(litaibai)); //client.AddItemToSet(key, JsonConvert.SerializeObject(litaibai)); //client.AddItemToSet(key, JsonConvert.SerializeObject(litaibai)); //client.AddItemToSet(key, JsonConvert.SerializeObject(litaibai)); //Console.WriteLine("***完成了"); #endregion #region 随机获取key集合中的一个值,获取当前setid中的所有值 //批量的去操作set 集合 //Console.WriteLine("set 开始了"); //client.AddRangeToSet(key, new List<string>() { "001", "001", "002", "003", "003", "004" }); //////当前setid中的值数量 //Console.WriteLine(client.GetSetCount(key)); ////随机获取key集合中的一个值 如果有需要取随机数也可以用 //Console.WriteLine(client.GetRandomItemFromSet(key)); ////获取当前setid中的所有值 //var lists = client.GetAllItemsFromSet(key); //Console.WriteLine("展示所有的值"); //foreach (var item in lists) //{ // Console.WriteLine(item); //} #endregion #region 随机删除key集合中的一个值 //client.AddRangeToSet(key, new List<string>() { "001", "001", "002" }); //////随机删除key集合中的一个值 返回当前删掉的这个值 //Console.WriteLine("随机删除的值" + client.PopItemFromSet(key)); //var lists = client.GetAllItemsFromSet(key); //Console.WriteLine("展示删除之后所有的值"); //foreach (var item in lists) //{ // Console.WriteLine(item); //} #endregion #region 根据小key 删除 一个key 对象多个value //client.AddRangeToSet(key, new List<string>() { "001", "001", "002" }); //client.RemoveItemFromSet(key, "001"); //var lists = client.GetAllItemsFromSet(key); //Console.WriteLine("展示删除之后所有的值"); //foreach (var item in lists) //{ // Console.WriteLine(item); //} #endregion #region 从fromkey集合中移除值为value的值,并把value添加到tokey集合中 //client.AddRangeToSet("fromkey", new List<string>() { "003", "001", "002", "004" }); //client.AddRangeToSet("tokey", new List<string>() { "001", "002" }); ////从fromkey 中把元素004 剪切到tokey 集合中去 //client.MoveBetweenSets("fromkey", "tokey", "004"); //Console.WriteLine("fromkey data ~~~~~~"); //foreach (var item in client.GetAllItemsFromSet("tokey")) //{ // Console.WriteLine(item); //} //Console.WriteLine("tokey data ~~~~~~"); //foreach (var item in client.GetAllItemsFromSet("tokey")) //{ // Console.WriteLine(item); //} #endregion #region 并集 把两个集合合并起来,然后去重 //client.AddRangeToSet("keyone", new List<string>() { "001", "002", "003", "004" }); //client.AddRangeToSet("keytwo", new List<string>() { "001", "002", "005" }); //var unionlist = client.GetUnionFromSets("keyone", "keytwo"); //Console.WriteLine("返回并集结果"); //foreach (var item in unionlist) //{ // Console.WriteLine(item); //} ////把 keyone 和keytwo 并集结果存放到newkey 集合中 //client.StoreUnionFromSets("newkey", "keyone", "keytwo"); //Console.WriteLine("返回并集结果的新集合数据"); //foreach (var item in client.GetAllItemsFromSet("newkey")) //{ // Console.WriteLine(item); //} #endregion #region 交集 获取两个集合中共同存在的元素 //client.AddRangeToSet("keyone", new List<string>() { "001", "002", "003", "004" }); //client.AddRangeToSet("keytwo", new List<string>() { "001", "002", "005" }); //var Intersectlist = client.GetIntersectFromSets("keyone", "keytwo"); //Console.WriteLine("交集的结果"); //foreach (var item in Intersectlist) //{ // Console.WriteLine(item); //} ////把 keyone 和keytwo 交集结果存放到newkey 集合中 //client.StoreIntersectFromSets("newkey", "keyone", "keytwo"); //Console.WriteLine("返回交集结果的新集合数据"); //foreach (var item in client.GetAllItemsFromSet("newkey")) //{ // Console.WriteLine(item); //} #endregion #endregion } }
public static void Show() { using (RedisClient client = new RedisClient("127.0.0.1", 6379)) { //删除当前数据库中的所有Key 默认删除的是db0 client.FlushDb(); //删除所有数据库中的key client.FlushAll(); #region Set 不重复集合 string key = "clay_set"; #region sorted set //string zsett_key = "clay_zset"; ////添加一个kye 如果有相同的值得花,则会替换(覆盖)进去,不会因为分数保留 //client.AddItemToSortedSet(zsett_key, "cc", 33); //client.AddItemToSortedSet(zsett_key, "cc", 44); //client.AddItemToSortedSet(zsett_key, "cc", 22); //Console.WriteLine("ok"); ////获取当前value的结果 //Console.WriteLine(client.GetItemIndexInSortedSet(zsett_key, "cc")); ////批量操作多个key ,给多个key 赋值1 //client.AddRangeToSortedSet(zsett_key, new List<string>() { "a", "b" }, 1); //foreach (var item in client.GetAllItemsFromSortedSet(zsett_key)) //{ // Console.WriteLine(item); //} client.AddItemToSortedSet("蜀国", "刘备", 5); client.AddItemToSortedSet("蜀国", "关羽", 2); client.AddItemToSortedSet("蜀国", "张飞", 3); client.AddItemToSortedSet("魏国", "刘备", 5); client.AddItemToSortedSet("魏国", "关羽", 2); client.AddItemToSortedSet("蜀国", "张飞", 3); ////获取 key为蜀国的下标0,到2 IDictionary<String, double> Dic = client.GetRangeWithScoresFromSortedSet("蜀国", 0, 2); foreach (var r in Dic) { Console.WriteLine(r.Key + ":" + r.Value); } //var DicString = client.StoreIntersectFromSortedSets("2", "蜀国", "魏国"); //var ss = client.GetAllItemsFromSortedSet("2"); //foreach (var r in DicString) //{ // Console.WriteLine(r.Key + ":" + r.Value); //} //int int32 #endregion } }
redis 解决了两个问题:1.直接操作硬盘的问题
2.连接阻塞的问题,之前是io阻塞,系统在等待请求的时候,不能干其他的事情,而且每次只能阻塞等待请求,redis通过多路复用,由系统帮你监听多个连接,只要有事情要处理 ,系统会调用你的回调函数,把监听的事情交给了系统,释放了我们自己的代码-- 开启的是高速通道,之前一次只能处理一个请求,现在可以处理多个请求。。。 (不管是单线程的redis还是多线程的redis,最后执行那个指令的线程有且只要一个,)
namespace RedisPublish { class Program { static void Main(string[] args) { try { //创建一个公众号--创建一个主题 Console.WriteLine("发布服务"); IRedisClientsManager redisClientManager = new PooledRedisClientManager("127.0.0.1:6379"); string topicname = "Send_Log"; RedisPubSubServer pubSubServer = new RedisPubSubServer(redisClientManager, topicname) { OnMessage = (channel, msg) => { Console.WriteLine($"从频道:{channel}上接受到消息:{msg},时间:{DateTime.Now.ToString("yyyyMMdd HH:mm:ss")}"); Console.WriteLine("___________________________________________________________________"); }, OnStart = () => { Console.WriteLine("发布服务已启动"); Console.WriteLine("___________________________________________________________________"); }, OnStop = () => { Console.WriteLine("发布服务停止"); }, OnUnSubscribe = channel => { Console.WriteLine(channel); }, OnError = e => { Console.WriteLine(e.Message); }, OnFailover = s => { Console.WriteLine(s); }, }; //接收消息 pubSubServer.Start(); while (1==1) { Console.WriteLine("请输入记录的日志"); string message = Console.ReadLine(); redisClientManager.GetClient().PublishMessage(topicname, message); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } } }
订阅
namespace RedisPublish { class Program { static void Main(string[] args) { try { //创建一个公众号--创建一个主题 Console.WriteLine("发布服务"); IRedisClientsManager redisClientManager = new PooledRedisClientManager("127.0.0.1:6379"); string topicname = "Send_Log"; RedisPubSubServer pubSubServer = new RedisPubSubServer(redisClientManager, topicname) { OnMessage = (channel, msg) => { Console.WriteLine($"从频道:{channel}上接受到消息:{msg},时间:{DateTime.Now.ToString("yyyyMMdd HH:mm:ss")}"); Console.WriteLine("___________________________________________________________________"); }, OnStart = () => { Console.WriteLine("发布服务已启动"); Console.WriteLine("___________________________________________________________________"); }, OnStop = () => { Console.WriteLine("发布服务停止"); }, OnUnSubscribe = channel => { Console.WriteLine(channel); }, OnError = e => { Console.WriteLine(e.Message); }, OnFailover = s => { Console.WriteLine(s); }, }; //接收消息 pubSubServer.Start(); while (1==1) { Console.WriteLine("请输入记录的日志"); string message = Console.ReadLine(); redisClientManager.GetClient().PublishMessage(topicname, message); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } } }
public class Logger { /// <summary> /// 写入文本日志 /// </summary> /// <param name="fileName"></param> /// <param name="type"></param> /// <param name="content"></param> public static void WriteTxtLogs(string fileName, string type, string content) { string path = AppDomain.CurrentDomain.BaseDirectory; if (!string.IsNullOrEmpty(path)) { path = AppDomain.CurrentDomain.BaseDirectory + fileName; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } path = path + "\\" + DateTime.Now.ToString("yyyyMMdd"); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } path = path + "\\" + DateTime.Now.ToString("yyyyMMdd") + ".txt"; if (!File.Exists(path)) { FileStream fs = File.Create(path); fs.Close(); } if (File.Exists(path)) { StreamWriter sw = new StreamWriter(path, true, System.Text.Encoding.Default); sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + type + "-->" + content); // sw.WriteLine("----------------------------------------"); sw.Close(); } } } }

布隆过滤器可以判断某个数据一定不存在,但是无法判断一定存在。
布隆过滤器优缺点
优点:优点很明显,二进制组成的数组,占用内存极少,并且插入和查询速度都足够快。
缺点:随着数据的增加,误判率会增加;还有无法判断数据一定存在;另外还有一个重要缺点,无法删除数据。
实操redis如何安装布隆过滤器
在docker中使用命令 docker run -p 6379:6379 --name redis--redisbloom redislabs/rebloom:latest 这个是把redis和过滤期集成在一起的了
使用它的客户端:docker exec -it redis -redisbloom bash
# redis-cli
代码:
//using (RedisClient client = new RedisClient("192.168.1.211", 6379)) //{ // client.Custom("bf.add", "myfilter", "dddd"); // Console.WriteLine(client.Custom("bf.exists", "myfilter", "dddd4444").Text); //}
其他:
1.内存满了,会触发数据淘汰策略,释放资源 2.限流--讲lua,扩展,看一下实现代码 ### 限流lua代码如下 local times = redis.call('incr',KEYS[1]) if times == 1 then redis.call('expire',KEYS[1], ARGV[1]) end if times > tonumber(ARGV[2]) then return 0 end return 1
Docker 中如何设置redis密码
挂载的时候,把配置文件改一下,挂载进去就行了。或者直接进容器改配置文件---
等下,把docker挂载启动redis配置和脚本放在下面 :
docker run -d -p 6379:6379 -v /myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf --name redis01 redis:6.0 redis-server /usr/local/etc/redis/redis.conf
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现