zoukankan      html  css  js  c++  java
  • KeySpaceNotification 键空间通知

    KeySpaceNotification 键空间通知

    1、Redis键淘汰机制简介

    在Redis中,内存的大小是有限的,所以为了防止内存饱和,需要实现某种键淘汰策略。主要有两种方法,一种是当Redis内存不足时所采用的内存释放策略。第二种是对过期键进行删除的策略,也可以在某种程度上释放内存。

    1.1 Redis键过期淘汰的策略

    当需要进行内存释放的时候,需要用某种策略对保存的的对象进行删除。Redis有六种策略:

    volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰

    volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰

    volatile-random:从已设置过期时间的数据集中任意选择数据淘汰

    allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰

    allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰

    no-enviction(驱逐):禁止驱逐数据

    2、KeySpaceNotification功能

    2.1 开启KeySpaceNotification功能

    默认情况下,该功能是关闭的,因为该功能消耗部分CPU。开启该功能需要修改redis的配置文件。

    当前需要修改的配置的机器有两台:Redis1、Redis2

    配置文件的路径均为: /etc/redis

    clip_image002

    图1 Redis1中需要修改的配置文件

    clip_image004

    图2 Redis2中需要修改的配置文件

    2.2 修改配置文件

    1. 使用vi 6379.conf 进入文件;

    clip_image006

    图3 使用vi指令进入配置文件

    2. 输入/keyspace,回车后定位到该功能开启部分;

    clip_image008

    图4 定位keyspace

    clip_image009

    图4 查看通知功能介绍

    3. 修改配置文件为下图所示 KEA表示所有的操作都会向相应的频道中发布通知信息;

    clip_image011

    图5 修改后的配置文件

    4. 按下Esc,输入:wq! 回车保存文件;

    5. 按照上述过程将所有的配置文件。

    6. 重启Redis1、Redis2,使键空间通知功能开启。

    3、使用键空间通知功能

    3.1 实现频道的订阅

    public class jedisSubscribe {
    
    public static void main(String[] args) {
    
      Set<HostAndPort> jedisClusterNodes=new HashSet<HostAndPort>();
    
      JedisCluster cluster;
    
      cluster = new JedisCluster(RedisPool.loadServers());
    
      String host1 = "192.168.1.34";
    
      JedisPubSub jedisPubSub = null;
    
      jedisPubSub = new JedisPubSub() {
    
      /*
    
      * 常规模式:关闭订阅时触发arg0 key值 arg1 订阅数量
    
      */
    
      public void onUnsubscribe(String arg0, int arg1) {
    
      }
    
      /*
    
      * 常规模式:启动订阅时触发arg0 key值 arg1 订阅数量
    
      */
    
      public void onSubscribe(String arg0, int arg1) {
    
        System.out.println("Success onSubscribe "+arg0);
    
      }
    
      /*
    
      * 常规模式:收到匹配key值的消息时触发arg0 key值arg1 收到的消息值
    
      */
    
      public void onMessage(String arg0, String arg1) {
    
        System.out.println("Get Message "+arg1);
    
        System.out.println("Get "+arg0);
    
        String key = cluster.get(arg0);
    
        System.out.println("Success "+key);
    
      }
    
      /*
    
      * 正则模式:关闭正则类型订阅时触发
    
      * arg0 key的正则表达式arg1 订阅数量
    
      */
    
      public void onPUnsubscribe(String arg0, int arg1) {
      
      }
    
      /*
    
      * 正则模式:启动正则类型订阅时触发
    
      * arg0 key的正则表达式
    
      * arg1 订阅数量
    
      */
    
      public void onPSubscribe(String arg0, int arg1) {
      
      }
    
      /*
    
      * 正则模式:收到匹配key值的消息时触发
    
      * arg0订阅的key正则表达式
    
      * arg1匹配上该正则key值
    
      * arg2收到的消息值
    
      */
    
      public void onPMessage(String arg0, String arg1, String arg2) {
      
      }
    
    };
    
      String channel4 = "__keyevent@0__:expire";//设置订阅的频道channels
    
      JedisPool jedisPool1 = new JedisPool(host1);
    
      jedisPool1.getResource().subscribe(jedisPubSub, channel4);
    
      }
    
    }

    3.2 对Redis中的键进行操作

    public static void main(String[] args) throws InterruptedException {
    
      Set<HostAndPort> jedisClusterNodes=new HashSet<HostAndPort>();
    
      JedisCluster cluster;
    
      cluster = new JedisCluster(RedisPool.loadServers());
    
      String key = "name";//设置一个key
    
      String value = "zpf";//设置该key的value
    
      cluster.set(key, value);//向redis中写入该(key,value)
    
      cluster.expire(key, 2);//设置key过期时间为2秒
    
      cluster.del(key);
    
    }
    3.3 运行结果

    clip_image013

    4.车辆信息的实时性维护

    4.1利用键空间通知的方法

    Redis会在设置过期时间的键集合中随机抽选进行键的判断,如果过期则进行删除操作,同时会向频道 __keyevent@0__:expire中过期消息,并且监听这个频道的程序会得到过期的键是哪一个键。也会向频道 __keyspace@0__:key中发布该键过期的消息,其中这里的频道根据过期的键key不同发布的频道也不同。进行删除操作时,Redis也会向频道__keyevent@0__:del和 __keyspace@0__:key中分别发布消息。

    为了维护车辆信息的实时性,需要对过期的车辆数据进行相应的删除操作,但是Redis中的删除操作只能将对应的key删除掉,这里的需求是进行网格以及其他相应的维护操作,删除操作是不相同的。因此需要再删除之前得到过期的key的值value。

    clip_image015

    clip_image017

    根据上面的描述,无法再订阅频道__keyevent@0__:expire接收到通知的时候得到过期键的值value。为了实现借助Redis的删除功能需要在该频道接收到信息之前得到要过期的key的值value。但是这样的话又成了对redis的判断操作。为了实现得到过期键的value,可以通过在得到该数据并进行设置过期时间的时候提前构造一个map<key,value>其中key为车牌,value为车牌+原始信息的value。这样在频道__keyevent@0__:expire接收到通知时,就可以使用map得到相应的value值。

    4.2 使用该方法造成的问题

    构造map时,需要对每一辆车进行判断,如果车牌key不在此map中时,需要将该信息放入map中;如果车牌key存在此map中,需要更新map。那么存储该map需要占用额外的存储空间。

    5.参考资料

    http://redis.io/topics/notifications

    https://cnodejs.org/topic/5577b493c4e7fbea6e9a33c9#5577e266c4e7fbea6e9a3449

    http://redisdoc.com/topic/notification.html#id1

    http://blog.csdn.net/caishenfans/article/details/44902651

    https://github.com/antirez/redis/issues/594

  • 相关阅读:
    基本MVVM 和 ICommand用法举例(转)
    WPF C# 命令的运行机制
    628. Maximum Product of Three Numbers
    605. Can Place Flowers
    581. Shortest Unsorted Continuous Subarray
    152. Maximum Product Subarray
    216. Combination Sum III
    448. Find All Numbers Disappeared in an Array
    268. Missing Number
    414. Third Maximum Number
  • 原文地址:https://www.cnblogs.com/zpfbuaa/p/5997773.html
Copyright © 2011-2022 走看看