• redis 一致性hash


    使用zookeeper 实现一致性hash。

    redis服务启动时,将自己的路由信息通过临时节点方式写入zk,客户端通过zk client读取可用的路由信息。

    image_thumb[12]

    服务端

    使用python 脚本写的守护进程:https://github.com/LittlePeng/redis-manager

    脚本部署在redis-server本机,定时ping redis-server

    节点失效的情况:

    1.服务器与ZK服务器失去连接 Session Expired ,环境网络波动造成,需要根据网络情况设置适当zookeeper的Timeout时间,避免此情况发生

    2. 服务器宕机,Zookeeper server 发现zkclient ping超时,就会通知节点下线

    3. redis-server 挂了,redis-manager ping 超时主动断开与zookeeper server的连接

    客户端

    需要zkclient监控 节点变化,及时更新路由策略

    下面是C# 版本一致性hash算法:

       1:  class KetamaNodeLocator
       2:      {
       3:          private Dictionary<long, RedisCluster> ketamaNodes;
       4:          private HashAlgorithm hashAlg;
       5:          private int numReps = 160;
       6:          private long[] keys;
       7:   
       8:          public KetamaNodeLocator(List<RedisCluster> nodes)
       9:          {
      10:              ketamaNodes = new Dictionary<long, RedisCluster>();
      11:   
      12:              //对所有节点,生成nCopies个虚拟结点
      13:              for (int j = 0; j < nodes.Count; j++) {
      14:                  RedisCluster node = nodes[j];
      15:                  int numReps = node.Weight;
      16:   
      17:                  //每四个虚拟结点为一组
      18:                  for (int i = 0; i < numReps / 4; i++) {
      19:                      byte[] digest = ComputeMd5(
      20:                          String.Format("{0}_{1}_{2}", node.RoleName, node.RouteValue, i));
      21:   
      22:                      /** Md5是一个16字节长度的数组,将16字节的数组每四个字节一组,
      23:                       * 分别对应一个虚拟结点,这就是为什么上面把虚拟结点四个划分一组的原因*/
      24:                      for (int h = 0; h < 4; h++) {
      25:   
      26:                          long rv = ((long)(digest[3 + h * 4] & 0xFF) << 24)
      27:                                     | ((long)(digest[2 + h * 4] & 0xFF) << 16)
      28:                                     | ((long)(digest[1 + h * 4] & 0xFF) << 8)
      29:                                     | ((long)digest[0 + h * 4] & 0xFF);
      30:   
      31:                          rv = rv & 0xffffffffL; /* Truncate to 32-bits */
      32:                          ketamaNodes[rv] = node;
      33:                      }
      34:                  }
      35:              }
      36:   
      37:              keys = ketamaNodes.Keys.OrderBy(p => p).ToArray();
      38:          }
      41:          public RedisCluster GetWorkerNode(string k)
      42:          {
      43:              byte[] digest = ComputeMd5(k);
      44:              return GetNodeInner(Hash(digest, 0));
      45:          }
      46:   
      47:          RedisCluster GetNodeInner(long hash)
      48:          {
      49:              if (ketamaNodes.Count == 0)
      50:                  return null;
      51:              long key = hash;
      52:              int near = 0;
      53:              int index = Array.BinarySearch(keys, hash);
      54:              if (index < 0) {
      55:                  near = (~index);
      56:                  if (near == keys.Length)
      57:                      near = 0;
      58:              }
      59:              else {
      60:                  near = index;
      61:              }
      62:   
      63:              return ketamaNodes[keys[near]];
      64:          }
      65:   
      66:          public static long Hash(byte[] digest, int nTime)
      67:          {
      68:              long rv = ((long)(digest[3 + nTime * 4] & 0xFF) << 24)
      69:                      | ((long)(digest[2 + nTime * 4] & 0xFF) << 16)
      70:                      | ((long)(digest[1 + nTime * 4] & 0xFF) << 8)
      71:                      | ((long)digest[0 + nTime * 4] & 0xFF);
      72:   
      73:              return rv & 0xffffffffL; /* Truncate to 32-bits */
      74:          }
     
      79:          public static byte[] ComputeMd5(string k)
      80:          {
      81:              MD5 md5 = new MD5CryptoServiceProvider();
      82:   
      83:              byte[] keyBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(k));
      84:              md5.Clear();
      85:              return keyBytes;
      86:          }
      87:      }
  • 相关阅读:
    一步步介绍如何给项目添加单元测试
    日期格式化在移动端的问题
    使用VW时,图片的问题
    转:vw适配中使用伪类选择器遇到的问题
    ES6模块的import和export用法总结
    转:如何在Vue项目中使用vw实现移动端适配
    PhpStrom添加调试功能
    小程序商城笔记
    使用TortoiseGit对android studio工程进行代码版本控制
    Android Studio 常见异常解决办法
  • 原文地址:https://www.cnblogs.com/lulu/p/3130906.html
Copyright © 2020-2023  润新知