redis和消息队列

本文详细介绍了Redis的五大数据类型,包括字符串、列表、集合、哈希和有序集合的操作,以及Redis的事务特性和主从复制策略。接着,阐述了RabbitMQ的点对点、工作队列和发布订阅三种模式的实现,展示了生产者和消费者如何交互。通过对Redis和RabbitMQ的深入理解,有助于提升分布式系统中的数据管理和消息通信能力。
摘要由CSDN通过智能技术生成

一、redis

        1、五大数据类型

                ①、字符串String
                        get/set/keys/del/append/strlen

set k1 v1  保存数据

keys *       查询所有数据

del k2       删除数据k2

get k1       获取数据k1

append k1 abc        往k1的值追加数据abc

strlen k1        返回k1值的长度(字符数量)


                      incr/decr/incrby/decrby

incr k1         k1自增1(相当于++)

decr k1        k1自减1(相当于--)

incrby k1 3         k1自增3(相当于+=3)

decrby k1 2          k1自减2(相当于-=2)

                        getrange/setrange

getrange k1 0 -1         查询k1全部的值

getrange k1 0 3         查询k1的值,范围是下标0~下标3

setrange k1 1 xxx         替换k1的值,从下标1开始提供为xxx

                     setnx/mset/mget/msetnx

setnx k2 sun      添加数据的时候判断是否已经存在,防止已存在的数据被覆盖掉

mset k1 v1 k2 v2 k3 v3         mset可以一次添加多条数据

mget k2 k3         一次获取多条数据

msetnx k3 v3 k4 v4         一次添加多条数据时,如果添加的数据 中有已经存在的,则失败

                        getset 

 getset k6 v6     因为没有k6,所以get为null,然后将k6v6的值添加到数据库
 getset k6 vv6    先获取k6的值,然后修改k6的值为vv6

 

                ②、列表List

                        lpush/rpush/lrange

lpush list01 1 2 3 4 5 # 从上往下添加

lrange list01 0 -1 # 查询list01中的全部数据

rpush list02 1 2 3 4 5 # 从下往上添加

                        lpop/rpop

lpop list02 # 从左(上)边移除第一个元素

 rpop list02 # 从右(下)边移除第一个元素

                        lindex/lrem/ltrim

lindex list01 2 # 从上到下数,下标为2的值

lrem list01 2 3 # 从list01中移除2个3


ltrim list01 3 6 # 截取下标3~6的值,别的全扔掉

                        rpoplpush/lset/linsert

rpoplpush list01 list02 # list01右边出一个,从左进入到list02的第一个位置

lset list02 0 x # 将list02中下标为0的元素修改成x

linsert list02 before 2 java # 从左边进入,在list02中的2元素之前插入java

                ③、集合Set

                        sadd/smembers/sismember

sadd set01 1 2 2 3 3 3 # 添加元素(自动排除重复元素)

smembers set01 # 查询set01集合

sismember set01 2    判断set01集合是否存在2

                        scard/srem/srandmember

scard set01    获得集合中的元素个数

srem set01 2 # 移除set01中的元素2


srandmember set01 3 # 从set01中随机获取3个元素

                        数学集合类         交集:sinter/ 并集:sunion /差集:sdiff

sinter set01 set02 # set01和set02共同存在的元素

sunion set01 set02 # 将set01和set02中所有元素合并起来(排除重复的)

sdiff set01 set02 # 在set01中存在,在set02中不存在

                ④、哈希Hash

                        hset/hget/hmset/hmget/hgetall/hde

hmset student id 101 name tom age 22 # 添加学生student,属性一堆

hget student name # 获取学生名字

hmget student name age # 获取学生名字年龄

hgetall student # 获取学生全部信息

hdel student age # 删除学生年龄属性

                        hlen/hexists/hkeys/hvals

hlen student    返回学生的属性个数

hexists student name # student中是否存在name属性

hkeys student # 获取student所有的属性名

hvals student # 获取student所有属性的值

                        hincrby/hincrbyfloat/hsetnx

hincrby student age 2 # 自增整数2


hincrbyfloat user money 5.5 # 自增小数5.5

hsetnx student age 18 # 添加时,判断age是否存在

                ⑤、有序集合Zset

                        zadd/zrange

zadd zset01 10 vip1 20 vip2 30 vip3 40 vip4 50 vip5    添加有序集合

zrange zset01 0 -1 # 查询数据

zrange zset01 0 -1 withscores # 带着分数查询数据

                        zrem/zcard/zcount/zrank/zscore

zrem zset01 vip5 # 移除vip

zcard zset01 # 集合中元素的个数

zcount zset01 20 30 # 分数在20~40之间,共有几个元素

