本文作者:包子也沉默

java架构之路-(Redis专题)SpringBoot连接Redis超简单

包子也沉默 3年前 (2019-10-25) ( 10-25 ) 1736 0条评论
摘要: .92",6379));JedisClusterjedisCluster=null;try{//connectionTimeout:指的是连接一个url的连接等待时间//soTimeout:指的是连接上一个url,获取response的返回等待时间jedisCluster=newJedisCluster(jedisClusterNode,6000,5000,10,"xiaoca

  上次我们搭建了Redis的主从架构,哨兵架构以及我们的集群架构,但是我们一直还未投入到实战中去,这次我们用jedis和springboot两种方式来操作一下我们的redis

个视图渲染的模板。context_object_name:指定获取的模型列表数据保存的变量名,这个变量会被传递给模板。如果还是有点难以理解,不妨将类视图的代码和index视图函数的代码对比一下:blo

主从架构

  如何配置我上次已经讲过了,https://www.cnblogs.com/cxiaocai/p/11711377.html。我们这次主要看如何用java来操作redis,先来复习一下上次的配置,准备三台服务器,安装redis,保证互通,两台改为slave,配置replicaof IP 端口,主从复制是通过rdb文件来复制的。大概就这么多,配置不再多说了,我们直接上代码。

  jedis

型的需求,django提供了一个DetailView类视图。下面我们就来将detail视图函数转换为等价的类视图PostDetailView,代码如下:blog/views.pyfromdjango.

quest,pk):#...这些视图函数都是从数据库中获取文章(Post)列表,唯一的区别就是获取的文章列表可能不同。比如index获取全部文章列表,category获取某个分类下的文章列表。将ind

bject_name="post_list"defget_queryset(self):cate=get_object_or_404(Category,pk=self.kwargs.g

  创建一个Maven项目,引入我们的jedis依赖包

t还有什么更多的操作不知道的,欢迎来我的公众号内问答,我会依依给你解释清楚的。哨兵架构  哨兵架构,是主从的升级版,master节点宕机后,可以主动选取我们的master节点。  我们还是分为jedi

<!-- 加入jedis依赖 --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.9.0</version></dependency>

这里我就不封装连接工具类啦,我们直接看下测试代码吧

t_list})index视图函数首先通过Post.objects.all()从数据库中获取文章(Post)列表数据,并将其保存到post_list变量中。而在类视图中这个过程ListView已经帮我

public static void main(String[] args) {
    JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
    jedisPoolConfig.setMaxTotal(20);
    jedisPoolConfig.setMaxIdle(10);
    jedisPoolConfig.setMinIdle(5);// timeout,这里既是连接超时又是读写超时,从Jedis 2.8开始有区分connectionTimeout和soTimeout的构造函数JedisPool jedisPool = new JedisPool(jedisPoolConfig, "127.0.0.1", 6379, 3000, null);

    Jedis jedis = null;try {//从redis连接池里拿出一个连接执行命令jedis = jedisPool.getResource();
        System.out.println(jedis.set("xiaocai", "666"));
        System.out.println(jedis.get("xiaocai"));
    } catch (Exception e) {
        e.printStackTrace();
    } finally {//注意这里不是关闭连接,在JedisPool模式下,Jedis会被归还给资源池。if (jedis != null)
            jedis.close();
    }
}

主从的连接很简单的,设置连接参数,直接连接就可以操作我们的redis了,主从的连接,就是基本的链接。

-加入redis连接池--><dependency><groupId>org.springframework.boot</groupId><artifa

  springboot

rintln(jedis.get("xiaocai888"));}catch(Exceptione){e.printStackTrace();}finally{//注意这里不是关闭连接,在JedisP

39;returnpostPostDetailView稍微复杂一点,主要是等价的detail视图函数本来就比较复杂,下面来一步步对照detail视图函数中的代码讲解。首先我们为PostDetailVi

库在开发网站的过程中,有一些视图函数虽然处理的对象不同,但是其大致的代码逻辑是一样的。比如一个博客和一个论坛,通常其首页都是展示一系列的文章列表或者帖子列表。对处理首页的视图函数来说,虽然其处理的对象

  我们再来看一下springboot怎么来连接吧,建立一个springboot项目,什么也不用设置,建立一个最简单的就可以的,首先还是加入我们的Maven驱动包

完全等价的,而且类视图具有代码复用等很多好处,所以以后一旦涉及视图,我们都会使用类视图来实现。『讲解开源项目系列』——让对开源项目感兴趣的人不再畏惧、让开源项目的发起者不再孤单。跟着我们的文章,你会发

<!-- 加入redis连接池--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

加入我们的redis的配置信息,放置在application.yml文件下即可。

{if(jedisCluster!=null)jedisCluster.close();}}//length用户要求产生字符串的长度publicstaticStringgetRandomString(

