设为首页 收藏本站
查看: 1397|回复: 0

[经验分享] 使用Spring Data Redis操作Redis(一)

[复制链接]

尚未签到

发表于 2018-11-6 11:54:11 | 显示全部楼层 |阅读模式
  Spring-Data-Redis项目(简称SDR)对Redis的Key-Value数据存储操作提供了更高层次的抽象,类似于Spring Framework对JDBC支持一样。
  项目主页:http://projects.spring.io/spring-data-redis/
  项目文档:http://docs.spring.io/spring-data/redis/docs/1.5.0.RELEASE/reference/html/
  本文主要介绍Spring Data Redis的实际使用。
  1.Spring Data Redis 1.5新特性
  增加了Redis HyperLogLog命令PFADD,PFCOUNT,PFMERGE
  可以使用Jackson基于RedisSerializer对Java类型序列化
  使用PropertySource配置Redis Sentinel连接,目前仅Jedis客户端支持
  2.Spring Data Redis ?
  Spring Data Redis使得在Spring应用中读写Redis数据库更加容易。
  Spring Data Redis提供了四种Redis服务的Java客户端包的集成,分别是Jedis, JRedis, SRP and Lettuce
  3.版本要求
  Spring Data Redis1.2.x要求JDK1.6+,Spring Framwork3.2.8+
  Key-Value存储服务Redis 2.6.x+
  4.搭建环境
  本文假设已经安装完成了Redis服务,并成功运行。
  创建maven项目,添加依赖的Jar,本文主要使用jedis
  org.springframework.data
  spring-data-redis
  1.5.0.RELEASE
  
  redis.clients
  jedis
  2.6.2
  
  5.连接Redis服务
  在Spring Data Redis中通过org.springframework.data.redis.connection包中的RedisConnection和RedisConnectionFactory类来获取Redis连接。
  5.1配置JedisConnectionFactory
  

  

  
  
  

  

  5.2配置Jredis,SRP,Lettuce的配置和上面配置类似,只需要配置对应的RedisConnectionFactory接口实现接口,它门位于如下包中:
DSC0000.jpg

  5.3关于RedisConnectionFactory注意问题
  上面四种连接器并不是都支持Redis的所有特性,它们之间有差异性,如果调用方法在Connection API中不支持则抛出“UnsupportedOperationException”异常,具体情况需要了解对应的Redis Java客户端Jar的实现。
  5.4关于Redis Sentinel(这里暂称为:哨兵)支持
  Redis Sentinel监听主服务,再主服务发生故障时能够切换至从服务,将从服务升为主服务来保证故障恢复,使用该功能需要在JedisConnectionFactory设置RedisSentinelConfiguration属性,目前Jedis对Redis Sentinel提供支持。
  编码方式如下:
public RedisConnectionFactory jedisConnectionFactory() {  
  RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration() .master("mymaster")
  
  .sentinel("127.0.0.1", 26379) .sentinel("127.0.0.1", 26380);
  
  return new JedisConnectionFactory(sentinelConfig);
  
}
  在Spring容器中配置:

  
  
  
  192.168.88.153:26379
  192.168.88.153:26380
  192.168.88.153:26382
  
  
  
  
  
  
  注意:在配置Redis的sentinel.conf文件时注意使用外部可以访问的ip地址,因为当redis-sentinel服务和redis-server在同一台机器的时候,主服务发生变化时配置文件中将主服务ip变为127.0.0.1,这样外部就无法访问了。如果应用程序,Redis服务在同一台机器则不存在这样的隐患,具体情况则更加实际的网络环境。
  配置好之后,在实例化JedisConnectionFactory之后,可见如下日志:
2015-4-1 17:29:30 redis.clients.jedis.JedisSentinelPool initSentinels  
信息: Trying to find master from available Sentinels...
  
2015-4-1 17:29:30 redis.clients.jedis.JedisSentinelPool initSentinels
  
信息: Redis master running at 192.168.88.153:6384, starting Sentinel listeners...
  
2015-4-1 17:29:30 redis.clients.jedis.JedisSentinelPool initPool
  
信息: Created JedisPool to master at 192.168.88.153:6384
  实验环境中192.168.88.153:6384的Redis实例是主服务。
  5.5下面通过一组代码展示具体使用
@FixMethodOrder(MethodSorters.NAME_ASCENDING)  
public class TestJedis {
  

  public static ApplicationContext ctx;
  

  public static JedisConnectionFactory jedisConnetionFactory;
  

