codis刷新缓存/删除所有key/flushall

codis不支持flush命令,使得我们无法清空key,虽然我们大部分时候都不应该让key大量失效,但是总有些系统/场景需要用到。想了很久,可以有个两个办法。

一、使用lua

我们知道codis是支持lua的,可以通过发送lua脚本去刷新。由于只发送少量代码“flushall”,可以采用直接发送代码的形式。不过这里有个问题就是lua脚本依然是通过参数决定将该命令发送到哪一台,算法跟普通API操作key一样,也是CRC32(key)%1024,因此我们需要想办法能够刷新指定的redis实例。

我们知道codis一共有1024个桶,所以我们可以构造能hash到这1024个桶的参数,然后发送命令,即可保证后端所有的server被刷新。

1、构造导航数据:

        CRC32 crc32 = new CRC32();
        
        // 寻找每个slot对应的导航参数
        for (int i = 0; i < 1024; i++)
        {
            for (int j = 0; j < Integer.MAX_VALUE; j++)
            {
                crc32.update(String.valueOf(j).getBytes());
                
                Long num = crc32.getValue();
                
                if (num % 1024 == i)
                {
                    guideData.put(Integer.valueOf(i), Integer.valueOf(j));
                    
                    break;
                }
            }
        }

2、依次刷新(这里也可以使用pipeline,但是经测试老报read time out,可能是发送的命令过多,导致结果不能及时返回,可以每几十个命令提交一次)

 for (Map.Entry<Integer, Integer> entry : guideData.entrySet())
        {
            jedis.eval("redis.call('flushall')", 1, entry.getValue().toString());
        }

这个方案的优点是简单,易于理解,对codis集群无侵入。缺点一是实现强依赖codis的实现,如果codis的桶数量、hash算法有改变,必须同步做出改变,二是由于每个server可能对应多个slot,每个server可能被刷新了N遍,看起来有点二。不过server有数据时刷新时才会占用时间,如果没有数据,比如空的集群,刷新也很快。经测试,空数据集群1024次flush几乎秒级返回。当然也可以根据集群情况进一步优化,没必要刷新所有slot。

二、读取zookeeper

codis所有的集群信息都在zk中有注册,可以读取zk上的group数据,获取主server的ip和port,然后使用底层链接刷新server。一个节点信息如下:

其中action为空的是主, {state:"synced"}的是从,如果从不synced主,则无法区分。

这个方案的优点是代码看起来逻辑性强,符合正常思维。缺点一是实现复杂,需要操作zk,且zk的数据让不让读需要确认(这里没做代码验证,zk是有权限控制的),再者codis存储在zk上的数据结构发生变化的话,这里依然需要同步做修改。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

济南大飞哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值