引入一个大家都用的到的需求来说吧。

需求:要在三主三从的redis集群,存入数据,会对数据进行批量删除操作,数据要求要在redis集群负载均衡。

思路:

1.存入数据好办

1 var connect = ConnectionMultiplexer.Connect(redisConn);
2 var redisDb = connect.GetDatabase();
3 var res1 = redisDb.StringSet("1", DateTime.Now.ToString(), TimeSpan.FromSeconds(600));
4 var res2 = redisDb.StringSet("1111", DateTime.Now.ToString(), TimeSpan.FromSeconds(600));

2.批量删除直接异常

1 redisDb.KeyDelete(new RedisKey[] { "1", "1111" });

Ex:"Multi-key operations must involve a single slot; keys can use 'hash tags' to help this, i.e. '{/users/12345}/account' and '{/users/12345}/contacts' will always be in the same slot"

3.查到异常是因为redis hash slot 机制导致的,什么是 hash slot?
hash slot 介绍:https://redis.io/topics/cluster-tutorial

4.加上hash slot 字符串,让key进入同一个slot
var res1 = redisDb.StringSet("{myslot}key1", DateTime.Now.ToString(), TimeSpan.FromSeconds(600));
var res2 = redisDb.StringSet("{myslot}key2", DateTime.Now.ToString(), TimeSpan.FromSeconds(600));
redisDb.KeyDelete(new RedisKey[] { "{myslot}key1", "{myslot}key2" });
能进行批量操作,但是都被分配到了同一台服务器上的同一个槽点,不负载均衡。

5.如何负载均衡, 让Key分布到各个服务器,并且可以批量操作?
如果知道每个槽点对应的字符串,key可以按照算法计算出自己对应的字符串,加上后,就可以进行分组批量增删改操作。

6.hash slot 计算方法
HASH_SLOT = CRC16(key) mod 16384 (crc16-XMODEM)
介绍 :https://redis.io/topics/cluster-spec

7.net core 计算出16384个slot 字符串 算法例子和 结果模板

 1         static void Main(string[] args)
2 {
3 var data = new Dictionary<int, string>();
4 var i = 0;
5 while (data.Keys.Count < 16384)
6 {
7 var temp = i.ToString("X");
8 var value = Crc16(Encoding.UTF8.GetBytes(temp)) % 16384;
9 data[int.Parse(value.ToString())] = temp;
10 i++;
11
12 }
13 var sb = new StringBuilder();
14 foreach (var item in data.OrderBy(s => s.Key))
15 {
16 var temp = $"slot num:{item.Key} str:{item.Value} \r\n";
17 Console.WriteLine(temp);
18 sb.Append(temp);
19 }
20 File.WriteAllText("data.txt", sb.ToString());
21 Console.ReadLine();
22 }
23 private static ushort Crc16(byte[] bytes)
24 {
25 ushort poly = 0x1021;
26 ushort[] table = new ushort[256];
27 ushort initialValue = 0x0;
28 ushort temp, a;
29 ushort crc = initialValue;
30 for (int i = 0; i < table.Length; ++i)
31 {
32 temp = 0;
33 a = (ushort)(i << 8);
34 for (int j = 0; j < 8; ++j)
35 {
36 if (((temp ^ a) & 0x8000) != 0)
37 temp = (ushort)((temp << 1) ^ poly);
38 else
39 temp <<= 1;
40 a <<= 1;
41 }
42 table[i] = temp;
43 }
44 for (int i = 0; i < bytes.Length; ++i)
45 {
46 crc = (ushort)((crc << 8) ^ table[((crc >> 8) ^ (0xff & bytes[i]))]);
47 }
48 return crc;
49 }

  data.txt 文件下载

8.校验算出来的字符串 对应 的slot位置 是否正确

9.批量设置和批量删除方法
假定三主三从,那么三台服务器,取九个slot字符串,这九个是均分的位置(均分利于集群扩展)。即16384/10=1638 1638是第一位,1638*2是第二位,以此类推取字符串
共九个["1A73F","18B13","1AAD3","184FF","143BF","18413","17B8D","18BFF","1B1C4"]
先分组,再批量插入,再批量删除

 1 try
2 {
3 var redisConn = "{集群地址}";
4 var connect = ConnectionMultiplexer.Connect(redisConn);
5 var redisDb = connect.GetDatabase();
6 var res1 = redisDb.StringSet("1", DateTime.Now.ToString(), TimeSpan.FromSeconds(600));
7 var res2 = redisDb.StringSet("1111", DateTime.Now.ToString(), TimeSpan.FromSeconds(600));
8 redisDb.KeyDelete(new RedisKey[] { "1", "1111" });
9
10
11 var redisSlotKeyList = new string[] { "1A73F", "18B13", "1AAD3", "184FF", "143BF", "18413", "17B8D", "18BFF", "1B1C4" };
12 var userIdArray = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
13 //group
14 var dic = new Dictionary<int, Dictionary<RedisKey,RedisValue>>();
15 foreach (var userId in userIdArray)
16 {
17 var index = userId % redisSlotKeyList.Length;
18 var slotKey = redisSlotKeyList[index];
19 var redisKey = $"{{{slotKey}}}test_{userId}";
20 Console.WriteLine($"{ redisKey} {userId}");
21 if (dic.ContainsKey(index))
22 {
23 dic[index].Add(redisKey, DateTime.Now.ToLongTimeString());
24 }
25 else
26 {
27 dic[index] = new Dictionary<RedisKey, RedisValue> { { new RedisKey(redisKey), new RedisValue("values") } };
28 }
29 }
30
31 //set
32 foreach (var item in dic)
33 {
34 var addRes = redisDb.StringSet(item.Value.ToArray());
35 Console.WriteLine(addRes);
36 }
37
38
39 //delete
40 foreach (var item in dic)
41 {
42 var deleteRes = redisDb.KeyDelete(item.Value.Keys.ToArray());
43 Console.WriteLine(deleteRes);
44 }
45
46
47
48 }
49 catch (Exception ex)
50 {
51 throw ex;
52 }

