Redis集群 Java客户端Jedis的使用

时间:2022-12-17 17:28:07

Java客户端Jedis 

这里只讲Jedis常规用法和五种数据结构的方法(关于集群的搭建以后再写)

Redis集群 Java客户端Jedis的使用

        2.稍微修饰下

Redis集群 Java客户端Jedis的使用

   3.运行效果

Redis集群 Java客户端Jedis的使用

4.相应的jar包(第一个不兼容,没用,junit4.4:@test 做测试所需)

Redis集群 Java客户端Jedis的使用


二,redis数据类型(String List Set Sorted Hash  )方法介绍(方法参数类型如果每注明都是String)

1.  Jedis jedis = new Jedis("192.168.0.163", 6379);  //写自己的地址

2.JedisCluster jedis  = new JedisCluster(jedisClusterNodes);//jedisClusterNodes是多个IP组成

        redis的String类型数据结构的缓存操作:

        

        /**

         * 字符串缓存操作类或者JavaBean缓存操作类

         * key String, value String-->看下边的注意点2

         * key byte[], value byte[]-->key.getBytes[], value 序列化为byte[],通常需要自己写一个序列化工具

         * 注意:这一点与memcached不一样,memcached可以key String, value Object

         * 1、memcached直接加序列化器就可以,或者在业务层中将Object-->String

         * 2、redis执行此接口,一般只会采用后者Object-->String

         */

        

   String:

        1. jedis.set(key,value);//set(String,String),value除了string以外,还可以是byte[]

        /**

            * 设置缓存

             * 类似于memcached的set,不管是否已经有相同的key,都成功

             * 实际上只是set(String, String)

             */

        2.jedis.setex(key, value, expire);

            /**

             * 设置缓存,并指定缓存过期时间,单位是秒

             */

        3.jedis.setnx(key, value);

        

            /**

             * 设置缓存,如果设置的key不存在,直接设置,如果key已经存在了,则什么操作都不做,直接返回

             * 类似于memcached的add

             */

          long setCount = jedis.setnx(keyPrefix+KEY_SPLIT+key, value);

         4.    jedis.get(key);      

        /**

             * 根据key获取缓存

             * @param key

             * @return String

             */

        5.  jedis.del(key);

        /**

             * 根据key删除缓存

             */

        6.  jedis.expire(key, expire);

            /**

             * 更新缓存过期时间,单位:秒

             * 从运行该方法开始,为相应的key-value设置缓存过期时间expire

             * 类似于memcached中的touch命令

             */



   redis的List类型数据结构的缓存操作:

        List(有序列表工具类)

        

        1. jedis.lpush(list, values);//可以多值(String list, String... values)

        

        /**

             * 从左边(首部)加入列表

             * 注意:

             * 1、可以一次性入队n个元素(这里使用了不定参数,当然可以换做数组)

             * 2、左边入队,相当于在队头插入元素,则之后的元素都要后移一位;而右边入队的话元素直接插在队尾,之前的元素的索引不变

             */

        2.

         jedis.lpush(list, values);

        jedis.expire(list, expire);//为该list设置缓存过期时间

         /**

             * 从左边(首部)加入列表

             * 并指定列表缓存过期时间

             */

        3.  jedis.rpush(list, values);

        /**

             * 从右边(尾部)加入列表

             */

        4.

         jedis.rpush(list, values);

        jedis.expire(list, expire);//设置缓存过期时间

            /**

             * 从右边(尾部)加入列表

             * 并设置缓存过期时间

             */

        5. jedis.lset(list, index, value);

        

         /**

             * 设置list中index位置的元素

             * index==-1表示最后一个元素

             */

        6.jedis.lpop(list);

        

         /**

             * 从左边(首部)出列表

             */

        7.jedis.rpop(list);

        

        /**

             * 从右边出列表

             */

        8.jedis.lindex(list, index);

        

        /**

             * 返回list中index位置的元素

             */

        9.jedis.lrange(list, start, end);

        

          /**

             * 返回list指定区间[start,end]内的元素 

             */

        10. lrange(list, 0, -1);

        

        /**

             * 返回list内的全部元素 

             */

        11. jedis.ltrim(list, start, end);

        

        /**

             * 让list只保留指定区间[start,end]内的元素,不在指定区间内的元素都将被删除 

             */

        12. jedis.lrem(list, count, value);//返回删除了多少个元素

        

          /**

             * 删除list中所有与value相等的元素

             * 注意:

             * count

             * ==0 :删除表中所有与value相等的元素

             * >0:从表头开始向表尾搜索,移除count个与value相等的元素

             * <0:从表尾开始向表头搜索,移除count个与value相等的元素

             */

        13.lremove(list, 0, value);

        

          /**

             * 删除list中所有与value相等的元素

             */

        14.jedis.llen(list);

        

         /**

             * 返回list*有多少个元素

             */


    set无序集合工具类

         注意:

  • 元素在set中的存放顺序为:与插入set的先后书顺序无关(即无序)

  • 不允许存放重复元素

  • 对于set而言,Jedis有交集、差集、并集运算,可是ShardJedis没有

        1.jedis.sadd(set, values);

         /*

                     * 对比:

                     * lpush(String key, String... strings);

                     * 返回push之后的list中包含的元素个数

                     * 

                     * sadd(String key, String... members)

                     * 1:添加元素成功

                     * 0:set中已经有要添加的元素了

                     */

        2.jedis.smembers(set)

         /**

             * 获取set集合中的所有缓存

             * @param set

             */

        3. jedis.srem(set, values)

         /**

             * 删除缓存

             * @param set

             * @param values

             */

        4.jedis.sismember(set, value);

        

         /**

             * set集合是否包含value

             * @param set

             */

        5.jedis.scard(set);

        /**

             * 返回set集合的元素个数

             * @param set

             */

        

 Sorted Set(有序集合工具类)

        /**

         * sorted set缓存操作类 

         * 1、有序集合,最后的顺序是按照score从小到大的顺序排列

         * 2、元素不能重复

         * 3、没有从set中获取指定value的运算

         */

        1.jedis.zadd(String sortedSet,double score, String value);

        /**

             * 添加缓存(一个)

             * @param sortedSet 添加入的集合

             * @param score        权重

             * @param value        值

             */

        2.jedis.zadd(String sortedSet,Map<String, Double> value2score);

          /**

             * 添加缓存(一次可添加多个)

             * @param sortedSet        添加入的集合

             * @param value2score    加入集合的元素集

             */

        /***************************获取缓存*****************************/

        3.jedis.zrange(sortedSet,long start, long end);

            /**

             * 返回sortedSet内[start,end]索引的元素set

             * 1、在sortedSet中,元素是按照score从小到大排列的,

             *         此方法从前向后获取元素(即按元素的score从小到大排列)

             */

        4.zrange(sortedSet, 0, -1);

        /**

             * 返回sortedSet内所有元素,元素按照score从小到大排列

             */

        5.jedis.zrevrange(sortedSet,long start, long end);

        /**

             * 返回sortedSet集合[start, end]中的元素

             * 1、此方法相当于从后向前取元素,即元素从大到小排列

             * 或者相当于将sortedSet从大到小排列,然后从前向后去元素

             */

        6.zrevrange(sortedSet, 0, -1);

        /**

             * 返回sortedSet内所有元素,元素按照score从大到小排列

             */

        7.jedis.zrangeByScore(String sortedSet, double minScore, double maxScore);

          /**

             * 获取sortedSet内[minScore, maxScore]的元素

             */

        8.  jedis.zrem(String sortedSet, String... values);

            /**

             * 删除多个缓存

             * @param sortedSet

             * @param values

             */

        9. jedis.zremrangeByRank(String sortedSet, long start, long end);

           /**

             * 删除指定范围(按照索引,包前包后)的缓存

             */

        10.  jedis.zremrangeByScore(String sortedSet, double minScore, double maxScore);

         /**

             * 删除指定范围(按照分数,包前包后)的缓存

             */

        11.jedis.zcard(String sortedSet);

         /**

             * 获取集合sortedSet的长度

             */

        12.edis.zscore(sortedSet, value);

        /**

             * 获取sortedSet中的value的权重score

             */

        13. jedis.zincrby(String sortedSet,double score, String value);

          /**

             * 为sortedSet中的value的权重加上增量score

             */

 Hash(hash工具类)

    1.jedis.hset(String map, String key, String value);


     /**

     * 添加单个缓存key-value到map中

     */

    2.jedis.hsetnx(String map, String key, String value);

     /**

     * 添加单个缓存key-value到map中

     * 若已经存在于指定key相同的key,那么就不操作

     */

    3. jedis.hmset(String map, Map<String, String> key2value);   

    /**

     * 在map中添加key2value的map,即一次性添加多条缓存

     * @param map

     * @param key2value

     */

    4.jedis.hkeys(String map);//返回类型Set<String>

      /**

     * 获取map中key的集合

     * @param set

     */

    5.jedis.hvals(String map)//返回类型List<String>

     /**

     * 获取map中的所有key的value

     */

    6.jedis.hmget(String map, String... keys) //返回类型List<String>

     /**

     * 从map中获取多个key的value,并放在List集合中

     */

    7.jedis.hgetAll(String map);//返回类型Map<String, String>

    /**

     * 从map中获取全部的缓存key-value对

     */

    8.jedis.hget(String map, String key);// 返回类型String

   /**

     * 从map中获取相应key的缓存value

     */

    9.   jedis.hdel(String map, String... keys); 

    /**

     * 从map中删除多个缓存

     */

    10. jedis.hlen(map);

    /**

     * 获取map中的key-value数

     */

    11.jedis.hexists(String map, String key);

    /**

     * map中是否存在键为key的缓存

     */

  