spring:
  redis:
    database: 0 # Redis数据库索引(默认为0)
    host: 127.0.0.1 # Redis服务器地址
    port: 6379 # Redis服务器连接端口
    password: # Redis服务器连接密码(默认为空)
    timeout: 5000 # 连接超时时间(毫秒)
    jedis:
      pool:
        max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
        max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 8 # 连接池中的最大空闲连接
        min-idle: 0 # 连接池中的最小空闲连接

这个也就不存在什么工具类了,内部都已经封装好了,我们直接来上测试类吧

染blog/index.html模板文件,index视图函数中使用render函数。但这个过程ListView已经帮我们做了,我们只需指定渲染哪个模板即可。接下来就是要将类视图转换成函数视图。为什么需

package com.redisclient.master_slave;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.data.redis.core.StringRedisTemplate;

@RestControllerpublic class RedisMasterSlave {

    @Autowiredprivate StringRedisTemplate stringRedisTemplate;

    @GetMapping(value = "/")public String getIndex(){
        stringRedisTemplate.opsForValue().set("xiaocai", "888");
        System.out.println(stringRedisTemplate.opsForValue().get("xiaocai"));return "小菜技术";
    }
}

  相比我们上面的jedis还要简单,直接自动装配一下我们的StringRedisTemplate即可,剩下的就是我们的redis操作了,五种数据的基本操作如下。

se:0#Redis数据库索引(默认为0)host:127.0.0.1#Redis服务器地址port:6379#Redis服务器连接端口password:#Redis服务器连接密码(默认为空)time

redisTemplate.opsForValue();//操作字符串 redisTemplate.opsForHash();//操作hashredisTemplate.opsForList();//操作listredisTemplate.opsForSet();//操作setredisTemplate.opsForZSet();//操作有序set

还有什么更多的操作不知道的,欢迎来我的公众号内问答,我会依依给你解释清楚的。

使用类视图是django推荐的做法,熟悉了类视图的使用方法后,能够减少视图函数的重复代码,节省开发时间。接下来就让我们把博客应用中的视图函数改成基于类的通用视图。ListView在我们的博客应用中,有

哨兵架构

  哨兵架构,是主从的升级版,master节点宕机后,可以主动选取我们的master节点。

uffer();for(inti=0;i<length;i++){intnumber=random.nextInt(62);sb.append(str.charAt(number));}retu

  我们还是分为jedis和springboot两种方式分别来尝试连接一下我们的哨兵架构,搭建我就不说啦,上次博文已经说过了。https://www.cnblogs.com/cxiaocai/p/11711377.html  

  jedis

型的需求,django提供了一个DetailView类视图。下面我们就来将detail视图函数转换为等价的类视图PostDetailView,代码如下:blog/views.pyfromdjango.

quest,pk):#...这些视图函数都是从数据库中获取文章(Post)列表,唯一的区别就是获取的文章列表可能不同。比如index获取全部文章列表,category获取某个分类下的文章列表。将ind