zrank zset01 vip3 # vip3在集合中的下标(从上向下)

 zscore zset01 vip2 # 通过元素获得对应的分数

        

        2、事务

                ①、三特性:

                        隔离性:所有命令都会按照顺序执行,事务在执行的过程中,不会被其他客户端送来的命令 打断

                        没有隔离级别:队列中的命令没有提交之前都不会被实际的执行,不存在“事务中查询要看到 事务里的更新,事务外查询不能看到”这个头疼的问题

                        不保证原子性:冤有头债有主,如果一个命令失败,但是别的命令可能会执行成功,没有回滚

                ②、三步走:

                        开启multi

                        入队queued

                        执行exec

        3、主从复制

                就是 redis集群的策略 配从(库)不配主(库):小弟可以选择谁是大哥,但大哥没有权利去选择小弟 读写分离:主机写,从机读。

                ①、一主二仆

                准备三台服务器,并修改redis.conf

bind 0.0.0.0

                启动三台redis,并查看每台机器的角色,都是master

info replication

                让其余两台机器跟随主机

slaveof 192.168.38.128 6379

                ②、血脉相承

                一个主机理论上可以多个从机,但是这样的话,这个主机会很累 我们可以使用java面向对象继承中的传递性来解决这个问题,减轻主机的负担 形成祖孙三代:

slaveof 192.168.38.128 6379 # 129跟随128
slaveof 192.168.38.129 6379 # 130跟随129

                ③、复制原理

                 全量复制:Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份slave接收到数据 文件后,存盘,并加载到内存中;(步骤1234)

                增量复制:Slave初始化后,开始正常工作时主服务器发生的写操作同步到从服务器的过程;(步 骤56)

                

                ④、哨兵模式

                有个哨兵一直在巡逻,突然发现!!!!!老大挂了,小弟们会自动投票,从众小弟中选出新的老大

                . 每一台服务器中创建一个配置文件sentinel.conf,名字绝不能错,并编辑sentinel.conf

# sentinel monitor 被监控主机名(自定义) ip port 票数
sentinel monitor redis128 192.168.38.128 6379 1

                启动服务的顺序:主Redis --> 从Redis --> Sentinel1/2/3

redis-sentinel sentinel.conf

 

二、RabbitMQ

        1、点对点模式实现

                ①、创建虚拟机
                ②、获取连接
                ③、创建生产者

package simplest;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import util.ConnectionUtil;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Sender {

    public static void main(String[] args) throws IOException, TimeoutException {
        String msg = "hahaha";


        // 1.获得连接
        Connection connection = ConnectionUtil.getConnection();
        // 2.在连接中创建通道(信道)
        Channel channel = connection.createChannel();

        // 3.创建消息队列(1,2,3,4,5)
        /*
            参数1:队列的名称
            参数2:队列中的数据是否持久化
            参数3:是否排外(是否支持扩展,当前队列只能自己用,不能给别人用)
            参数4:是否自动删除(当队列的连接数为0时,队列会销毁,不管队列是否还存保存数据)
            参数5:队列参数(没有参数为null)
        */
        channel.queueDeclare("queue1",false,false,false,null);

        // 4.向指定的队列发送消息(1,2,3,4)
            /*
            参数1:交换机名称,当前是简单模式,也就是P2P模式,没有交换机,所以名称为""
            参数2:目标队列的名称
            参数3:设置消息的属性(没有属性则为null)
            参数4:消息的内容(只接收字节数组)
            */
        channel.basicPublish("","queue1",null,msg.getBytes());

        System.out.println("发送:" + msg);

        // 5.释放资源
        channel.close();
        connection.close();

    }
}


                ④、创建消费者

package simplest;

import com.rabbitmq.client.*;
import util.ConnectionUtil;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Recer {

    public static void main(String[] args) throws IOException, TimeoutException {


        // 1.获得连接
        Connection connection = ConnectionUtil.getConnection();
        // 2.获得通道(信道)
        Channel channel = connection.createChannel();

        DefaultConsumer consumer = new DefaultConsumer(channel){
            @Override//交付处理(收件人信息,包裹上的快递标签,协议的配置,消息)
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                // body就是从队列中获取的消息
                String s = new String(body);
                System.out.println("接收 = " + s);
            }
        };

        // 4.监听队列 true:自动消息确认
        channel.basicConsume("queue1", true,consumer);
    }
}

        2、工作队列模式
                ①、创建虚拟机
                ②、获取连接
③、创建生产者

package work;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import util.ConnectionUtil;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Sender {

    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection = ConnectionUtil.getConnection();
        Channel channel = connection.createChannel();
        // 声明队列(此处为生产者,创建队列)注明出餐口位置,通知大家来排队
        channel.queueDeclare("test_work_queue",false,false,false,null);
        for(int i = 1;i<=100;i++) {
            String msg = "羊肉串 --> "+i;
            channel.basicPublish("", "test_work_queue", null, msg.getBytes());
            System.out.println("师傅烤好:" + msg);
        }

        // 5.释放资源
        channel.close();
        connection.close();

    }
}


④、创建多个消费者

        消费者1

package work;