总结:

  • list

    • 元素在list中的存放顺序为:插入list的顺序(从左边插入在头部,从右边插入在尾部)

    • 允许存放重复元素

    • 可用作模拟队列(queue)、堆栈(stack),支持双向操作(L--首部或者R--尾部)

    • 左边入队,相当于在队头插入元素,则之后的元素都要后移一位;而右边入队的话元素直接插在队尾,之前的元素的索引不变(推荐使用右边入队,即队尾入队)

  • set

    • 元素在set中的存放顺序为:与插入set的先后书顺序无关(即无序)

    • 不允许存放重复元素

    • 对于set而言,Jedis有交集、差集、并集运算,可是ShardJedis没有

  • soretd set

    • 元素在set中的存放顺序为:根据score(权重)从小到大排列

    • 不允许存放重复元素

相同点:

  • index

    • 从0开始 -1表示结尾  -2表示倒数第二个

  • API中的 start end参数

    • 都是包前也包后的

  • 按key查找功能

    • list、set、sorted set没有按key查找的功能

    • String、hash具有按key查找value的功能

  • 直接的指定缓存过期的API

    • String有

    • list、set、sorted set、hash没有,但是可以按例如如下的方式指定缓存过期时间  

        jedis.lpush(list, values);19     
         jedis.expire(list, expire);//为该list设置缓存过期时间


    删除整个元素

  • jedis.del(list):可用于五种结构

