C# redis集群批量操作之slot计算出16384个字符串
引入一个大家都用的到的需求来说吧。
需求:要在三主三从的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 }
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个字符串的更多相关文章
- Redis集群批量操作
Redis在3.0版正式引入了集群这个特性,扩展变得非常简单.然而当你开心的升级到3.0后,却发现有些很好用的功能现在工作不了了, 比如我们今天要聊的pipeline功能等批量操作. Redis集群是 ...
- 深入浅出—Redis集群的相关详解
前言: 这篇文章主要介绍了Redis集群的相关,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值. 注意!要求使用的都是redis3.0以上的版本,因为3.0以上增加了red ...
- redis集群报错:(error) CLUSTERDOWN Hash slot not served
百度上坑太多,如果你遇到搭建redis集群的时候出现这个错误在百度上找到解决办法基本上都是坑. 首先集群搭建完成后,你肯定去登陆redis进行测试 1.redis01/redis-cli -h &qu ...
- .NET使用Task动态创建多任务多线程并行程序计算Redis集群keys计算
Task是一个很好用的多任务处理类,并且通过Task可以对任务进行很好的控制. 下面将通过代码实现Redis集群在使用IServer.keys时通过多任务对多个服务器示例进行并行计算,并对返回key做 ...
- 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 ...
- Redis集群环境各节点无法互相发现与Hash槽分配异常 CLUSTERDOWN Hash slot not served的解决方式
总结/朱季谦 在搭建Redis5.x版本的集群环境曾出现各节点无法互相发现与Hash槽分配异常 CLUSTERDOWN Hash slot not served的情况,故而把解决方式记录下来. 在以下 ...
- Redis集群最佳实践
今天我们来聊一聊Redis集群.先看看集群的特点,我对它的理解是要需要同时满足高可用性以及可扩展性,即任何时候对外的接口都要是基本可用的并具备一定的灾备能力,同时节点的数量能够根据业务量级的大小动态的 ...
- redis 集群配置实战
文章转载自:http://hot66hot.iteye.com/blog/2050676 最近研究Redis-cluster,正好搭建了一个环境,遇到了很多坑,系统的总结下,等到redis3 rele ...
- redis集群讨论
一.生产应用场景 二.存储架构演变 三.应用最佳实践 四.运维经验总结 第1.2节:介绍redis cluster在唯品会的生产应用场景,以及存储架构的演变.第3节:redis cluster的稳定性 ...
随机推荐
- CTF相关
https://blog.csdn.net/zxl2016/article/details/96482763
- 【转】Loading PNGs with SDL_image
FROM:http://lazyfoo.net/tutorials/SDL/06_extension_libraries_and_loading_other_image_formats/index2. ...
- Hive 如何快速拉取大批量数据
用hive来做数仓类操作,或者大数据的运算,是没有疑问的,至少在你没有更多选择之前. 当我们要hive来做类似于大批量数据的select时,也许问题就会发生了变化. 1. 通用解决方案之分页 首先,我 ...
- shell脚本之字符串测试表达式
1.字符串测试操作符 字符串测试操作符的作用有:比较两个字符串是否相同.字符串的长度是否为零,字符串是否为NULL(注:bash区分零长度字符串和空字符串等) 下表为常用字符串操作符 也可以通过man ...
- Android Studio的第一次经历
第一个简单APP的制作是从xml开始的,通过在java新建一个empty activity,并在layout里找到对应的xml文件进行编写.每编写一个xml就要事先新建 一个对应的empty ac ...
- Python常用组件、命令大总结(持续更新)
Python开发常用组件.命令(干货) 持续更新中-关注公众号"轻松学编程"了解更多. 1.生成6位数字随机验证码 import random import string def ...
- 初步配置基于Struts的maven的Web项目demo
1.创建mavenweb项目 eclipse | Idea 中创建maven项目,具体步骤PASS. 2.导入Struts2核心架包 Idea中在maven项目上,选择ADD FRAMEWORK ec ...
- 构建者模式(Builder pattern)
构建者模式应用场景: 主要用来构建一些复杂对象,这里的复杂对象比如说:在建造大楼时,需要先打牢地基,搭建框架,然后自下向上地一层一层盖起来.通常,在建造这种复杂结构的物体时,很难一气呵成.我们需要首先 ...
- 正式班D25
2020.11.09星期一 正式班D25 目录 13.7 LVM 13.7.1 lvm简介 13.7.2 lvm基本使用 13.7.3 在线动态扩容 13.7.4 在线动态缩容与删除 13.7.5 快 ...
- 为什么要谨慎使用Arrays.asList、ArrayList的subList?
1. 使用Arrays.asList的注意事项 1.1 可能会踩的坑 先来看下Arrays.asList的使用: List<Integer> statusList = Arrays.asL ...