Spring Boot 集成Spring Data

夙愿已清 提交于 2020-12-16 23:31:39

 

参考文档:Reference 

30.Working with NoSQL Technologies (使用NoSQL技术)

Spring Data 提供额外的模块帮助你接入各种各样的NoSQL技术,有MongoDB,Neo4J,ElasticSearch,Solr,Redis,Gemfire,Cassandra,Couchbase 还有 LDAP。Spring Boot 为上面的中间件提供自动配置文件。你可以使用它们,但是必须自己配置。请参考Spring-Data相关文档 Spring Boot Data Reference

30.1 Redis

( Reference_2.0.3.RELEASE )
Redis 集群安装 参考:https://www.cnblogs.com/yuanermen/p/5717885.html 
Error 4 Ruby required >= 2.2.2  https://blog.csdn.net/lixwjava/article/details/50408070

1.New Features

这一节简要的介绍了各个在新版本特性和要注意的方面。(1.5>1.6>1.7>1.8>2.0新特性)

Spring Data Redis 1.8中的新功能 < 5/6/7 略>

  • Jedis更新到2.9  Lettuce更新到4.2(JDK 版本最低 1.8)
  • 支持Redis GEO 命令
  • 支持地理空间索引
  • 基于MappingRedisConverter的HashMapper实现
  • SSL支持连接Redis cluster
  • 使用Jedis时,支持客户端名称使用ConnectionFactory

3、Reuqirements (要求)

    2.x版本要求JDK8 及以上

    Spring 要求 4.3.18.RELEASE及以上

    Redis 要求 2.6及以上版本

Reference Documentation

Document structure(文件结构)

这部分文档介绍了Spring Data Redis提供的核心功能。

Redis support 介绍了Redis的模块特性。

5.Redis Support 

    Redis是Spring Data支持的一个键值对存储模块。引用项目主页上的一段话:

Redis is an advanced key-value store. It is similar to memcached but the dataset is not volatile, and values can be strings, exactly like in memcached, but also lists, sets, and ordered sets. All this data types can be manipulated with atomic operations to push/pop elements, add/remove elements, perform server side union, intersection, difference between sets, and so forth. Redis supports different kind of sorting abilities.

    redis是一个高级键值对数据库。它跟memcacheed相似,但数据是持久化的,跟memcached相同的基本数据类型String,同时还支持list,set,有序set。所有这些数据类型都可以通过原子操作来操作以推送/弹出元素,添加/删除元素,执行服务器端并集,交集,集合之间的差异等等。 Redis支持不同类型的排序功能。

 

7.Redis Cluster

7.1 Enabling Redis Cluster

启用Redis集群

       集群支持基于与非集群通信完全相同的模块构建。RedisClusterConnection是RedisConnection的扩展,它处理与Redis群集的通信,并将错误转换为Spring DAO异常层次结构。通过RedisConnectionFactory创建RedisClusterConnection,使用RedisClusterConfiguration进行设置。

Example ↓↓↓↓
/**
 * Description :Redis cluster properties
 * @author: manji
 * 2018/7/23 14:09
 */
@Component
@ConfigurationProperties(prefix = "spring.redis.cluster")
@Data
public class RedisClusterProperties {

    /**
     * @Configuration__Properties
     *      spring.redis.cluster.nodes: Comma delimited list of host:port pairs. 逗号分隔的host:port对
     *          spring.redis.cluster.nodes[0] = 127.0.0.1:7379
     *          spring.redis.cluster.nodes[1] = 127.0.0.1:7380
     *      spring.redis.cluster.max-redirects: Number of allowed cluster redirections. 允许集群重定向的数量
     */
    List<String> nodes;
}
/**
 * Description :Redis 集群客户端
 * @author: manji
 * 2018/7/23 14:10
 */
@Configuration
public class RedisConfig {

    @Autowired
    RedisClusterProperties redisClusterProperties;
    /**
     * 默认值 null
     */
    @Value("${redis.password:}")
    private @Nullable String password;

    /**
     * RedisClusterConfiguration can also be defined via PropertySource.
     * @return
     */
    @Bean
    public  RedisConnectionFactory connectionFactory(){
        RedisClusterConfiguration clusterConf = new RedisClusterConfiguration(redisClusterProperties.getNodes());
        clusterConf.setPassword(RedisPassword.of(password));
        return  new JedisConnectionFactory(clusterConf);
    }
}

application.yml

server:
  port: 8088

spring:
  redis:
    cluster:
     nodes[0] : 192.168.220.140:7001
     nodes[1] : 192.168.220.140:7002
     nodes[2] : 192.168.220.140:7003
     nodes[3] : 192.168.220.141:7004
     nodes[4] : 192.168.220.141:7005
     nodes[5] : 192.168.220.141:7006

