Redis

作者: Roct | 来源:发表于2019-10-10 17:48 被阅读0次

    Redis启动方法

    1. redis-server和redis-cli默认启动

    进入redis安装目录的src下

    cd /usr/local/redis-5.0.4/src/
    

    启动服务

     → /usr/local/redis-5.0.4/src$ ./redis-server
    5693:C 10 Oct 2019 17:06:43.321 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
    5693:C 10 Oct 2019 17:06:43.323 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=5693, just started
    5693:C 10 Oct 2019 17:06:43.323 # Warning: no config file specified, using the default config. In order to specify a config file use ./redis-server /path/to/redis.conf
    5693:M 10 Oct 2019 17:06:43.328 * Increased maximum number of open files to 10032 (it was originally set to 256).
                    _._
               _.-``__ ''-._
          _.-``    `.  `_.  ''-._           Redis 5.0.4 (00000000/0) 64 bit
      .-`` .-```.  ```\/    _.,_ ''-._
     (    '      ,       .-`  | `,    )     Running in standalone mode
     |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
     |    `-._   `._    /     _.-'    |     PID: 5693
      `-._    `-._  `-./  _.-'    _.-'
     |`-._`-._    `-.__.-'    _.-'_.-'|
     |    `-._`-._        _.-'_.-'    |           http://redis.io
      `-._    `-._`-.__.-'_.-'    _.-'
     |`-._`-._    `-.__.-'    _.-'_.-'|
     |    `-._`-._        _.-'_.-'    |
      `-._    `-._`-.__.-'_.-'    _.-'
          `-._    `-.__.-'    _.-'
              `-._        _.-'
                  `-.__.-'
    
    5693:M 10 Oct 2019 17:06:43.334 # Server initialized
    5693:M 10 Oct 2019 17:06:43.334 * Ready to accept connections
    

    链接redis

     → /usr/local/redis-5.0.4/src$ ./redis-cli
    127.0.0.1:6379> keys *
    (empty list or set)
    

    指定端口启动

    # 指定6390端口启动redis服务
    ./redis-server --port 6390
    
    ./redis-cli -p 6390
    

    指定某个配置文件启动

    ./redis-server ../redis.conf
    

    链接远程的redis

    # 6390为端口号 127.0.0.1 为本地ip, 链接远程redis直接更换为远程服务器的ip
    ./redis-cli -p 6390 -h 127.0.0.1
    

    配置密码

    修改redis的配置文件以设置密码

    ## ruiredis为密码
    requirepass ruiredis
    

    使用配置文件启动

    ./redis-server ../redis.conf
    

    链接redis, 如果不输入密码或者输入错误密码, 也可以链接到redis, 但是查看keys或者做别的操作会提示

     → /usr/local/redis-5.0.4/src$ ./redis-cli
    127.0.0.1:6379> keys *
    (error) NOAUTH Authentication required.
    127.0.0.1:6379>
    

    输入密码链接

     → /usr/local/redis-5.0.4/src$ ./redis-cli -a ruiredis
    127.0.0.1:6379> keys *
    1) "a"
    127.0.0.1:6379>
    

    Redis键命令

    • 存储一个值
    set key value
    
    127.0.0.1:6379> set name lisi
    OK
    
    • 获取一个值
    get key
    
    127.0.0.1:6379> get name
    "lisi"
    
    • 获取存储列表所有的key
    keys * 
    
    127.0.0.1:6379> keys *
    1) "c"
    2) "b"
    3) "name"
    4) "a"
    
    • 判断一个key是否存在
    exists key
    
    127.0.0.1:6379> exists name
    (integer) 1
    127.0.0.1:6379> exists 9
    (integer) 0
    
    • 判断key的剩余生存时间
    # -1代表永久有效, -2代表不存在
    127.0.0.1:6379> ttl name
    (integer) -1 
    
    • 给一个key设置有效期
    # 给name设置20s的有效期
    127.0.0.1:6379> expire name 20
    (integer) 1
    127.0.0.1:6379> ttl name
    (integer) 18
    
    • 获取key的类型
    127.0.0.1:6379> type b
    string
    
    • 将key 重命名
    # 如果rename是一个存在的key, 那么会将已有的key的value覆盖掉
    127.0.0.1:6379> rename b d
    OK
    127.0.0.1:6379> keys *
    1) "c"
    2) "a"
    3) "d"
    # 如果renamenx一个存在的key, 那么会覆盖失败, 0为覆盖失败, 1是覆盖成功
    127.0.0.1:6379> renamenx b c
    (integer) 0
    127.0.0.1:6379> renamenx b m
    (integer) 1
    

    Redis数据结构

    1 .字符串

    • setex: 设置有效期为秒
    # 设置key为c, value为d, 有效期为100s
    127.0.0.1:6379> setex c 100 d
    OK
    127.0.0.1:6379> get c
    "d"
    127.0.0.1:6379> ttl c
    (integer) 91
    
    • psetex: 设置有效期为毫秒
    # 设置key为d, value为m, 有效期为10000ms
    127.0.0.1:6379> psetex d 10000 m
    OK
    127.0.0.1:6379> get d
    "m"
    127.0.0.1:6379> ttl d
    (integer) 4
    
    • getrange: 获取范围内的字符串, 闭合区间, 包含边界的元素
    # 获取key为word的前5个字符
    127.0.0.1:6379> set word wordwordword
    OK
    127.0.0.1:6379> get word
    "wordwordword"
    127.0.0.1:6379> getrange word 0 4
    "wordw"
    
    • getset: 返回旧的value并设置一个新的value
    127.0.0.1:6379> set rui rui
    OK
    127.0.0.1:6379> get rui
    "rui"
    127.0.0.1:6379> getset rui rui123
    "rui"
    127.0.0.1:6379> get rui
    "rui123"
    
    • mset: 同时设置多个key
    127.0.0.1:6379> mset r1 1 r2 2 r3 3
    OK
    127.0.0.1:6379> mget r1 r2 r3
    1) "1"
    2) "2"
    3) "3"
    
    • setnx: 当key不存在的时候set成功, 返回1, 当key存在的时候set失败, 返回0
    127.0.0.1:6379> keys *
    1) "word"
    2) "a"
    3) "m"
    4) "r2"
    5) "r1"
    6) "rui"
    7) "r3"
    127.0.0.1:6379> setnx rui 123
    (integer) 0
    127.0.0.1:6379> setnx rui123 345
    (integer) 1
    
    • msetnx: 当key不存在的时候set成功, 当key存在的时候set失败, 且具有事务的原子性, 要么全部成功, 要么全部失败
    127.0.0.1:6379> msetnx rui 123 uuu iii
    (integer) 0
    127.0.0.1:6379> msetnx ruic 123 uuu iii
    (integer) 1
    
    • incr, decr: integer类型增加和减少
    127.0.0.1:6379> set int 1
    OK
    127.0.0.1:6379> incr int # 一次加1
    (integer) 2
    127.0.0.1:6379> incr int
    (integer) 3
    127.0.0.1:6379> incr int
    (integer) 4
    127.0.0.1:6379> get int
    "4"
    127.0.0.1:6379> incrby int 100 # 一次性加100
    (integer) 104
    127.0.0.1:6379> get int
    "104"
    127.0.0.1:6379> decr int
    (integer) 103
    127.0.0.1:6379> decr int
    (integer) 102
    127.0.0.1:6379> decrby int 100
    (integer) 2
    
    • append: 拼接字符串
    127.0.0.1:6379> append int wtf
    (integer) 4
    127.0.0.1:6379> get int
    "2wtf"
    

    2. 哈希hash

    • hset: 存储一个hash类型的数据
    # map是key, name是map的key, lisi是map的value
    127.0.0.1:6379[1]> hset map name lisi
    (integer) 1
    127.0.0.1:6379[1]> type map
    hash
    
    • hexists: 判断map内的key是否存在
    127.0.0.1:6379[1]> hexists map name
    (integer) 1
    127.0.0.1:6379[1]> hexists map namecccc
    (integer) 0
    
    • hget: 获取一个hash类型的数据
    127.0.0.1:6379[1]> hget map name
    "lisi"
    127.0.0.1:6379[1]> hget map cccc
    (nil)
    
    • hgetall: 获取hash的所有数据
    127.0.0.1:6379[1]> hset map age 19
    (integer) 1
    127.0.0.1:6379[1]> hgetall map
    1) "name"
    2) "lisi"
    3) "age"
    4) "19"
    
    • hkeys: 获取所有的key
    127.0.0.1:6379[1]> hkeys map
    1) "name"
    2) "age"
    
    • hvals: 获取所有的value
    127.0.0.1:6379[1]> hvals map
    1) "lisi"
    2) "19"
    
    • hlen: 获取hash类型数据的长度
    127.0.0.1:6379[1]> hlen map
    (integer) 2
    
    • hmget: 一次性获取多个hash类型数据key的值
    127.0.0.1:6379[1]> hmget map name age
    1) "lisi"
    2) "19"
    
    • hmset: 一次性设置多个数据
    127.0.0.1:6379[1]> hmset map newname zhangsan newage 28
    OK
    
    • hdel: 删除hash数据类型数据的值
    127.0.0.1:6379[1]> hdel map newname newage
    (integer) 2
    

    3. 列表list

    # 创建一个key为list的List, 先加入的在最下面
    127.0.0.1:6379[2]> lpush list 1 2 3 4 5 6 7 8
    (integer) 8
    # 获取key
    127.0.0.1:6379[2]> keys *
    1) "list"
    127.0.0.1:6379[2]> type list
    list
    # 获取key为list的数据长度
    127.0.0.1:6379[2]> llen list
    (integer) 8
    # 获取前3个数据,  闭合区间, 包含边界的元素
    127.0.0.1:6379[2]> lrange list 0 2
    1) "8"
    2) "7"
    3) "6"
    # 将最上面的数据修改为100
    127.0.0.1:6379[2]> lset list 0 100
    OK
    127.0.0.1:6379[2]> lrange list 0 2
    1) "100"
    2) "7"
    3) "6"
    # 获取索引为5的数据
    127.0.0.1:6379[2]> lindex list 5
    "3"
    # 删除最上面的元素
    127.0.0.1:6379[2]> lpop list
    "100"
    # 删除最下面的元素
    127.0.0.1:6379[2]> rpop list
    "1"
    127.0.0.1:6379[2]> lrange list 0 100
    1) "7"
    2) "6"
    3) "5"
    4) "4"
    5) "3"
    6) "2"
    

    4. 集合set

    # 创建一个set, key为set
    127.0.0.1:6379[3]> sadd set a b c d
    (integer) 4
    127.0.0.1:6379[3]> keys *
    1) "set"
    127.0.0.1:6379[3]> type set
    set
    # 给set添加一个元素, 如果存在返回0, 如果不存在返回1
    127.0.0.1:6379[3]> sadd set a
    (integer) 0
    # 返回集合内元素的数量
    127.0.0.1:6379[3]> scard set
    (integer) 4
    127.0.0.1:6379[3]> sadd set2 c d e f
    (integer) 4
    127.0.0.1:6379[3]> keys *
    1) "set2"
    2) "set"
    # 获取一个集合内的所有元素
    127.0.0.1:6379[3]> smembers set
    1) "c"
    2) "b"
    3) "a"
    4) "d"
    127.0.0.1:6379[3]> smembers set2
    1) "c"
    2) "e"
    3) "d"
    4) "f"
    # 获取set比set2多的元素,
    127.0.0.1:6379[3]> sdiff set set2
    1) "b"
    2) "a"
    # 获取set2比set多的元素,
    127.0.0.1:6379[3]> sdiff set2 set
    1) "e"
    2) "f"
    # 获取两个集合的交集
    127.0.0.1:6379[3]> sinter set set2
    1) "c"
    2) "d"
    # 获取两个集合的并集
    127.0.0.1:6379[3]> sunion set set2
    1) "b"
    2) "a"
    3) "f"
    4) "c"
    5) "d"
    6) "e"
    # 从集合里随机获取2个元素
    127.0.0.1:6379[3]> srandmember set 2
    1) "b"
    2) "d"
    127.0.0.1:6379[3]> srandmember set 2
    1) "c"
    2) "d"
    # 判断a是否为集合set内部的元素, 如果是返回1, 如果不是返回0
    127.0.0.1:6379[3]> sismember set a
    (integer) 1
    127.0.0.1:6379[3]> sismember set m
    (integer) 0
    # 移除一个或者多个成员, 移除a和b
    127.0.0.1:6379[3]> srem set a b
    (integer) 2
    127.0.0.1:6379[3]> smembers set
    1) "c"
    2) "d"
    # 移除并且返回 一个随机元素
    127.0.0.1:6379[3]> spop set2
    "c"
    127.0.0.1:6379[3]> smembers set2
    1) "e"
    2) "d"
    3) "f"
    

    5. 有序集合sortedset

    # 创建一个有序集合, key为sortedset1 , 内部的key为a b c, value为100 200 300
    127.0.0.1:6379[4]> zadd sortedset1 100 a 200 b 300 c
    (integer) 3
    127.0.0.1:6379[4]> keys *
    1) "sortedset1"
    127.0.0.1:6379[4]> type sortedset1
    zset
    127.0.0.1:6379[4]> rename sortedset1 sortedset
    OK
    # 获取sortedset的元素个数
    127.0.0.1:6379[4]> zcard sortedset
    (integer) 3
    # 获取a的value
    127.0.0.1:6379[4]> zscore sortedset a
    "100"
    # 获取b的value
    127.0.0.1:6379[4]> zscore sortedset b
    "200"
    # 获取c的value
    127.0.0.1:6379[4]> zscore sortedset c
    "300"
    # 获取d的value, 没有不存在返回nil
    127.0.0.1:6379[4]> zscore sortedset d
    (nil)
    # 获取value在[0, 200]的元素的个数
    127.0.0.1:6379[4]> zcount sortedset 0 200
    (integer) 2
    # 获取value在[0, 300]的元素的个数
    127.0.0.1:6379[4]> zcount sortedset 0 300
    (integer) 3
    # 获取a的索引
    127.0.0.1:6379[4]> zrank sortedset a
    (integer) 0
    # 获取b的索引
    127.0.0.1:6379[4]> zrank sortedset b
    (integer) 1
    127.0.0.1:6379[4]> zrank sortedset c
    (integer) 2
    # 获取a的增加1000
    127.0.0.1:6379[4]> zincrby sortedset 1000 a
    "1000"
    # 获取前101个元素的key, 闭合区间
    127.0.0.1:6379[4]> zrange sortedset 0 100
    1) "a"
    2) "b"
    3) "c"
    127.0.0.1:6379[4]> zrange sortedset 0 1
    1) "a"
    2) "b"
    127.0.0.1:6379[4]> zrange sortedset 0 1 withscores
    1) "a"
    2) "100"
    3) "b"
    4) "200"
    

    Redis连接池

    public class RedisPool {
        // jedis连接词
        private static JedisPool pool;
        // 最大连接数
        private static Integer maxTotal = Integer.parseInt(PropertiesUtil.getProperty
                ("redis.max.total", "20"));
        // 最大的Jedispool中最大的idle状态(空闲的)的Jedis实例的个数
        private static Integer maxIdle = Integer.parseInt(PropertiesUtil.getProperty
                ("redis.max.idle", "20"));
        // 最小的Jedispool中最大的idle状态(空闲的)的Jedis实例的个数
        private static Integer minIdle = Integer.parseInt(PropertiesUtil.getProperty
                ("redis.min.idle", "10"));
        // 在brrow一个jedis实例的时候, 是否要进行验证, 如果赋值为true, 那么表示不需要. 从连接池获取链接
        private static Boolean testOnBrrow = Boolean.parseBoolean(PropertiesUtil
                .getProperty
                ("redis.test.testOnBrrow", "true"));
        // 在return一个jedis实例的时候, 是否要进行验证, 如果赋值为true, 那么不需要, 链接归还连接池
        private static Boolean testOnReturn = Boolean.parseBoolean(PropertiesUtil
                .getProperty("redis.test.testOnReturn", "true"));
        // redis的ip
        private static String ip = PropertiesUtil.getProperty("redis.ip");
        // redis的port
        private static Integer port = Integer.parseInt(PropertiesUtil.getProperty
                ("redis.port"));
        private static void initPool() {
            JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
            jedisPoolConfig.setMaxTotal(maxTotal);
            jedisPoolConfig.setMaxIdle(maxIdle);
            jedisPoolConfig.setMinIdle(minIdle);
            jedisPoolConfig.setTestOnBorrow(testOnBrrow);
            jedisPoolConfig.setTestOnReturn(testOnReturn);
            // 链接耗尽的时候 是否阻塞. false会抛出异常, true会阻塞一直到超时, 默认为true
            jedisPoolConfig.setBlockWhenExhausted(true);
            pool = new JedisPool(jedisPoolConfig, ip, port, 1000 * 2);
        }
        // 随着tomcat的启动而初始化
        static {
            initPool();
        }
        // 获取jedis实例
        public static Jedis getJedis() {
            return pool.getResource();
        }
        // 回收jedis
        public static void returnResource(Jedis jedis) {
            pool.returnResource(jedis);
        }
        // 回收坏的链接
        public static void returnBrokenResource(Jedis jedis) {
            pool.returnBrokenResource(jedis);
        }
    
        public static void main(String[] args) {
            Jedis jedis = getJedis();
            jedis.set("ruirui", "dayday");
            returnResource(jedis);
            pool.destroy();
        }
    }
    

    Redis API工具类

    public class RedisPoolUntil {
        private static Logger logger = LoggerFactory.getLogger(CategoryServiceImpl
                .class);
    
        /**
         * 封装set方法
         * @param key
         * @param value
         * @return
         */
        public static String set(String key, String value) {
            Jedis jedis = null;
            String result = null;
            try {
                jedis = RedisPool.getJedis();
                result = jedis.set(key, value);
            } catch (Exception e) {
                logger.error("set key:{} value:{} error:", key, value, e);
                RedisPool.returnBrokenResource(jedis);
                return result;
            }
            RedisPool.returnResource(jedis);
            return result;
        }
    
        /**
         * 重新给key设置过期时间
         * @param key
         * @param exTime 单位为秒
         * @return
         */
        public static Long expire(String key, int exTime) {
            Jedis jedis = null;
            Long result = null;
            try {
                jedis = RedisPool.getJedis();
                result = jedis.expire(key, exTime);
            } catch (Exception e) {
                logger.error("expire key:{} value:{} error:", key, e);
                RedisPool.returnBrokenResource(jedis);
                return result;
            }
            RedisPool.returnResource(jedis);
            return result;
        }
        /**
         * 设置过期时间
         * @param key
         * @param value
         * @param exTime 单位是秒
         * @return
         */
        public static String setEx(String key, String value, int exTime) {
            Jedis jedis = null;
            String result = null;
            try {
                jedis = RedisPool.getJedis();
                result = jedis.setex(key, exTime, value);
            } catch (Exception e) {
                logger.error("setex key:{} value:{} error:", key, value, e);
                RedisPool.returnBrokenResource(jedis);
                return result;
            }
            RedisPool.returnResource(jedis);
            return result;
        }
        /**
         * 封装get方法
         * @param key
         * @return
         */
        public static String get(String key) {
            Jedis jedis = null;
            String result = null;
            try {
                jedis = RedisPool.getJedis();
                result = jedis.get(key);
            } catch (Exception e) {
                logger.error("get key:{} error:", key, e);
                RedisPool.returnBrokenResource(jedis);
                return result;
            }
            RedisPool.returnResource(jedis);
            return result;
        }
    
        /**
         * 删除key
         * @param key
         * @return
         */
        public static Long del(String key) {
            Jedis jedis = null;
            Long result = null;
            try {
                jedis = RedisPool.getJedis();
                result = jedis.del(key);
            } catch (Exception e) {
                logger.error("del:{} error:", key, e);
                RedisPool.returnBrokenResource(jedis);
                return result;
            }
            RedisPool.returnResource(jedis);
            return result;
        }
    }
    
    

    Redis分布式

    Redis分布式算法原理

    传统分布式算法
    例子

    假设有一个图片 test.jpg,我们有 3 个服务器, 服务器1 ,服务器2 ,服务器3
    4 个 redis 节点

    • Redis0
    • Redis1
    • Redis2
    • Redis3
      20个数据


      image

      这上面 1-20 大家就可以认识是 对应数据 hash 之后的结果,然后对这些结果用 4 取模(因为这里有 4 个 Redis 节点).
      1 % 4 = 1 所以将该数据放在 Redis1
      2 % 4 = 2 所以将该数据放在 Redis2
      3 % 4 = 3 所以将该数据放在 Redis3
      4 % 4 = 0 所以将该数据放在 Redis0
      同理,后面的其他数据应该这样放置,如下图


      image
      但是,突然我们发现Redis 的节点不够用了(需要增加节点),或者Redis负载非常低(需要删除节点)。
      这里我们来增加一个节点 Redis4,增加之后的数据再节点上的分部如下图:
      image

      你会发现,只有 redis0 命中了值 20,redis1命中了1,redis2 命中了2,redis3命中了3,命中率为 4/20 = 20%

    Consistent hashing一致性算法原理

    这个算法有一个环形hash空间的概念,通常hash算法都是将value映射在一个32位的key值当中,那么把数据首尾相接就会形成一个圆形,取值范围为0 ~ 2^32-1,这个圆环就是环形hash空间。如下图:


    image

    将对象映射到 圆形hash空间

    • 我们hash 4个 对象 obj1-obj4
    • 通过hash 函数计算出hash 值的key
      落在 环形 hash 空间上的情况如图


      image

      将cache 映射到环形 hash空间

    • 将对象和 cache 都映射到同一个hash 空间,并且使用相同的hash 算法,如下图:


      image

      现在我们就把数据对象和cache 都映射到 hash空间上了,接下来就是要考虑如何将这个对象映射到cache 上面,看下面的图,沿着环形顺时针走,从key1开始,可将obj1 映射到keyA上,obj2 映射到keyC ,obj3映射到keyC,obj4映射到keyB上


      image

    下面来看看移除和添加cache 节点有什么变化


    image

    将cacheB移除,obj4就只能顺时针找到 cacheC了,所以移除一个cache节点,影响的是从该cache节点逆时针开始碰到第一个节点的范围对象,环状的其他区域数据节点都不会影响,如图:


    image

    在 obj2和obj3直接添加一个 cacheD ,如图,我们可以看到obj2 顺时针就会映射到cacheD上,同时受到影响的也是从添加的cache节点逆时针碰到第一个节点的范围


    image
    从上面我们可以看到,cache 的变动,对应数据对象的影响很小。
    Hash倾斜性

    但是呢,要知道理想和现实的差距,我们理想的环状空间是均匀分布的,如图:


    image

    现实却是这样的情况:


    如果用上面的hash 算法,大量的数据对象会映射在 A 节点上,而BC节点很少,这样就导致A节点很忙,BC却很是清闲,这就是因为Hash 的倾斜性造成的。


    image
    虚拟节点

    如何解决Hash 倾斜性导致的问题呢?从而引入了虚拟节点


    image

    比如有 obj1 和 obj 2 两个对象 对其进行 hash 计算,这里增加了 6 个虚拟节点,hash 之后分布落在了 V2,V5上,然后对虚拟节点进行 rehash ,这时 V1,V2映射在 N1上,V3,V4映射在N2上,V5,V6 映射在N3上,obj就映射在了 N1上,obj2映射在N3上。
    引入了 虚拟节点,现在 环状空间是什么样子的呢?看下图


    image

    ABC分别都有对应的影子节点,这时候数据对象的映射就相对均匀了,但是要知道,虚拟节点也有是hash 倾斜性的,这就要在真实节点和虚拟节点之间做一个平衡,分配一个很好的比例,随着节点越来越多,数据越来越多,那么这个分布就会越来越均匀了,在删除节点和添加节点的时候也会把影响降到最小。

    Consistent hashing命中率

    (1-n/(n + m)) * 100%

    • n为服务器台数
    • m为新增服务器台数

    分布式Redis连接池

    public class RedisShardedPool {
        private static ShardedJedisPool pool;//sharded jedis连接池
        private static Integer maxTotal = Integer.parseInt(PropertiesUtil.getProperty("redis.max.total","20")); //最大连接数
        private static Integer maxIdle = Integer.parseInt(PropertiesUtil.getProperty("redis.max.idle","20"));//在jedispool中最大的idle状态(空闲的)的jedis实例的个数
        private static Integer minIdle = Integer.parseInt(PropertiesUtil.getProperty("redis.min.idle","20"));//在jedispool中最小的idle状态(空闲的)的jedis实例的个数
    
        private static Boolean testOnBorrow = Boolean.parseBoolean(PropertiesUtil.getProperty("redis.test.borrow","true"));//在borrow一个jedis实例的时候,是否要进行验证操作,如果赋值true。则得到的jedis实例肯定是可以用的。
        private static Boolean testOnReturn = Boolean.parseBoolean(PropertiesUtil.getProperty("redis.test.return","true"));//在return一个jedis实例的时候,是否要进行验证操作,如果赋值true。则放回jedispool的jedis实例肯定是可以用的。
    
        private static String redis1Ip = PropertiesUtil.getProperty("redis1.ip");
        private static Integer redis1Port = Integer.parseInt(PropertiesUtil.getProperty("redis1.port"));
        private static String redis2Ip = PropertiesUtil.getProperty("redis2.ip");
        private static Integer redis2Port = Integer.parseInt(PropertiesUtil.getProperty("redis2.port"));
    
        private static void initPool(){
            JedisPoolConfig config = new JedisPoolConfig();
    
            config.setMaxTotal(maxTotal);
            config.setMaxIdle(maxIdle);
            config.setMinIdle(minIdle);
    
            config.setTestOnBorrow(testOnBorrow);
            config.setTestOnReturn(testOnReturn);
    
            config.setBlockWhenExhausted(true);//连接耗尽的时候,是否阻塞,false会抛出异常,true阻塞直到超时。默认为true。
    
            JedisShardInfo info1 = new JedisShardInfo(redis1Ip,redis1Port,1000*2);
    
            JedisShardInfo info2 = new JedisShardInfo(redis2Ip,redis2Port,1000*2);
    
            List<JedisShardInfo> jedisShardInfoList = new ArrayList<JedisShardInfo>(2);
    
            jedisShardInfoList.add(info1);
            jedisShardInfoList.add(info2);
    
            pool = new ShardedJedisPool(config,jedisShardInfoList, Hashing.MURMUR_HASH, Sharded.DEFAULT_KEY_TAG_PATTERN);
        }
    
        static{
            initPool();
        }
    
        public static ShardedJedis getJedis(){
            return pool.getResource();
        }
    
    
        public static void returnBrokenResource(ShardedJedis jedis){
            pool.returnBrokenResource(jedis);
        }
    
    
    
        public static void returnResource(ShardedJedis jedis){
            pool.returnResource(jedis);
        }
    
    
        public static void main(String[] args) {
            ShardedJedis jedis = pool.getResource();
    
            for(int i =0;i<10;i++){
                jedis.set("key"+i,"value"+i);
            }
            returnResource(jedis);
    
    //        pool.destroy();//临时调用,销毁连接池中的所有连接
            System.out.println("program is end");
    
    
        }
    }
    
    

    分布式Redis API工具类

    @Slf4j
    public class RedisShardedPoolUtil {
    
        /**
         * 设置key的有效期,单位是秒
         * @param key
         * @param exTime
         * @return
         */
        public static Long expire(String key,int exTime){
            ShardedJedis jedis = null;
            Long result = null;
            try {
                jedis = RedisShardedPool.getJedis();
                result = jedis.expire(key,exTime);
            } catch (Exception e) {
                log.error("expire key:{} error",key,e);
                RedisShardedPool.returnBrokenResource(jedis);
                return result;
            }
            RedisShardedPool.returnResource(jedis);
            return result;
        }
    
        //exTime的单位是秒
        public static String setEx(String key,String value,int exTime){
            ShardedJedis jedis = null;
            String result = null;
            try {
                jedis = RedisShardedPool.getJedis();
                result = jedis.setex(key,exTime,value);
            } catch (Exception e) {
                log.error("setex key:{} value:{} error",key,value,e);
                RedisShardedPool.returnBrokenResource(jedis);
                return result;
            }
            RedisShardedPool.returnResource(jedis);
            return result;
        }
    
        public static String set(String key,String value){
            ShardedJedis jedis = null;
            String result = null;
    
            try {
                jedis = RedisShardedPool.getJedis();
                result = jedis.set(key,value);
            } catch (Exception e) {
                log.error("set key:{} value:{} error",key,value,e);
                RedisShardedPool.returnBrokenResource(jedis);
                return result;
            }
            RedisShardedPool.returnResource(jedis);
            return result;
        }
    
        public static String getSet(String key,String value){
            ShardedJedis jedis = null;
            String result = null;
    
            try {
                jedis = RedisShardedPool.getJedis();
                result = jedis.getSet(key,value);
            } catch (Exception e) {
                log.error("getset key:{} value:{} error",key,value,e);
                RedisShardedPool.returnBrokenResource(jedis);
                return result;
            }
            RedisShardedPool.returnResource(jedis);
            return result;
        }
    
        public static String get(String key){
            ShardedJedis jedis = null;
            String result = null;
            try {
                jedis = RedisShardedPool.getJedis();
                result = jedis.get(key);
            } catch (Exception e) {
                log.error("get key:{} error",key,e);
                RedisShardedPool.returnBrokenResource(jedis);
                return result;
            }
            RedisShardedPool.returnResource(jedis);
            return result;
        }
    
        public static Long del(String key){
            ShardedJedis jedis = null;
            Long result = null;
            try {
                jedis = RedisShardedPool.getJedis();
                result = jedis.del(key);
            } catch (Exception e) {
                log.error("del key:{} error",key,e);
                RedisShardedPool.returnBrokenResource(jedis);
                return result;
            }
            RedisShardedPool.returnResource(jedis);
            return result;
        }
    
        public static Long setnx(String key,String value){
            ShardedJedis jedis = null;
            Long result = null;
    
            try {
                jedis = RedisShardedPool.getJedis();
                result = jedis.setnx(key,value);
            } catch (Exception e) {
                log.error("setnx key:{} value:{} error",key,value,e);
                RedisShardedPool.returnBrokenResource(jedis);
                return result;
            }
            RedisShardedPool.returnResource(jedis);
            return result;
        }
    
    
        public static void main(String[] args) {
            ShardedJedis jedis = RedisShardedPool.getJedis();
            RedisPoolUtil.set("keyTest","value");
            String value = RedisPoolUtil.get("keyTest");
            RedisPoolUtil.setEx("keyex","valueex",60*10);
            RedisPoolUtil.expire("keyTest",60*20);
            RedisPoolUtil.del("keyTest");
            String aaa = RedisPoolUtil.get(null);
            System.out.println(aaa);
            System.out.println("end");
        }
    }
    

    集群和分布式的区别

    小饭店原来只有一个厨师,切菜洗菜备料炒菜全干。后来客人多了,厨房一个厨师忙不过来,又请了个厨师,两个厨师都能炒一样的菜,这两个厨师的关系是集群。
    为了让厨师专心炒菜,把菜做到极致,又请了个配菜师负责切菜,备菜,备料,厨师和配菜师的关系是分布式,一个配菜师也忙不过来了,
    又请了个配菜师,两个配菜师关系是集群

    相关文章

      网友评论

          本文标题:Redis

          本文链接:https://www.haomeiwen.com/subject/zjeapctx.html