10.注意点
集群的分割slot配置不一定的均分的,提前先查看,命令:cluster nodes。 查看之后再根据实际情况取slot string

C# redis集群批量操作之slot计算出16384个字符串的更多相关文章

  1. Redis集群批量操作

    Redis在3.0版正式引入了集群这个特性,扩展变得非常简单.然而当你开心的升级到3.0后,却发现有些很好用的功能现在工作不了了, 比如我们今天要聊的pipeline功能等批量操作. Redis集群是 ...

  2. 深入浅出—Redis集群的相关详解

    前言: 这篇文章主要介绍了Redis集群的相关,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值. 注意!要求使用的都是redis3.0以上的版本,因为3.0以上增加了red ...

  3. redis集群报错:(error) CLUSTERDOWN Hash slot not served

    百度上坑太多,如果你遇到搭建redis集群的时候出现这个错误在百度上找到解决办法基本上都是坑. 首先集群搭建完成后,你肯定去登陆redis进行测试 1.redis01/redis-cli -h &qu ...

  4. .NET使用Task动态创建多任务多线程并行程序计算Redis集群keys计算

    Task是一个很好用的多任务处理类,并且通过Task可以对任务进行很好的控制. 下面将通过代码实现Redis集群在使用IServer.keys时通过多任务对多个服务器示例进行并行计算,并对返回key做 ...

  5. redis集群错误解决:/usr/lib/ruby/gems/1.8/gems/redis-3.0.0/lib/redis/client.rb:79:in `call': ERR Slot 15495 is already busy (Redis::CommandError)

    错误信息: /usr/lib/ruby/gems/1.8/gems/redis-3.0.0/lib/redis/client.rb:79:in `call': ERR Slot 15495 is al ...

  6. Redis集群环境各节点无法互相发现与Hash槽分配异常 CLUSTERDOWN Hash slot not served的解决方式

    总结/朱季谦 在搭建Redis5.x版本的集群环境曾出现各节点无法互相发现与Hash槽分配异常 CLUSTERDOWN Hash slot not served的情况,故而把解决方式记录下来. 在以下 ...

  7. Redis集群最佳实践

    今天我们来聊一聊Redis集群.先看看集群的特点,我对它的理解是要需要同时满足高可用性以及可扩展性,即任何时候对外的接口都要是基本可用的并具备一定的灾备能力,同时节点的数量能够根据业务量级的大小动态的 ...

  8. redis 集群配置实战

    文章转载自:http://hot66hot.iteye.com/blog/2050676 最近研究Redis-cluster,正好搭建了一个环境,遇到了很多坑,系统的总结下,等到redis3 rele ...

  9. redis集群讨论

    一.生产应用场景 二.存储架构演变 三.应用最佳实践 四.运维经验总结 第1.2节:介绍redis cluster在唯品会的生产应用场景,以及存储架构的演变.第3节:redis cluster的稳定性 ...

随机推荐

  1. 010_Java基础语法

    目录 Java基础语法 注释 单行注释 // 多行注释 /* */ 文档注释 /** */ 标识符 关键字 标识符注意点 数据类型 强类型语言 弱类型语言 Java基础语法 注释 单行注释 // 多行 ...

  2. 十年老苹果(A1286)强升Catalina及Win10踩坑记(续)

    背景 自上次发布十年老苹果(A1286)强升Catalina及Win10踩坑记以来,因为后半部分-----系统安装上的细节描述过于简略,一些朋友在安装过程中总是又遇到坑,由此特意详述这一过程,让园友少 ...

  3. pycharm调试bug Process finished with exit code -1073740791 (0xC0000409)

    我经常py代码出错 控制台只提示这个 Process finished with exit code -1073740791 (0xC0000409) 但是根本没有报错原因 首先我们应该改一下pych ...

  4. oneshot_tjctf_2016

    简单题,容易想到先泄漏libc基址,然后jump to onegadget 从而getshell from pwn import * ''' author: lemon time: 2020-10-2 ...

  5. webpack4的安装使用

    1.全局安装Webpack 安装到全局后你可以在任何地方共用一个 Webpack 可执行文件( 也就是说可以直接在终端使用webpack的命名 ,例如:webpack --config webpack ...

  6. java数据结构-08队列

    一.什么是队列 队列是一种特殊的线性表,只能在头尾两端进行操作,特点是先进先出:就像排队买票一样,先来的先买 二.接口设计  三.代码实现 可以使用动态数组.链表等实现:这里两种实现栈与双向链表 1. ...

  7. 843. Guess the Word —— weekly contest 86

    题目链接:https://leetcode.com/problems/guess-the-word/description/ 占坑 据说要用启发式算法,可参考下述答案进行学习:https://leet ...

  8. How to using code find the menu label of Menus【X++】

    // VAR Changed by Xie Yu Fan.Fandy 谢宇帆 static void XIE_FindMenu(Args _args) { Dialog dlg = new Dialo ...

  9. 【linux】-Makefile简要知识+一个通用Makefile

    目录 Makefile Makefile规则与示例 为什么需要Makefile Makefile样式 先介绍Makefile的两个函数 完善Makefile 通用Makefile的使用 通用的Make ...

  10. php支付宝签名验证类

    <?php /* * 黎明互联 * https://www.liminghulian.com/ */ class RSA { /** * RSA签名 * @param $data 待签名数据 * ...