  public JedisConnection jedisConnection;
  

  @SuppressWarnings("unchecked")
  @BeforeClass
  public static void setBeforeClass() {
  ctx = new ClassPathXmlApplicationContext("spring-redis.xml");
  jedisConnetionFactory = (JedisConnectionFactory) ctx
  .getBean("jedisConnectionFactory");
  }
  

  @Before
  public void setBefore() {
  jedisConnection = jedisConnetionFactory.getConnection();
  }
  

  @After
  public void setAfter() {
  jedisConnection.close();
  }
  

  private void print(Collection c) {
  for (Iterator iter = c.iterator(); iter.hasNext();) {
  RedisServer rs = (RedisServer) iter.next();
  System.out.println(rs.getHost() + ":" + rs.getPort());
  }
  }
  

  // 简单测试JedisConnection
  @Ignore
  @Test
  public void test1() {
  if (!jedisConnection.exists(new String("zz").getBytes())) {
  jedisConnection.set(new String("zz").getBytes(),
  new String("zz").getBytes());
  }
  }
  

  @Ignore
  @Test
  public void test2() {
  Set keys = jedisConnection.keys(new String("*").getBytes());
  for (Iterator iter = keys.iterator(); iter.hasNext();) {
  System.out.println(new String(iter.next()));
  }
  }
  

  // 测试Sentinel
  @Ignore
  @Test
  public void test3() throws InterruptedException {
  if (jedisConnetionFactory.getSentinelConnection().isOpen()) {
  Collection c = jedisConnetionFactory
  .getSentinelConnection().masters();
  print(c);
  RedisNode rn = new RedisNode("192.168.88.153", 6380);
  rn.setName("mymaster");
  c = jedisConnetionFactory.getSentinelConnection().slaves(rn);
  print(c);
  }
  

  for (int i = 0; i < 1000; i++) {
  jedisConnection.set(new String("k" + i).getBytes(), new String("v"
  + i).getBytes());
  Thread.sleep(1000);
  }
  Set keys = jedisConnection.keys(new String("k*").getBytes());
  Assert.assertEquals(1000, keys.size());
  }
  
}
  6.RedisTemplate支持
  熟悉Spring的JdbcTemplate对象的话,应该大概能猜出来RedisTemplate的作用了,RedisTemplate对象对RedisConnection进行了封装,它提供了连接管理,序列化等功能,它对Redis的交互进行了更高层次的抽象。另外还提供了Redis操作命令的操作视图,这极大的方便和简化了Redis的操作。
  下表是具体的操作视图接口类介绍:
Key类型操作ValueOperationsRedis String/Value 操作ListOperationsRedis List 操作SetOperationsRedis Set 操作ZSetOperationsRedis Sort Set 操作HashOperationsRedis Hash 操作Value约束操作BoundValueOperationsRedis String/Value key 约束BoundListOperationsRedis List key 约束BoundSetOperationsRedis Set key 约束BoundZSetOperationsRedis Sort Set key 约束BoundHashOperationsRedis Hash key 约束  在org.springframework.data.redis.core包中对表中的接口都提供了相应的默认实现。
  6.1RedisSerializer
  Spring Data Redis提供了对Key-Value的序列号,在使用RedisTemplate对象是默认使用JdkSerializationRedisSerializer实现。还提供了其它的序列化实现如:Jackson2JsonRedisSerializer,JacksonJsonRedisSerializer,GenericToStringSerializer,StringRedisSerializer,OxmSerializer。
  另外用户可以提供自己的序列化实现
  6.2配置RedisTemplate

  
  
  
  这里配置了RedisTemplate和StringRedisTemplate,不同之处在于StringRedisTemplate的Key-Value序列化使用的是StringRedisSerializer。使用StringRedisTemplate操作Redis之后的结果是读友好的。
  另外对Hash类型而言,还有对应的HashKey序列化(其对应于Hash类型的字段名)。
  6.3RedisTemplate的使用