代码:
package test;

import java.util.HashSet;
import java.util.Set;

import org.junit.Test;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;

public class RedisCesi {


@Test
public void testJedisSingle() {
System.err.println("start1");
//创建jedis对象
Jedis jedis = new Jedis("192.168.0.163", 6379);
//调用jedis对象的方法,方法名称和redis 的命令一致
//jedis.set("key1", "jedis songtie02");
// jedis.set("key07", "jedis songtie02");
// jedis.del("key07");
// String string = jedis.get("key07");
// Long list= jedis.lpush("list", "value1","value2","value4");


System.err.println( jedis.lindex("list", 0)+" "+ jedis.lindex("list", 1)+" "+jedis.lindex("list", 2)+" "+jedis.lindex("list", 3));
//System.err.println(jedis.rpop("list"));
//System.out.println("single "+string);
//关闭jedis
jedis.close();
}


/**
*使用jedis连接池
*/
@Test
public void testJedisPool(){
@SuppressWarnings("resource")
JedisPool jedisPool = new JedisPool("192.168.0.163", 6379);
//获得jedis 连接对象
Jedis jedis = jedisPool.getResource();
System.out.println("链接池 "+ jedis.lindex("list", 0)+" "+ jedis.lindex("list", 1)+" "+jedis.lindex("list", 2)+" "+jedis.lindex("list", 3));
jedis.close();
}
/**
* 集群连接测试
*/
@Test
public void testJedisCluster(){
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.0.163", 6379));
nodes.add(new HostAndPort("192.168.0.164", 6379));
nodes.add(new HostAndPort("192.168.0.165", 6379));
nodes.add(new HostAndPort("192.168.0.163", 6380));
nodes.add(new HostAndPort("192.168.0.164", 6380));
nodes.add(new HostAndPort("192.168.0.165", 6380));


@SuppressWarnings("resource")
JedisCluster cluster = new JedisCluster(nodes );
cluster.set("key01", "1000");

System.out.println("集群 "+cluster.get("key01"));

System.out.println("key2 "+cluster.get("key02"));
System.out.println("key7 "+cluster.get("key07"));

}


}

