wangyongshan 2008-11-03 21:48
浏览 193
已采纳

问大家一个 memcached 缓存策略

问题是这样的:

我有一个 IP 地址库(里面有近 40万 条IP地址记录),表结构是这样的:
[color=darkred]
id —— 主键,自增长
fromip —— ip地址段的开始值(long型的-将ip地址转换成long型存入的)
toip —— ip地址段的结束值(long型的)
unit —— 该ip段分配给的单位名称[/color]

我主要的任务就是:查询一个IP地址在哪个IP地址段范围内,并给出其分配的单位名称。
SQL语句类似这样([color=darkblue]976362050 ——是一个IP地址的long型值[/color]):

[color=darkred]select unit from ipglobe where fromip < 976362050 and toip > 976362050[/color]

因为要大量查询一些IP地址在哪个IP地址段范围内,所以如果每次都从数据库近40万条记录中检索,速度很慢。

于是就想采用 memcached 缓存策略,但是想了好几天,也没有想到该如何缓存这些数据?

曾经想到这样一个方法:
[color=darkblue]将近40万记录以 key = "fromip#toip" value="unit" 形式存放,然后遍历所有的 key ,取key分离出fromip和toip,然后判断给的IP值是否在该key的范围内。[/color]

但是后来发现遍历memcached中所有的 key 是不行的,所以想请教一下该怎么设计存储策略?? (我用的是 Java 语言)

  • 写回答

1条回答 默认 最新

  • nomoney_boy 2008-11-04 13:16
    关注

    1.你可不可以通过一个KEY,VALUE为FORMIP,TOIP组装成一个字串

    遍历memcached中所有的 key 是行的,看看下面这个方法

    // memcache中的KEY遍历(当前slab)
    // 一个SLAB中包含 多个dump
    public static void keySet() {
        Set<String> keys = new HashSet<String>();
        Map<String, Integer> dumps = new HashMap<String, Integer>();
        // 获取所有的slab(由服务器地址:端口号组成KEY,dump信息组成value)
        Map slabs = getMemCachedClient().statsItems();
    
        Iterator itemsItr = slabs.keySet().iterator();
        // 用来收集所有slab的dump号
        while (itemsItr.hasNext()) {
            String server = itemsItr.next().toString();
            Map itemNames = (Map) slabs.get(server);
            System.out.println(itemNames);
            Iterator itemNameItr = itemNames.keySet().iterator();
            while (itemNameItr.hasNext()) {
                String itemName = itemNameItr.next().toString();
    
                String[] itemAtt = itemName.split(":");
                // 如果是itemName中是:number来表示,那么证明是一个存储数据的dump,还有一些是age的部分
                if (itemAtt[2].startsWith("number")) {
                    System.out.println(itemAtt[1] + "        " + Integer.parseInt(itemAtt[1]));
                    // put dump区号
                    dumps.put(itemAtt[1], Integer.parseInt(itemAtt[1]));
                }
            }
        }
        // 根据收集到的dump来获取keys
        if (!dumps.values().isEmpty()) {
            Iterator<Integer> dumpIter = dumps.values().iterator();
            while (dumpIter.hasNext()) {
                int dump = dumpIter.next();
                // statsCacheDump支持三个参数String[],int,int,第一个参数可以省略,默认填入null,表示从那些slab中获取dump号为第二个参数的keys,如果是null就从当前所有的slab中获取。
                // 第二个参数表示dump号,第三个参数表示返回最多多少个结果。
                // {127.0.0.1:11211={DD=[2 b; 1223911432 s], AA=[2 b; 1223911432 s], BB=[2 b; 1223911432 s]}}
                Map cacheDump = getMemCachedClient().statsCacheDump(dump, 10);
                System.out.println(cacheDump);
                Iterator entryIter = cacheDump.values().iterator();
                while (entryIter.hasNext()) {
                    Map items = (Map) entryIter.next();
                    Iterator ks = items.keySet().iterator();
                    while (ks.hasNext()) {
                        String k = (String) ks.next();
                        try {
                            // 这里为什么要作decode,因为其实在我使用的这个java客户端存储的时候,默认会把key都作encoding一次,所以必须要做,不然会出现问题。
                            k = URLDecoder.decode(k, "UTF-8");
                            // key 对应的VALUE是这个值的长度,过期时间
                            System.out.println(k);
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
    
                    }
                }
            }
    
        }
    
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 安装 opencv4nodejs 报错
  • ¥15 adb push异常 adb: error: 1409-byte write failed: Invalid argument
  • ¥15 nginx反向代理获取ip,java获取真实ip
  • ¥15 eda:门禁系统设计
  • ¥50 如何使用js去调用vscode-js-debugger的方法去调试网页
  • ¥15 376.1电表主站通信协议下发指令全被否认问题
  • ¥15 物体双站RCS和其组成阵列后的双站RCS关系验证
  • ¥15 复杂网络,变滞后传递熵,FDA
  • ¥20 csv格式数据集预处理及模型选择
  • ¥15 部分网页页面无法显示!