《Learning Redis》学习笔记一:基础介绍

Redis是面向key-value存储速度最快的NoSql数据库之一,既可基于内存也可持久化。作为key-value数据存储,在一些非功能性需求中主要有以下特点:

1、数据集插入快,无异常

2、随机读:所有keys放内存因此读取速度非常快,Redis使用虚拟内存将keys存内存,将最小最近使用的values放磁盘来避免内存消耗

3、容错性和负载均衡:采用主从拓扑结构,master-slave;读请求均匀分布于从节点;

4、最终一致性:主节点更新从节点也会异步更新,存在短暂时间点不一致问题但会到达最终一致

5、分片和可扩展性:节点水平扩展使得数据集能大于内存

6、多数据中心支持+可管理+多客户端

一、Redis的安装和启动

1、下载zip安装文件解压即可

2、在redis安装目录下,直接运行Redis-server.exe或者Windows命令redis-server [redis.windows.conf]启动,默认端口号6379

3、conf文件是redis配置文件可以重名名和修改默认属性,修改后启动必需带上配置文件参数,否则还是以默认参数启动

二、客户端连接

1、进入redis安装目录,执行cmd命令:redis-cli [-h] [-p] 默认配置下IP和端口可以省略,可以连接多个客户端

2、连接客户端可进行各种数据操作,redis主要支持5种数据类型:String/List/Set/SortedSet/Hashes

3、基本命令:set/get等,不同数据类型set/get命令有不同前缀,可查询相关文档了解

例如String类型:set/get key [value]基本存取值操作;setNx N一般代表已存在key不做操作,不存在则新建;setEx E代表附加失效操作,单位秒set key value ex timeout

以下示例是几种数据类型在java中的简单使用,在以Redis作为数据库的时候会用到:

public class TestJedis {

    private JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "localhost");

    private Jedis jedis;

    public Jedis getResource() {
        jedis = jedisPool.getResource();
        return jedis;
    }

    public void setResource() {
        jedis.close();
    }

    /**
     * redis sets类型基本操作
     */
    private void testSetsType() {
        Jedis jedis = getResource();
        jedis.sadd("follow:cricket", "[email protected]", "[email protected]",
            "[email protected]");
        System.out.println("follow:cricket" + " : " + jedis.smembers("follow:cricket"));
        //元素个数统计
        Assert.assertEquals(3, jedis.scard("follow:cricket").longValue());
        jedis.sadd("follow:redis", "[email protected]", "[email protected]");
        System.out.println("follow:redis" + " : " + jedis.smembers("follow:redis"));
        Assert.assertEquals(2 , jedis.scard("follow:redis").longValue());

        //获取集合中的公共元素
        System.out.println(jedis.sinter("Cricket:followers", "follow:redis"));
        //存储集合中的公共元素到指定list中
        jedis.sinterstore("follow:redis+cricket", "follow:cricket", "follow:redis");
        System.out.println("follow:redis+cricket" + " : " + jedis.smembers("follow:redis+cricket"));
        System.out.println(jedis.sismember("follow:redis+cricket", "[email protected]"));
        System.out.println(jedis.sismember("follow:redis+cricket", "[email protected]"));

        //将成员从源集合移到目标集合中,但源集合中不删除该成员
        jedis.smove("follow:cricket", "follow:redis", "[email protected]");
        System.out.println("follow:cricket" + " : " + jedis.smembers("follow:cricket"));
        System.out.println("follow:redis" + " : " + jedis.smembers("follow:redis"));
        //随机返回一个元素
        System.out.println(jedis.srandmember("follow:cricket"));
        //随机移除
        System.out.println(jedis.spop("follow:cricket"));
        System.out.println(jedis.smembers("follow:cricket"));
        jedis.sadd("follow:cricket","[email protected]");
        System.out.println(jedis.smembers("follow:cricket"));
        jedis.srem("follow:cricket","[email protected]");
        System.out.println(jedis.smembers("follow:cricket"));
        System.out.println(jedis.sunion("follow:cricket", "follow:redis"));
        jedis.sunionstore("follow:cricket-or-redis", "follow:cricket", "follow:redis");
        System.out.println("follow:cricket-or-redis" + " : " + jedis.smembers("follow:cricket-or-redis"));
        System.out.println(jedis.sdiff("follow:cricket", "follow:redis"));
    }

    /**
     * redis List类型基本操作
     */
    private void testListType() {
        Jedis jedis = getResource();
        String key1 = "mykey4list1";
        String key2 = "mykey4list2";
        System.out.println("del key : " + jedis.del(key1, key2).longValue());

        for (int i = 0; i < 3; i++) {
            jedis.lpush(key1, "message" + i);
        }
        System.out.println(key1 + ":" + jedis.lrange(key1, 0, -1));
        for (int i = 3; i < 6; i++) {
            jedis.rpush(key2, "message" + i);
        }
        System.out.println(key2 + ":" + jedis.lrange(key2, 0, -1));

        Assert.assertEquals("message2", jedis.lindex(key1, 0));

        System.out.println(jedis.linsert(key1, LIST_POSITION.AFTER, "message2", "message7"));
        System.out.println(key1 + ":" + jedis.lrange(key1, 0, -1));
        Assert.assertEquals(4, jedis.llen(key1).longValue());
        //从左边移除第一个元素
        System.out.println("remove : " + jedis.lpop(key1));
        System.out.println(key1 + ":" + jedis.lrange(key1, 0, -1));

        System.out.println(jedis.lpushx(key1, "Message - 1.8"));
        System.out.println(key1 + ":" + jedis.lrange(key1, 0, -1));
        //按顺序和个数移除指定值,负数从右到左,0移除全部指定元素
        System.out.println(jedis.lrem(key1, 0, "Message - 1.8"));
        System.out.println(jedis.lrange(key1, 0, -1));

        System.out.println(jedis.lset(key1, -1, "Message - 7"));
        System.out.println(key1 + ":" + jedis.lrange(key1, 0, -1));
        System.out.println(jedis.ltrim(key1, 0, -1));
        System.out.println(key1 + ":" + jedis.lrange(key1, 0, -1));
        //最右边的元素从list1移到list2中
        jedis.rpoplpush(key1, key2);
        System.out.println(key1 + ":" + jedis.lrange(key1, 0, -1));
        System.out.println(key2 + ":" + jedis.lrange(key2, 0, -1));
    }

    /**
     * redis hashes类型基本操作
     */
    private void testHashesType() {
        Jedis jedis = getResource();
        String commonkey = "learning redis";
        jedis.hset(commonkey, "publisher", "Packt Publisher");
        jedis.hset(commonkey, "author", "Vinoo Das");
        System.out.println(jedis.hgetAll(commonkey).get("author"));
        Map attributes = new HashMap<>();
        attributes.put("ISBN", "XX-XX-XX-XX");
        attributes.put("tags", "Redis,NoSQL");
        attributes.put("pages", "250");
        attributes.put("weight", "200.56");
        jedis.hmset(commonkey, attributes);
        System.out.println(jedis.hgetAll(commonkey));
        System.out.println(jedis.hget(commonkey, "publisher"));
        System.out.println(jedis.hmget(commonkey, "publisher", "author"));
        System.out.println(jedis.hvals(commonkey));
        System.out.println(jedis.hget(commonkey, "publisher"));
        System.out.println(jedis.hkeys(commonkey));
        System.out.println(jedis.hexists(commonkey, "cost"));
        System.out.println(jedis.hlen(commonkey));
        System.out.println(jedis.hincrBy(commonkey, "pages", 10));
        System.out.println(jedis.hincrByFloat(commonkey, "weight", 1.1) + "gms");
        System.out.println(jedis.hdel(commonkey, "weight-in-gms"));
        System.out.println(jedis.hgetAll(commonkey));
        setResource();
    }
}
4、在客户端查看所有keys命令: keys * ,也支持通配表达式keys pattern