单纯的集群代码:
package test;  

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
public class why123 {

private String serverInfo = "192.168.0.163:6379,192.168.0.163:6380,192.168.0.164:6379,192.168.0.164:6380,192.168.0.165:6379,192.168.0.165:6380";

private Set<HostAndPort> getClusterInfo(String serverInfo) {
Set<HostAndPort> set = new HashSet<HostAndPort>();
if(serverInfo==null||"".equals(serverInfo.length())) {
throw new RuntimeException("serverInfo 不能为空");
}
String ipPort[] = serverInfo.split(",");
int len = ipPort.length;
for(int i=0;i<len;i++) {
String server[] = ipPort[i].split(":");
System.out.println(server[0]+"-----------------"+server[1]);
set.add(new HostAndPort(server[0], Integer.parseInt(server[1])));
}
return set;
}

@SuppressWarnings("resource")
@Test
public void test() {

Set<HostAndPort> jedisClusterNodes = getClusterInfo(serverInfo);
// Jedis 集群尝试自动发现节点
JedisCluster jc = new JedisCluster(jedisClusterNodes);
System.err.println("----------------------------测试hash------------------------------");
System.err.println("---------插入--------");
//插入一条
jc.hset("aamap", "aa1", "aa11");
Map<String,String> maps = new HashMap<String, String>();
maps.put("aa2", "aa22");
maps.put("aa3", "aa33");
//插入多条
jc.hmset("aamap", maps);
//获取所有的key
System.out.println(jc.hkeys("aamap"));//[aa3, aa2, aa1]
//获取所有的value
System.out.println(jc.hvals("aamap"));//[aa33, aa22, aa11]
//从map中获取全部的缓存key-value对
System.out.println(jc.hgetAll("aamap"));//{aa3=aa33, aa2=aa22, aa1=aa11}
//从map中获取相应key的缓存value
System.out.println(jc.hget("aamap","aa2"));//aa22
//从map中获取多个key的value,并放在List集合中
System.out.println(jc.hmget("aamap","aa2","aa1"));//[aa22, aa11]
//获取map中的key-value数
System.out.println(jc.hlen("aamap"));//3
//map中是否存在键为key的缓存
System.out.println(jc.hexists("aamap","aa3"));//true
System.out.println(jc.hexists("aamap","aa0"));//false

// jc.hdel("aamap","aa0");
// jc.hdel("aamap","aa1");
// System.out.println(jc.hgetAll("aamap"));//{aa3=aa33, aa2=aa22}


}

}

redis整理来源开源中国:

二,Redis整理

1.redis是什么?