redis:
 password: 写你自己的密码

测试类:    

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath*:spring/spring.xml")
public class RedisConfigTest {
    @Autowired
    RedisConnectionFactory connectionFactory;
    @Test
    public void test(){
        final RedisClusterConnection clusterConnection = connectionFactory.getClusterConnection();
        final byte[] bytes = clusterConnection.get("java_test".getBytes());
        System.out.println(new String(bytes));
    }
}
Result Test Pass !!

7.2 Working With Redis Cluster Connection

使用Redis集群连接

       如上所述,redis cluster的行为和单节点redis 甚至是sentinel监控的主从环境是不一样的.因为集群自动将key映射到分布在不同节点的16384个分片上.因此当命令涉及不止一个key的时候,为了避免分片之间出现交叉执行错误,需要所有的key映射到正确的分片上.

此外,一个集群节点仅仅为固定的key提供返回查询结果的服务.

(什么意思呢?说白了就是,你存的时候 集群根据Key 将你分配到集群中的某一个slot上,当然这个slot一定是属于某一个node的,你的key对应的value就存在这个node上,当你再次去获取的时候,其他nodes的节点并不会有你要的key的数据,你最终还是会去你存的那个solt所在的node去取数据。)

举个简单的栗子,当你在集群的某个节点上使用 KEYS * 命令的时候,你最终只能获得这个node上所有的key的值,而拿不到这个集群的其他节点的key的值。所以呢,如果你想获取一个redis cluster 中所有的key的时候,你至少知道这个集群的所有master节点,获取每一个master节点的key.

但是具体key重定向到对应的分片节点是由驱动程序处理的,包括更高级别的功能,跨节点搜集信息,向RedisClusterConnection涵盖的所有节点发送命令。就像前面pick up的keys示例,意思就是,keys(pattern) 这个方法 pick up keys命令在集群每个master节点同时执行keys 命令,同时pick up 结果和返回keys的合计结果。要请求单个节点的话RedisClusterConnection 提供了keys方法的重载 (keys(node , pattern)).

关于参数node (RedisClusterNode) 你可以从RedisClusterConnection.clusterGetNodes获得也可以直接通过构造函数构造.

一、通过RedisClusterConnection.clusterGetNodes 构造获得的是一个集合,不过是无序的,要什么信息可以自己获取,下面图片仅供参考

二、通过构造函数构造
RedisClusterNode redisClusterNode = new RedisClusterNode("host", port); // 这里写你自己的 host 和 port

MGET 命令 >> 当所有key映射到同一个分片时,本机驱动会自动提供服务为这个多分片请求命令.但是如果不是这种情况的话,RedisClusterConnection会执行多个并行的GET命令通过分片服务节点,然后再返回合计的结果。很明显,多分片请求命令比单分片执行性能更差,因此应该谨慎使用。如果有疑问的话(in doubt)请考虑使用一个带大括号的前缀把key固定到某一个分片. 就像{manji}.foo和{manji}.bar都会映射到相同的分片。

简单的概括上面的一段话就是,像mget这种批量命令,当你的 keys 参数是落在一个分片上的时候 会很方便,如果你给的keys 参数在不同的分片上,这样还是先路由到不同的分片上,然后再将查询的结果合并起来返回给你,所以这样会性能比较差,如果你实在要用的话,用它的建议,给key前面加业务相关的前缀。

Bulb 上面提供了简单的示例来演示Spring Data Redis遵循的一般策略,请注意,某些操作可能需要将大量数据加载到内存中才能计算所需的命令.另外,不是所有的多分片请求都能正确的分发到各个单节点,如果误用的话就会报错. 譬如 PFCOUNT

7.3 //TODO Working With RedisTemplate and ClusterOperations 

使用RedisTemplate和集群操作

请参考 Working with Objects through RedisTemplate 这一章了解RedisTemplate 一般用途,配置和用法.

//TODO 使用任何JSON RedisSerializer设置RedisTemplate#keySerializer时请小心,因为更改json结构会立即影响哈希槽计算。

RedisTemplate通过ClusterOperations接口提供对集群特定的访问操作,ClusterOperations接口可以通过RedisTemplate.opsForCluster()获得.

这允许在集群内的单个节点上显式执行命令,同时保留为模板配置的去/序列化功能并提供管理命令,例如CLUSTER MEET或更高级别的操作 resharding.

Example4:通过RedisTemplate访问RedisClusterConnection
// ClusterOperations clusterOps = redisTemplate.opsForCluster();
// clusterOps.shutdown(redisClusterNode);

//TODO 关闭redisClusterNode这个节点,然后cross finger,有一个slave节点来继承master的功能.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!