5、删除key:del key 删除该库所有key:flushDb  删除所有库所有数据:flushall

6、其它一些常用命令:

->append key value 追加值

->strlen key  查看value长度

->setRange key offset value 从offset位置开始替换或插入值,原长度不够的前置补'\xoo'

三、通信协议RESP(Redis Serialization Protocol)

Redis工作于C-S模式,客户端和服务端之前使用TCP/IP协议(应用层、传输层、网络层、网关接口),client向server发送请求数据包括:请求主体(Request Data)和请求头header(meta info),server向client返回数据包括:响应主体(Response Data)和响应头header;Header+Body共同构成信息块用于传输数据,Header主要包括协议名称、版本号、安全信息、参数个数和类型等,body存放的主要是真实数据。

以下是一个简单的使用实例:

抽象类Command主要是建立连接和定义通用命令执行方法:

public abstract class Command {

    protected Socket socket;

    public Command() {
        try {
            socket = new Socket(ConnectionProperties.host, ConnectionProperties.port);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String createPayload(ArrayList messageList) {
        int argumentSize = messageList.size();
        StringBuffer payload = new StringBuffer();
        payload.append('*');
        payload.append(argumentSize);
        payload.append("\r\n");
        for (int cursor = 0; cursor < messageList.size(); cursor++) {
            payload.append("$");
            payload.append(messageList.get(cursor).length());
            payload.append("\r\n");
            payload.append(messageList.get(cursor));
            payload.append("\r\n");
        }
        return payload.toString().trim();
    }

    public abstract String createPayload();

    public abstract void execute() throws IOException;

接下来是set/get命令执行,SetCommand和GetCommand继承抽象类Command:

public class SetCommand extends Command {

    private String key;
    private String value;

    public SetCommand(String key, String value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public String createPayload() {
        ArrayList messageList = new ArrayList<>();
        messageList.add("SET");
        messageList.add(key);
        messageList.add(value);
        return super.createPayload(messageList);
    }

    @Override
    public void execute() throws IOException {
        PrintWriter out = null;
        BufferedReader in = null;
        try {
            out = new PrintWriter(super.socket.getOutputStream(), true);
            out.println(createPayload());
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            System.out.println(in.readLine());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            in.close();
            out.flush();
            out.close();
            socket.close();
        }
    }
}
public class GetCommand extends Command {

    private String key;

    public GetCommand(String key) {
        this.key = key;
    }

    @Override
    public String createPayload() {
        ArrayList messageList = new ArrayList<>();
        messageList.add("GET");
        messageList.add(key);
        return super.createPayload(messageList);
    }

    @Override
    public void execute() throws IOException {
        PrintWriter out = null;
        BufferedReader in = null;
        try {
            out = new PrintWriter(super.socket.getOutputStream(), true);
            out.println(this.createPayload());
            //Reads from Redis server
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String msg = in.readLine();
            if (!msg.contains("-1")) {
                System.out.println(msg);
                System.out.println(in.readLine());
            } else {
                // This will show the error message since the
                // server has returned '-1'
                System.out.println("This Key does not exist !");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            out.flush();
            out.close();
            in.close();
            socket.close();
        }
    }
}
测试类如下:

public class TestClient {

    public void execute(Command command) {
        try {
            command.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        TestClient testClient = new TestClient();
        SetCommand setCommand = new SetCommand("msg", "redis learning");
        testClient.execute(setCommand);

        GetCommand getCommand = new GetCommand("msg");
        testClient.execute(getCommand);
    }
}



你可能感兴趣的:(《Learning Redis》学习笔记一:基础介绍)