目标

  1. 了解Redis的客户端实现原理
  2. Redis的客户端简单实现

是什么

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种 类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集 合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查 询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵 (Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

使用场景

数据高并发的读写 海量数据的读写 对扩展性要求高的数据 生成流水号(按日期,每天从1开始增加)

为什么要用

解决应用服务器的cpu和内存压力 减少io的读操作,减轻io的压力 关系型数据库的扩展性不强,难以改变表结构

Redis底层通讯原理

例子

在此附上redis客户端传输协议原理地址:https://redis.io/topics/protocol


import java.io.IOException;
import java.net.Socket;

/**
 * @ClassName SqRedisClient
 * @Description
 * @Author 夕
 * @Date 2019-08-11 23:58
 * @Version V1.0
 **/
public class SqRedisClient {
    Socket connection;
    public SqRedisClient(String host, int port) throws IOException {
        connection = new Socket(host, port);
        // 数据发送,读取 基于连接
    }

    // set key value
    public String set(String key, String value) throws IOException {
        // 构建数据包
        StringBuilder command = new StringBuilder();
        command.append("*3").append("\r\n"); // 第一部分描述整个请求包含几个参数

        command.append("$3").append("\r\n");// 第一个参数的长度 --- 命令的名称
        command.append("SET").append("\r\n");// 第一个参数的值

        command.append("$").append(key.getBytes().length).append("\r\n");// 第2个参数的长度
        command.append(key).append("\r\n");// 第2个参数的值

        command.append("$").append(value.getBytes().length).append("\r\n");// 第3个参数的长度
        command.append(value).append("\r\n");// 第2个参数的值

        // 发送命令请求,发给redis服务器
        connection.getOutputStream().write(command.toString().getBytes());
        // 读取redis服务器的响应
        byte[] response = new byte[1024];
        connection.getInputStream().read(response);
        return new String(response);
    }

    // get key
    public String get(String key) throws IOException {
        // 构建数据包
        StringBuilder command = new StringBuilder();
        command.append("*2").append("\r\n"); // 第一部分描述整个请求包含几个参数

        command.append("$3").append("\r\n");// 第一个参数的长度 --- 命令的名称
        command.append("GET").append("\r\n");// 第一个参数的值

        command.append("$").append(key.getBytes().length).append("\r\n");// 第2个参数的长度
        command.append(key).append("\r\n");// 第2个参数的值

        System.out.println(command.toString());

        // 发送命令请求,发给redis服务器
        connection.getOutputStream().write(command.toString().getBytes());
        // 读取redis服务器的响应
        byte[] response = new byte[1024];
        connection.getInputStream().read(response);
        return new String(response);
    }
    public static void main(String[] args) throws IOException {
//        Jedis jedis = new Jedis("127.0.0.1",6379);
//        String str = jedis.get("mykey");
//        System.out.println(str);

        SqRedisClient redisClient = new SqRedisClient("127.0.0.1",6379);
        redisClient.set("hello","tony3333");
        System.out.println("设置完成####################");


        String value = redisClient.get("hello");
        System.out.println(value);

    }
}

以上代码是手写的redis的客户端发送get和set指令到服务器端,实现存储数据到redis和读取数据

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.sqyq</groupId>
    <artifactId>springboot-aop-learn</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-aop-learn</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--数据库连接驱动和连接池依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- 引入AOP组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <!--引入redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

以上是我的pom.xml

总结

类似redis的nosql数据库没有关联关系,数据结构简单,拓展表比较容易 nosql读取速度快,对较大数据处理快