bject_name="post_list"defget_queryset(self):cate=get_object_or_404(Category,pk=self.kwargs.g

  还是老规矩,引入依赖,剩下的我们直接来写测试类吧。

</artifactId><version>2.9.0</version></dependency>这里我就不封装连接工具类啦,我们直接看下测试代码吧p

package com.redisclient.sentinel;import redis.clients.jedis.*;import java.util.HashSet;import java.util.Set;public class JedisClientSentinel {public static void main(String[] args) {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(20);
        jedisPoolConfig.setMaxIdle(10);
        jedisPoolConfig.setMinIdle(5);

        String masterName = "mymaster";
        Set<String> sentinels = new HashSet<String>();
        sentinels.add(new HostAndPort("47.105.97.79", 6380).toString());
        sentinels.add(new HostAndPort("47.105.97.142", 6380).toString());
        sentinels.add(new HostAndPort("118.190.147.181", 6380).toString());//JedisSentinelPool其实本质跟JedisPool类似,都是与redis主节点建立的连接池//JedisSentinelPool并不是说与sentinel建立的连接池,而是通过sentinel发现redis主节点并与其建立连接JedisSentinelPool jedisPool = new JedisSentinelPool(masterName, sentinels, jedisPoolConfig, 5000, null);

        Jedis jedis = null;try {//从redis连接池里拿出一个连接执行命令jedis = jedisPool.getResource();
            System.out.println(jedis.set("xiaocai888", "666888"));
            System.out.println(jedis.get("xiaocai888"));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {//注意这里不是关闭连接,在JedisPool模式下,Jedis会被归还给资源池。if (jedis != null)
                jedis.close();
        }
    }

}

  最简单的理解就是我们建立了一个set连接池。当哨兵节点宕机一个的时候,会尝试连接其它节点,当master节点宕机时,会报错连接错误,稍后会自动恢复的。 ✨

s服务器连接端口password:xiaocai#Redis服务器连接密码(默认为空)timeout:5000#连接超时时间(毫秒)cluster:nodes:115.28.208.105:6379,

  springboot

rintln(jedis.get("xiaocai888"));}catch(Exceptione){e.printStackTrace();}finally{//注意这里不是关闭连接,在JedisP

39;returnpostPostDetailView稍微复杂一点,主要是等价的detail视图函数本来就比较复杂,下面来一步步对照detail视图函数中的代码讲解。首先我们为PostDetailVi

库在开发网站的过程中,有一些视图函数虽然处理的对象不同,但是其大致的代码逻辑是一样的。比如一个博客和一个论坛,通常其首页都是展示一系列的文章列表或者帖子列表。对处理首页的视图函数来说,虽然其处理的对象

  我们先来修改一下我们yml配置文件

ig.setMaxIdle(10);config.setMinIdle(5);//这里将所有主从节点全部放入Set<HostAndPort>jedisClusterNode=newHash

#哨兵模式
spring:
  redis:
    database: 0 # Redis数据库索引(默认为0)
    host: 120.27.27.4 # Redis服务器地址
    port: 6379 # Redis服务器连接端口
    password: # Redis服务器连接密码(默认为空)
    timeout: 5000 # 连接超时时间(毫秒)
    sentinel:
      master: mymaster #主服务器所在集群名称
      nodes: 115.28.208.105:26379,47.105.92.89:26379,118.190.151.92:26379

  而我们的测试类和主从是一样的配置就可以了,springboot主要改一下配置就可以了。

as_view(),name="category"),]访问以下某个分类页面,可以看到依然显示的是该分类下的全部文章列表,和使用视图函数category时效果一模一样。将archive

集群架构

  上次我们说过了我们的集群架构,就是很多个小主从集合在一起,内部有半数机制,建议设置大于3的奇数个主从服务。

   这从我们来搭建三组一主一从服务,我们先来看一下jedis的代码,我们内部redis是将16384分为了三个片区,为了确保每个片区都存入数据我们采用了随机生成的key。

  jedis

型的需求,django提供了一个DetailView类视图。下面我们就来将detail视图函数转换为等价的类视图PostDetailView,代码如下:blog/views.pyfromdjango.

quest,pk):#...这些视图函数都是从数据库中获取文章(Post)列表,唯一的区别就是获取的文章列表可能不同。比如index获取全部文章列表,category获取某个分类下的文章列表。将ind