import com.rabbitmq.client.*;
import util.ConnectionUtil;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Recer1 {
    static int i = 1; // 记录执行次数
    public static void main(String[] args) throws IOException, TimeoutException {


        // 1.获得连接
        Connection connection = ConnectionUtil.getConnection();
        // 2.获得通道(信道)
       final Channel channel = connection.createChannel();
        // 声明队列(此处为消费者,不是声明创建队列,而且获取,二者代码相同)出餐口排队
        channel.queueDeclare("test_work_queue",false,false,false,null);
        // 可以理解为:快递一个一个送,送完一个再送下一个,速度快的送件就多
        channel.basicQos(1);

        Consumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String msg = new String(body);
                System.out.println("【顾客1】吃掉 " + msg+" ! 共吃【"+i++ +"】串");
                // 撸一会,有延迟
                try {
                    Thread.sleep(400);
                }catch (InterruptedException e){
                }
                // 手动确认(收件人信息,是否同时确认多个消息)
                channel.basicAck(envelope.getDeliveryTag(),false);
            }

        };
        //监听队列
        channel.basicConsume("test_work_queue", false, consumer);

    }
}

        消费者2

package work;

import com.rabbitmq.client.*;
import util.ConnectionUtil;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Recer2 {


    static int i = 1; // 记录执行次数
    public static void main(String[] args) throws IOException, TimeoutException {


        // 1.获得连接
        Connection connection = ConnectionUtil.getConnection();
        // 2.获得通道(信道)
        final Channel channel = connection.createChannel();
        // 声明队列(此处为消费者,不是声明创建队列,而且获取,二者代码相同)出餐口排队
        channel.queueDeclare("test_work_queue",false,false,false,null);
        // 可以理解为:快递一个一个送,送完一个再送下一个,速度快的送件就多
        channel.basicQos(1);
        Consumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String msg = new String(body);
                System.out.println("【顾客2】吃掉 " + msg+" ! 共吃【"+i++ +"】串");
                // 撸一会,有延迟
                try {
                    Thread.sleep(200);
                }catch (InterruptedException e){
                }
                channel.basicAck(envelope.getDeliveryTag(),false);
            }

        };
        //监听队列
        channel.basicConsume("test_work_queue", false, consumer);
    }
}

        3、发布订阅模式
                 ①、创建虚拟机
                ②、获取连接
                ③、创建生产者(创建路由)

package ps;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import util.ConnectionUtil;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Sender {

    public static void main(String[] args) throws IOException, TimeoutException {
        String msg = "hahaha";


        // 1.获得连接
        Connection connection = ConnectionUtil.getConnection();
        // 2.在连接中创建通道(信道)
        Channel channel = connection.createChannel();
        //3. 声明路由(路由名,路由类型)
        // fanout:不处理路由键(只需要将队列绑定到路由上,发送到路由的消息都会被转发到与该路由绑定的所有队列上)
        channel.exchangeDeclare("test_exchange_fanout", "fanout");
        //s1是路由名称
        channel.basicPublish("test_exchange_fanout", "", null, msg.getBytes());


        System.out.println("发送:" + msg);
        // 5.释放资源
        channel.close();
        connection.close();

    }
}


                ④、创建多个消费者(声明队列,绑定路由)

消费者1:

package ps;

import com.rabbitmq.client.*;
import util.ConnectionUtil;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Recer1 {


    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection = ConnectionUtil.getConnection();
        Channel channel = connection.createChannel();
        // 声明队列
        channel.queueDeclare("test_exchange_fanout_queue_1",false,false,false,null);
        // 绑定路由(关注)
        /*
            参数1:队列名
            参数2:交换器名称
            参数3:路由key(暂时无用,""即可)
        */
        channel.queueBind("test_exchange_fanout_queue_1",
                "test_exchange_fanout", "");
        DefaultConsumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                                       AMQP.BasicProperties properties, byte[] body) throws IOException {
                String s = new String(body);
                System.out.println("【消费者1】 = " + s);
            }
        };
        // 4.监听队列 true:自动消息确认
        channel.basicConsume("test_exchange_fanout_queue_1", true,consumer);


    }
}

消费者2:

package ps;

import com.rabbitmq.client.*;
import util.ConnectionUtil;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Recer2 {


    public static void main(String[] args) throws IOException, TimeoutException {

        Connection connection = ConnectionUtil.getConnection();
        Channel channel = connection.createChannel();
        // 声明队列
        channel.queueDeclare("test_exchange_fanout_queue_2",false,false,false,null);
        // 绑定路由(关注)
        /*
            参数1:队列名
            参数2:交换器名称
            参数3:路由key(暂时无用,""即可)
        */
        channel.queueBind("test_exchange_fanout_queue_2",
                "test_exchange_fanout", "");
        DefaultConsumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                                       AMQP.BasicProperties properties, byte[] body) throws IOException {
                String s = new String(body);
                System.out.println("【消费者2】 = " + s);
            }
        };
        // 4.监听队列 true:自动消息确认
        channel.basicConsume("test_exchange_fanout_queue_2", true,consumer);


    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值