redis(remote dictionary server):是一个以key-value形式存储于内存中的数据库.提供了 String / List / Set / Sort Set /Hash 五种数据结构。服务器在断电之后,仍然可以恢复到断电之前的状态(另外的解释:集群是一个提供在多个Redis间节点间共享数据的程序集.

2.redis特点?

线程模型:单线程-多路复用io模型

性能高:支持读 11万/秒  ,  写 8万/秒

存储: 内存 ;  RDB文件(二进制安全的真实数据) ;  AOF文件(客户端的命令集合)

事务: 支持事务(每个客户端串行执行命令,其他客户端处于阻塞状态)

3.redis数据类型

String:动态字符串(每个key都是一个String)

编码方式:int / raw() /embstr

应用场景:普通的string场景

List:列表结构,有序可重复的结构。它拥有队列的特性。 

编码方式:ziplist / linkedlist (如果数据量较小,且是数字或者字符串,则内部结构为 ziplist)

应用场景:普通的集合数据

Set:集合结构,不重复的集合结构。

编码方式:intset(整数集合) / hashtable

应用场景:普通的非重复集合数据;支持取交集、取并集等操作

Sort Set:有序集合结构,和Set比较起来,它是有序的。

编码方式:ziplist / skiplist

应用场景:有序不重复的集合数据

Hash:哈希结构,存储多个key:value的结构,此种结构可以存储对象 ;  如  HMSET  user(key)  username value1 password value2

编码方式:ziplist / hashtable

应用场景: 从关系型数据库去出一条数据,就可以让入到此种结构中

4.内存优化

redis提供内存回收策略,根据使用的情况可以选择适当的回收策略

redis提供内存共享策略,服务器启动时,会自动创建0-9999的数字对象,其他地方使用,可以直接引用。

本质:对内存的操作,其实是在每一个redis对象结构内都有一个count的属性,该属性记录了这个对象被引用的次数,如果为0,那么在内存回收时将回收该空间。

save参数调整:当满足条件时,触发SAVE命令,持久化到RDB文件

appendonly参数: 默认no ,若yes,则开启AOF文件持久化; BGREWRITEAOF  命令 持久化。其中appendsync参数调整具体的持久化策略,默认为每秒

5.事务

单线程处理所有客户端发来的请求,所以当有一个客户端在执行,其他客户端只能处于阻塞态。只有当前客户端请求完毕,其他客户端才能请求


6.主从复制

功能:数据备份,读写分离(测试环境,主服务器写,从服务器读)

步骤:在从服务端器执行: slaveof <masterip> <masterport> 即可维持关系;配置文件中也可以

特点:

1.master可以有多个slave

2.除了多个slave连到相同的master外,slave也可以连接其他slave形成图状结构

3.主从复制不会阻塞master。也就是说当一个或多个slave与master进行初次同步数据时,master可以继续处理client发来的请求。相反slave在初次同步数据时则会阻塞不能处理client的请求。

4.主从复制可以用来提高系统的可伸缩性,我们可以用多个slave 专门用于client的读请求,比如sort操作可以使用slave来处理。也可以用来做简单的数据冗余

5.可以在master禁用数据持久化,只需要注释掉master 配置文件中的所有save配置,然后只在slave上配置数据持久化。

  6.主服务器可以关闭持久化功能(注释掉save参数)

 

7.sentinel(监测系统)

本质:是一个运行在特殊模式下的redis服务器。

功能:监控运行在多机上的主redis服务器,若有某一台主服务器出现故障,将自动把其他正常的从服务器切换为主服务器,代替出现故障主服务器的工作。

特点:

1.不发挥数据库的功能(所有对key以及数据类型操作的命令不能使用)

2.将会给监控的主服务器以及主服务器所属的从服务器发送命令,确认是否下线

3.会和监控同一个主服务器的其他sentinel服务器通信,作用是在共同判断所监控的主服务器的状态

4.根据多个sentinel判断的主服务器状态,来决定是否要进行主从切换,故障转移等

转移:sentinel监控的主服务器配置参数要在 sentinel.conf 文件中配置,启动时加载

8.集群

功能:将众多的key-value集合存在多个节点上,当某一个节点出现障碍,不影响整个集群的功能。

涉及到的关键词:

节点:一个端口的redis服务便是一个节点

槽指派(集群将整个系统分为16384个hash槽):这16384个槽位要全部分布在集群中的主节点上。

重新分片:若某个主节点故障了,将该主节点的槽位分配到其他可以用的主节点上。

上线/下线状态: 是否全部的槽位都分布在节点上。

特点:

1.如果某个节点要集群,必须要设置cluster-enabled yes

2.每个节点都有这16384个槽位所属的节点信息,如果值没有正确进入槽位,那么该节点会提示系统将信息放入正确槽位。重定向的过程会出现一个面向客户端隐藏的MOVED错误

3.集群在线状态也可以进行重新分片

4.集群中的主节点用户处理客户端命令,从节点用于复制主节点的数据,主节点下线时,从节点代替主节点的工作

//注意:目前官方提供的集群功能仍处于内测版本。

9.redis基准

redis自带的redis-benchmark 工具,支持各种参数进行性能测试

特点:

1.可以模拟多个客户端处理任意个请求

2.可以测试仅仅少数使用的命令等

注意:测试发现,linux环境下部署的redis服务器性能远高于windows下部署的redis服务器性能, 不在一个层级上面

10.关系数据库模型的转换

关系型数据库表结构:user表 (uid username password birthday )

在redis中可以这样存在:

1.主键: SET user:uid 1  、  GET user:1

2.其他字段:SET user:uid:username  GET user:5:username ( 5 是通过参数值传进来的)

3.表数据也可以存在hash结构中:      HMSET user:uid username value1 password value2 birthday value3

11.管道

功能:客户端一次可以传送多个命令到服务器,减少往返时延。大大提高性能。

12.优化

redis提供一些简单的内存优化策略,如过期数据清除,内存数据共享。