bject_name="post_list"defget_queryset(self):cate=get_object_or_404(Category,pk=self.kwargs.g

package com.redisclient.cluster;import org.apache.commons.pool2.impl.GenericObjectPoolConfig;import redis.clients.jedis.*;import java.io.IOException;import java.util.HashSet;import java.util.Random;import java.util.Set;public class JedisClientCluster {public static void main(String[] args) throws IOException {
        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
        config.setMaxTotal(20);
        config.setMaxIdle(10);
        config.setMinIdle(5);//这里将所有主从节点全部放入Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
        jedisClusterNode.add(new HostAndPort("120.27.27.4", 6379));
        jedisClusterNode.add(new HostAndPort("47.105.86.150", 6379));
        jedisClusterNode.add(new HostAndPort("47.105.84.186", 6379));
        jedisClusterNode.add(new HostAndPort("115.28.208.105", 6379));
        jedisClusterNode.add(new HostAndPort("47.105.92.89", 6379));
        jedisClusterNode.add(new HostAndPort("118.190.151.92", 6379));

        JedisCluster jedisCluster = null;try {//connectionTimeout:指的是连接一个url的连接等待时间//soTimeout:指的是连接上一个url,获取response的返回等待时间jedisCluster = new JedisCluster(jedisClusterNode, 6000, 5000, 10, "xiaocai", config);while (true) {try {
                    jedisCluster.set(getRandomString(4), "value" + getRandomString(4));
                    Thread.sleep(5000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {if (jedisCluster != null)
                jedisCluster.close();
        }
    }//length用户要求产生字符串的长度public static String getRandomString(int length) {
        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();for (int i = 0; i < length; i++) {int number = random.nextInt(62);
            sb.append(str.charAt(number));
        }return sb.toString();
    }

}

  springboot

rintln(jedis.get("xiaocai888"));}catch(Exceptione){e.printStackTrace();}finally{//注意这里不是关闭连接,在JedisP

39;returnpostPostDetailView稍微复杂一点,主要是等价的detail视图函数本来就比较复杂,下面来一步步对照detail视图函数中的代码讲解。首先我们为PostDetailVi

库在开发网站的过程中,有一些视图函数虽然处理的对象不同,但是其大致的代码逻辑是一样的。比如一个博客和一个论坛,通常其首页都是展示一系列的文章列表或者帖子列表。对处理首页的视图函数来说,虽然其处理的对象

  还是老规矩改一下配置类 

从数据库获取分类,然后使用filter函数过滤出该分类下的全部文章。来看看这种情况下类视图该怎么写:blog/views.pyclassCategoryView(ListView):model=Pos

# 集群模式
spring:
  redis:
    database: 0 # Redis数据库索引(默认为0)
    host: 120.27.27.4 # Redis服务器地址
    port: 6379 # Redis服务器连接端口
    password: xiaocai # Redis服务器连接密码(默认为空)
    timeout: 5000 # 连接超时时间(毫秒)
    cluster:
      nodes: 115.28.208.105:6379,47.105.92.89:6379,118.190.151.92:6379

  说到这里我们的三种模式的连接就全部写完了,这些使用还是一个比一个简单的,我们来看下内部的通讯和选举机制吧。

e();//操作字符串redisTemplate.opsForHash();//操作hashredisTemplate.opsForList();//操作listredisTemplate.opsFo

选举机制

  当slave发现自己的master变为FAIL状态时,便尝试进行Failover,以期成为新的master。由于挂掉的master可能会有 多个slave,从而存在多个slave竞争成为master节点的过程, 其过程如下:

39;blog/detail.html"context_object_name="post"defget(self,request,*args,**kwargs):#覆写get

1.slave发现自己的master变为FAIL

ringboot  我们先来修改一下我们yml配置文件#哨兵模式spring:redis:database:0#Redis数据库索引(默认为0)host:120.27.27.4#Redis服务器地址p

2.将自己记录的集群currentEpoch加1,并广播FAILOVER_AUTH_REQUEST 信息

=self.kwargs.get("pk"))returnsuper(CategoryView,self).get_queryset().filter(category=cate)和I

3.其他节点收到该信息,只有master响应,判断请求者的合法性,并发送FAILOVER_AUTH_ACK,对每一个epoch只发 送一次ack

ndomString(4),"value"+getRandomString(4));Thread.sleep(5000);}catch(Exceptione){e.printStackTrace();

4.尝试failover的slave收集master返回的FAILOVER_AUTH_ACK

=super(PostDetailView,self).get(request,*args,**kwargs)#将文章阅读量+1#注意self.object的值就是被访问的文章postself.obj

5.slave收到超过半数master的ack后变成新Master(这里解释了集群为什么至少需要三个主节点,如果只有两个,当其 中一个挂了,只剩一个主节点是不能选举成功的)

7.105.92.89:26379,118.190.151.92:26379  而我们的测试类和主从是一样的配置就可以了,springboot主要改一下配置就可以了。集群架构  上次我们说过了我们的集

6.广播Pong消息通知其他集群节点。从节点并不是在主节点一进入 FAIL 状态就马上尝试发起选举,而是有一定延迟,一定的延迟确保我们等待FAIL状态在 集群中传播,slave如果立即尝试选举,其它masters或许尚未意识到FAIL状态,可能会拒绝投票

图函数来说,虽然其处理的对象一个是文章,另一个是帖子,但是其处理的过程是非常类似的:首先是从数据库取出文章或者帖子列表,然后将这些数据传递给模板并渲染模板。于是,django把这些相同的逻辑代码抽取了

  最近公司有一些事情,就先说到这里吧,有时间给大家说一下redis来实现分布式锁的机制,还有一个炒鸡好用的redis分布式锁。

原文:https://www.cnblogs.com/cxiaocai/p/11715874.html
分享到:

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

发表评论

快捷回复:

评论列表 (有 0条评论, 1736人围观) 参与讨论