zoukankan      html  css  js  c++  java
  • Redis学习

    打算认真地系统地学习一下redis,本文为鉴,笑。

    先说认识

    这货是一个数据库,特点是:NoSQL + 内存型

    只是,其实多数人使用的都是“内存型”这个特性 -- 因为速度快,NoSQL 反而没那么显眼。

    当然,如果只是“内存型”,其实还有很多选择,例如ehcache、memcache等,甚至web应用的session也算一个,或者,还可以自己构建一个Map用于存取数据。

    之所以使用Redis,是因为它还提供了很多其他特性,例如多种数据格式、事务、集群、主从、持久化、订阅/发布等等。 -- 鉴于没有深入研究过ehcache、memcache,就不列出对比了。

    开始

    官方网站 redis.io 下载后,需要安装方可使用,详情请搜索之。--建议使用Linux运行,因为多数开源工具都优先支持Linux,总要接触的,不如直接开始。当然也有windows版本的,版本较旧就是。

    Linux下安装后的内容:

    [root@localhost redis-3.2.6]# cd /usr/local/bin/
    [root@localhost bin]# ll
    总用量 26344
    -rw-r--r--. 1 root root     377 12月 24 14:55 dump.rdb
    -rwxr-xr-x. 1 root root 5580287 12月 24 01:45 redis-benchmark
    -rwxr-xr-x. 1 root root   22177 12月 24 01:45 redis-check-aof
    -rwxr-xr-x. 1 root root 7826296 12月 24 01:45 redis-check-rdb
    -rwxr-xr-x. 1 root root 5708996 12月 24 01:45 redis-cli
    lrwxrwxrwx. 1 root root      12 12月 24 01:45 redis-sentinel -> redis-server
    -rwxr-xr-x. 1 root root 7826296 12月 24 01:45 redis-server
    [root@localhost bin]#

    需要说明的是,redis-server可以直接启动,但是仅限于本机使用。正确的启动方式应该附加配置文件redis.conf -- 可以在redis解压后的目录中找到,如下:

    [root@localhost bin]# ll ~/software/redis-3.2.6
    总用量 200
    -rw-rw-r--.  1 root root 80406 12月  6 16:38 00-RELEASENOTES
    -rw-rw-r--.  1 root root    53 12月  6 16:38 BUGS
    -rw-rw-r--.  1 root root  1805 12月  6 16:38 CONTRIBUTING
    -rw-rw-r--.  1 root root  1487 12月  6 16:38 COPYING
    drwxrwxr-x.  7 root root  4096 12月 24 01:42 deps
    -rw-rw-r--.  1 root root    11 12月  6 16:38 INSTALL
    -rw-rw-r--.  1 root root   151 12月  6 16:38 Makefile
    -rw-rw-r--.  1 root root  4223 12月  6 16:38 MANIFESTO
    -rw-rw-r--.  1 root root  6834 12月  6 16:38 README.md
    -rw-rw-r--.  1 root root 46695 12月  6 16:38 redis.conf
    -rwxrwxr-x.  1 root root   271 12月  6 16:38 runtest
    -rwxrwxr-x.  1 root root   280 12月  6 16:38 runtest-cluster
    -rwxrwxr-x.  1 root root   281 12月  6 16:38 runtest-sentinel
    -rw-rw-r--.  1 root root  7606 12月  6 16:38 sentinel.conf
    drwxrwxr-x.  2 root root  4096 12月 24 01:42 src
    drwxrwxr-x. 10 root root  4096 12月  6 16:38 tests
    drwxrwxr-x.  7 root root  4096 12月  6 16:38 utils
    [root@localhost bin]#

    但是,默认的配置仅限于回环访问,就是仅限于127.0.0.1访问,其他地址不行,所以需要修改一下(建议备份原有的)。

    [root@localhost redis-3.2.6]# cat redis.conf 
    # 许可IP
    bind 127.0.0.1
    # 监听端口
    port 6379
    
    tcp-backlog 511
    
    # 客户端空闲N秒后关闭连接(0是禁用)
    timeout 0
    
    tcp-keepalive 300
    
    # 是否改为守护进程
    daemonize no
    
    supervised no
    
    pidfile /var/run/redis_6379.pid
    
    loglevel notice
    
    logfile ""
    
    databases 16
    
    ################################ SNAPSHOTTING  ################################
    # 持久化(保存到硬盘上)
    # 900秒(15分钟)后,如果至少一个key发生改变
    save 900 1
    # 300秒(5分钟)后,如果至少十个key发生改变
    save 300 10
    # 50秒后,如果至少10000个key发生改变
    save 60 10000
    
    
    stop-writes-on-bgsave-error yes
    
    rdbcompression yes
    
    rdbchecksum yes
    # 持久化的目标文件名
    dbfilename dump.rdb
    
    # 持久化的目标目录
    dir ./
    
    
    
    # 主从
    slave-serve-stale-data yes
    
    slave-read-only yes
    
    repl-diskless-sync no
    
    repl-diskless-sync-delay 5
     
    repl-disable-tcp-nodelay no
     
    slave-priority 100
     
     
    ################################## SECURITY ###################################
    # 安全
    # 要求客户端在处理命令之前先AUTH <PASSWD>
    # 鉴于Redis非常快速,外部用户每秒可以尝试150K次密码,所以建议启用一个非常强壮的密码,否则很容易被破解。--本人建议配合bind使用或者仅使用bind。
    # 默认注释,即不需要密码。这里我给放开了,所以需要密码foobared
    requirepass foobared
    
    
    
    # maxclients 10000
    
    # maxmemory <bytes>
     
    # maxmemory-policy noeviction
     
    # maxmemory-samples 5
     
    appendonly no
    
    # The name of the append only file (default: "appendonly.aof")
    appendfilename "appendonly.aof"
    
    # appendfsync always
    appendfsync everysec
    # appendfsync no
     
    no-appendfsync-on-rewrite no
     
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
     
    aof-load-truncated yes
     
    # Set it to 0 or a negative value for unlimited execution without warnings.
    lua-time-limit 5000
    
    ################################ REDIS CLUSTER  ###############################
     
    # cluster-enabled yes
     
    # cluster-config-file nodes-6379.conf
     
    # cluster-node-timeout 15000
    
    # cluster-slave-validity-factor 10
     
    # cluster-migration-barrier 1
     
    # cluster-require-full-coverage yes
     
    
    ################################## SLOW LOG ###################################
     
    slowlog-log-slower-than 10000
     
    slowlog-max-len 128
    
    ################################ LATENCY MONITOR ##############################
     
    latency-monitor-threshold 0
    
    ############################# EVENT NOTIFICATION ##############################
     
    notify-keyspace-events ""
    
    ############################### ADVANCED CONFIG ###############################
     
    hash-max-ziplist-entries 512
    hash-max-ziplist-value 64
     
    list-max-ziplist-size -2
     
    list-compress-depth 0
     
    set-max-intset-entries 512
     
    zset-max-ziplist-entries 128
    zset-max-ziplist-value 64
     
    hll-sparse-max-bytes 3000
     
    activerehashing yes
     
    client-output-buffer-limit normal 0 0 0
    client-output-buffer-limit slave 256mb 64mb 60
    client-output-buffer-limit pubsub 32mb 8mb 60
     
    hz 10
     
    aof-rewrite-incremental-fsync yes

    以上是精简版,去掉了大段的英文注释。因为我使用了虚拟机+桥接方式,所以不能通过127.0.0.1:6379访问,所以放开了requirepass,这样就可以通过auth来验证了。

    数据格式

    Redis支持的数据格式有五种:string、list、hash、set、sortedset!

    需要注意的是,这些数据格式的 -- 本质上都是字节数组(byte[])!

    所以,Redis的任何一种格式都可以存储Java的所有的类型 -- 只要你将其转成字节数组 (byte[])!

    Java中对象转成字节数组(byte[])的方式,最基本的是通过ByteArrayOutputStream和ObjectOutputStream将实现了Serializable接口的类对象转成字节数组。如下:

    Person p = new Person();
    p.setName("小雯");
    p.setId("456321789");
    p.setAge(13);
    p.setWords("豆蔻年华二月初");
    
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try {
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(out);
        objectOutputStream.writeObject(p);
        byte[] byteArray = out.toByteArray();
    } catch (IOException e) {
        e.printStackTrace();
    }

    或者,使用Jackson等序列化工具进行序列化 -- 更简洁明了,因为都是字符串。

    需要提一句,不建议使用ByteArrayOutputStream和ObjectOutputStream这种原始方式进行序列化,因为会序列化很多不必要的信息。以上面的代码为例,实际上我们只需要name、id、age、words这四个properties的信息就足够了,但原始的序列化还会附加很多信息(如继承的类、接口等等),这样会浪费时间和空间。

    所以,推荐使用Jackson、fastjson、gson等序列化工具。

    客户端

    Java的客户端推荐使用Jedis(其实我就知道这个),自带连接池、集群等配置,其方法与Redis完全一致。与Spring结合时可以使用RedisTemplate,类似RestTemplate。

    新建maven项目,添加依赖即可:

    <!-- jackson新版本 -->
    <!-- jackson-databind依赖core和annation,所以不必重复导入 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.8.5</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-joda</artifactId>
        <version>2.8.5</version>
    </dependency>
    
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.9.0</version>
    </dependency>

    现在就可以使用Jedis了,先放一个小例子,后面详细研究下每种数据格式对应的方法。

    public class BasicDemo {
        private static final String PREFIX = "ABCDEF.";
        private static Jedis redis;
    
        // redis默认开启了保护,只允许本地回环连接请求(就是127.0.0.1),需要在redis.conf中修改。或设置密码、或bind许可ip。
        @Before
        public void setUp() {
            String host = "192.168.0.210";
            int port = 6379;
            redis = new Jedis(host, port);
            redis.auth("foobaredauth");
        }
    
        // STRING 操作 --TODO:实际上存储的是byte[],所以可以存储任意内容
        @Test
        public void string() {
    
            // SET key value: 将字符串值value关联到key。
            redis.set("name", "wangjun1");
            redis.set("id", "123456");
            redis.set("address", "guangzhou");
    
            // SETEX key seconds value :将值value关联到key,并将key的生存时间设为seconds(以秒为单位)。
            redis.setex("foo", 5, "haha");
    
            // MSET key value [key value ...] :同时设置一个或多个key-value对。
            redis.mset("haha", "111", "xixi", "222");
    
            // redis.flushAll();清空所有的key
            System.out.println(redis.dbSize());// dbSize是多少个key的个数
    
            // APPEND key value :如果key已经存在并且是一个字符串,APPEND命令将value追加到key原来的值之后。
            redis.append("foo", "*00");// 如果key已经存在并且是一个字符串,APPEND命令将value追加到key原来的值之后。
    
            // GET key 返回key所关联的字符串值
            String foo = redis.get("foo");
            System.out.println(foo);
    
            // MGET key [key ...] 返回所有(一个或多个)给定key的值
            List<String> list = redis.mget("haha", "xixi");
            for (int i = 0; i < list.size(); i++) {
                System.out.println(list.get(i));
            }
        }
    }

    未完待续

    参考:

    Redis 命令参考

    为什么要选择使用 Redis ?

  • 相关阅读:
    codeforces 980A Links and Pearls
    zoj 3640 Help Me Escape
    sgu 495 Kids and Prizes
    poj 3071 Football
    hdu 3853 LOOPS
    hdu 4035 Maze
    hdu 4405 Aeroplane chess
    poj 2096 Collecting Bugs
    scu 4444 Travel
    zoj 3870 Team Formation
  • 原文地址:https://www.cnblogs.com/larryzeal/p/6263124.html
Copyright © 2011-2022 走看看