// 测试RedisTemplate,自主处理key的可读性(String序列号)  @Ignore
  @Test
  public void test4() {
  String key = "spring";
  ListOperations lop = redisTemplate.opsForList();
  RedisSerializer serializer = new StringRedisSerializer();
  redisTemplate.setKeySerializer(serializer);
  redisTemplate.setValueSerializer(serializer);
  // rt.setDefaultSerializer(serializer);
  

  lop.leftPush(key, "aaa");
  lop.leftPush(key, "bbb");
  long size = lop.size(key); // rt.boundListOps(key).size();
  Assert.assertEquals(2, size);
  }
  

  // 测试便捷对象StringRedisTemplate
  @Ignore
  @Test
  public void test5() {
  ValueOperations vop = stringRedisTemplate.opsForValue();
  String key = "string_redis_template";
  String v = "use StringRedisTemplate set k v";
  vop.set(key, v);
  String value = vop.get(key);
  Assert.assertEquals(v, value);
  }
  具体使用那种序列化策略则更加存储的Key-Value内容做权衡即可。
  通过RedisTemplate中的方法的参数RedisCallback回调接口来获取RedisConnection,进一步操作Redis,比如事务控制。需要注意的是如果使用StringRedisTemplate则返回的是StringRedisConnection对象。
  测试RedisCallback代码示例:
// 测试Callback  @Ignore
  @Test
  public void test61() {
  Long dbsize = (Long) stringRedisTemplate
  .execute(new RedisCallback() {
  @Override
  public Long doInRedis(RedisConnection connection)
  throws DataAccessException {
  StringRedisConnection stringRedisConnection=(StringRedisConnection)connection;
  return stringRedisConnection.dbSize();
  }
  });
  System.out.println("dbsize:" + dbsize);
  }
  测试SessionCallback代码示例:
@Test  public void test62() {
  List txresult = stringRedisTemplate
  .execute(new SessionCallback() {
  

  @Override
  public List execute(RedisOperations operations)
  throws DataAccessException {
  operations.multi();
  operations.opsForHash().put("hkey", "multikey4",
  "multivalue4");
  operations.opsForHash().get("hkey", "k1");
  

  return operations.exec();
  }
  

  });
  for (Object o : txresult) {
  System.out.println(o);
  /**
  * 0. false/true
  * 1. v1
  */
  }
  }
  说明:

  •   在事务中的操作返回都是null,因此不能在execute中对操作的结果进行处理。比如这里get("hkey","k1")的结果。
  •   Hash操作中如果字段存在则返回false(redis中是0),不存在返回true(redis中是1)与字段对应的值是否更新无关联。
  •   exec()方法返回List中的对象对应事务中执行的每条命令的返回结果。
  7.执行Lua脚本
  Redis中执行Lua脚本开发思路:http://aiilive.blog.51cto.com/1925756/1626372
  Spring Data Redis中执行Lua脚本更加便利,下面示例展示使用RedisTemplate对象执行Lua脚本。
// 测试Lua脚本  @Ignore
  @Test
  public void test71() {
  List keys = new ArrayList();
  RedisScript script = new DefaultRedisScript(
  "local size = redis.call('dbsize'); return size;", Long.class);
  Long dbsize = stringRedisTemplate
  .execute(script, keys, new Object[] {});
  System.out.println("sha1:" + script.getSha1());
  System.out.println("Lua:" + script.getScriptAsString());
  System.out.println("dbsize:" + dbsize);
  }
  

  @Test
  public void test72() {
  DefaultRedisScript script = new DefaultRedisScript();
  /**
  * isexistskey.lua内容如下:
  *
  * return tonumber(redis.call("exists",KEYS[1])) == 1;
  */
  script.setScriptSource(new ResourceScriptSource(new ClassPathResource(
  "/isexistskey.lua")));
  

  script.setResultType(Boolean.class);// Must Set
  

  System.out.println("script:" + script.getScriptAsString());
  Boolean isExist = stringRedisTemplate.execute(script,
  Collections.singletonList("k2"), new Object[] {});
  Assert.assertTrue(isExist);
  }
  8.支持类操作
  在org.springframework.data.redis.support包中提供了各种可重用组件,这些组件可以应用到Redis存储,如atomic计数,JDK集合,Redis的类型集合(RedisList,RedisSet等)

@Ignore  @Test
  public void test8() {
  RedisAtomicInteger rai = new RedisAtomicInteger("redis:atomic",
  jedisConnetionFactory);
  System.out.println(rai.get());
  }
  

  // 测试Redis Collection
  @Ignore
  @Test
  public void test9() {
  @SuppressWarnings("unchecked")
  RedisList redisList = (RedisList) ctx
  .getBean("springList");
  redisList.clear();
  redisList.addFirst("china");
  redisList.add("in");
  redisList.add("go");
  redisList.addLast("made");
  System.out.println(redisList.getKey());
  }



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-631522-1-1.html 上篇帖子: redis 服务器相关命令 下篇帖子: 使用Spring Data Redis操作Redis(二)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表