Redis入门笔记

NoSQL的概述

什么是NoSQL

  • Not Only Sql
  • 非关系型数据库

为什么需要NoSQL

  • High performance — 高并发读写
  • Huge Storage — 海量数据的高效率存储与访问
  • High Scalability && High Availablity — 高可扩展和高可用

NoSQL产品

  • Redis
  • MongoDB
  • membase

NoSQL数据库的四大分类

  • 键值(K-V)存储:快速查询,数据没有结构化
  • 列存储(Hbase):查找速度快,扩展强,功能局限
  • 文档数据库(MongoDB):数据结构要求不严格,查询性能不是很高,缺少统一查询的语法
  • 图形数据库(Neo4j,infinite):利用图结构的算法,需要的整个图做计算才能拿到结果,不利于分布式的部署

NoSQL特点

  • 易扩展,非关系型
  • 灵活的数据模型
  • 大量数据,高性能
  • 高可用

Redis

高性能键值对数据库,使用C语言开发,支持的数据类型如下:

  • 字符串类型
  • 列表类型
  • 有序集合类型
  • 散列类型
  • 集合类型

读写性能:50个并发程序执行10万个请求,读速度:100000次/秒 写速度:81000次/秒

Redis应用场景

  • 缓存
  • 任务队列
  • 网站访问统计
  • 数据过期处理
  • 应用排行榜
  • 分布式集群架构中的session分离

redis安装

自行google或者百度

Jedis入门

什么是jedis ?
Jedis官方github,readme介绍如下:

Jedis is a blazingly small and sane Redis java client.
Jedis was conceived to be EASY to use.
Jedis is fully compatible with redis 2.8.x and 3.x.x.

Jedis是一个超级炫酷轻量和智能与一体的Redis的Java客户端,大家都觉得Jedis非常的好用,并且完全的兼容Redis2.8.x and 3.x.x.与此同时,Jedis也是Redis官方推荐使用的Redis的Java客户端。

Jedis的基本使用

 @Test
    /**
     * jedis 单例测试
     */
    public void demo1() {
        // 1.设置ip地址和端口
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        // 2.保存数据
        jedis.set("name", "hello");
        // 3.获取数据
        String v = jedis.get("name");
        System.out.println(v);
        // 4.释放资源
        jedis.close();

    }

    @Test
    /**
     * 使用jedis连接池
     */
    public void demo2() {
        //创建jedis连接池配置对象:
        JedisPoolConfig config = new JedisPoolConfig();
        //配置jedisPoolConfig
        config.setMaxTotal(30);
        config.setMaxIdle(10);
        //创建jedis连接池
        JedisPool jedisPool = new JedisPool(config, "127.0.0.1", 6379);
        //使用连接池获取核心对象:
        Jedis jedis = null;
        try {
            //获取对象
            jedis = jedisPool.getResource();
            //设置数据
            jedis.set("name", "hashMap");
            //获取数据
            String value = jedis.get("name");
            System.out.println(value);

        } catch (Exception e) {
            System.out.println(e.getMessage());

        } finally {
            //释放资源
            if (jedis != null) {
                jedis.close();
            }
            if (jedisPool != null) {
                jedisPool.close();
            }
        }
    }

Redis数据结构

  • 字符串(String)常用
  • 哈希(hash)常用
  • 字符串列表(list)
  • 字符串集合(set)
  • 有序字符串集合(sorted list)

key的定义注意点:

  • 不要太长,占用内容大,且查找效率降低
  • 不要太短,否则降低可读性

存储String

以二进制的形式进行存储操作的,意味着String的存储和获取的结果是相同的
最多容纳的value:512M

存储String的常用命令:
  • 赋值
  1. set key value
  2. getset key newvalue
    –> 先获取key的值然后将key对应的value设置为newvalue
  • 取值
  1. get key
    –> 获取这个key对应的value
  • 删除
  1. del key
    –> 返回一个(interger)1表示删除成功,之后get key
    –> 会得到(nil)表示这个key没有value
  • 数值增减
  1. incr num
    –> 如果num不存在初始化为0然后加1,num变为1
    –> 如果num存在并且可以转为整形,num直接加1
    –> 如果num存在但是不能转为整形,报出错误信息

  2. decr num
    –> 如果num不存在初始化为0然后减1,num变为-1
    –> 如果num存在并且可以转为整形,num直接减1
    –> 如果num存在但是不能转为整形,报出错误信息

  • 扩展命令
  1. incrby num increment
    –> 如果num不存在初始化为0然后减increment
    –> 如果num存在并且可以转为整形,num直接减increment
    –> 如果num存在但是不能转为整形,报出错误信息

  2. decrby num decrement
    –> 如果num不存在初始化为0然后减decrement
    –> 如果num存在并且可以转为整形,num直接减decrement
    –> 如果num存在但是不能转为整形,报出错误信息

  3. append num value
    –> 如果num不存在新创建一个num value
    –> 如果num存在,以字符串形式在num后面追加一个value,得到追加之后的长度,结果是”numvalue”

存储Hash

hash类型可以看做是String key 和String value的map容器,非常适合存储值对象的信息,比如同户名,密码,年龄等…

存储hash常用的命令:
  • 赋值
  1. hset myset key value
    –> 设置 myset 指定的哈希集中指定字段key的值。
    –> 如果 myset 指定的哈希集不存在,会创建一个新的哈希集并与 myset 关联。
    –> 如果字段在哈希集中存在,它将被重写

  2. hmset myset key value [key value …]
    –> 设置 myset 指定的哈希集中指定字段的值。该命令将重写所有在哈希集中存在的字段
    –> 如果 myset 指定的哈希集不存在,会创建一个新的哈希集并与 myset 关联

  • 取值
  1. hget myset key
    –> 返回 myset 指定的哈希集中该key所关联的值

  2. hmget myset key [key …]
    –> 设置 myset 指定的哈希集中指定key的值。该命令将重写所有在哈希集中存在的字段。
    –> 如果 myset 指定的哈希集不存在,会创建一个新的哈希集并与 myset 关联

  3. hgetall myset
    –> 返回 key 指定的哈希集中所有的字段和值。返回值中,每个字段名的下一个是它的值,所以返回值的长度是哈希集大小的两倍

  • 删除
  1. hdel myset key [key …]
    –> 从 key 指定的哈希集中移除指定的域。在哈希集中不存在的域将被忽略
    –> 如果 key 指定的哈希集不存在,它将被认为是一个空的哈希集,该命令将返回0

  2. del myset
    –> 直接删除整个哈希集

  • 增加数字
  1. hincreby myhash key increment
    增加 myhash 指定的哈希集中指定字段的数值。如果 myhash不存在,会创建一个新的哈希集并与 myhash 关联。如果字段不存在,则字段的值在该操作执行前被设置为 0

HINCRBY 支持的值的范围限定在 64位 有符号整数

  • 自学命令
  1. hexists myhash key
    判断key是否在myhash中存在。存在返回1,否则返回0

  2. hlen myhash
    返回 myhash 指定的哈希集包含的字段的数量。

  3. hkeys myhash
    返回 myhash 指定的哈希集中所有字段的key。

  4. hvals myhash
    返回 myhash 指定的哈希集中所有字段的value。

存储list:

  • ArrayList使用数字方式存储
  • LinkedList使用双向链表方式存储
  • 双向链表中增加数据
  • 双向链表中删除数据

存储list常用的命令:

  • 两端添加
  1. lpush
  2. rpush
  • 查看链表
  1. lrange
  • 两端弹出
  1. lpop
  2. rpop
  • 获取列表元素个数
  1. llen
  • 扩展命令
  1. lpushx
  2. rpushx
  3. lrem
  4. lset
  5. linsert
  6. rpoplpush –> 消息队列

存储Set

  • 和list类型不同的是,Set集合中不允许出现重复的元素
  • Set可以包含的元素数量是4294967295

存储Set常用的命令:

  • 添加删除元素
  1. sadd myset 1 2 3
  2. srem myset 2
  • 获取集合中的元素
  1. smembers myset –> 获取所有元素
  2. sismember myset 3 -> 判断某个元素时候属于集合
  • 集合中的差集运算
  1. sdiff
  • 集合中的并集运算
  1. sunion
  • 集合中的交集运算
  1. sinter
  • 扩展命令
  1. scard -> 获取元素个数
  2. srandmember myset -> 随机返回myset中的某个成员
  3. sdiffstore my1 my2 my3-> 把my2 my3差集存在my1中
  4. sinterstore my1 my2 my3 -> 把my2 my3 交集存在my1中
  5. sunionstore my1 my2 my3 -> 把my2 my3 并集存入my1中

存储Set使用的场景

  • 跟踪一些唯一性数据
  • 用于维护数据对象之间的关联关系,可以做一些并集交集的运算

存储Sorted-Set

  • 与Set的区别:
  1. Sorted-Set成员有序,时间复杂度是元素个数的对数O(logn)
  2. Sorted-Set中的成员在集合中的位置是有序的

存储Sorted-Set常用的命令:

  • 添加元素
  1. zadd mysort 50 funi 60 sorw
  • 删除元素
  1. zrem mysort funi sorw -> 删除sorted-set中的funi sorw记录
  • 获取元素
  1. zscore mysort funi -> 获取具体元素的分数
  2. zcard mysort -> 获取mysort的元素个数
  • 范围查询
  1. zrange mysort 0 -1 -> 显示所有元素(不显示分数)
  2. zrange mysort 0 -1 withscores -> 显示所有元素并显示分数,由小到大排序
  3. zrevrange mysort 0 -1 withscores -> 显示所有元素并显示分数,由大到小排序
  4. zremrangebyrank mysort 0 4 -> 按照下标顺序删除元素
  5. zremrangebyscore mysort 80 100 -> 按照分数的范围删除元素
  • 扩展命令
  1. zrangebyscore mysort 0 100 [withscores][limit 0 2]-> 显示分数为0到100并按照从小到大排序显示,withscore显示分数,limit显示从第0个到第2个
  2. zincrby mysort 3 li -> 给li的分数加3
  3. zcount mysort 80 90 -> 显示分数是80到90的元素个数

Sorted-Set使用场景

  • 大型在线游戏积分排行榜
    先使用zadd添加,然后zrange获取
  • 构建索引数据

Keys的通用操作

  • keys * -> 获取所有的key
  • del -> 删除key
  • exists -> 判断是否存在
  • get key -> 获取这个key的value
  • rename company newcompany -> 重命名company
  • expire newcompany 1000 -> 设置1000s的过期时间
  • ttl newcompany -> 过期时间剩余
  • type key -> 获取这个key的数据类型

Redis特性:

  1. 多数据库
  • 一个redis实例最多可以提供十六个数据库,就像是mysql的数据库一样,客户端可以指定连接那个数据库,redis的数据库下标是从0 – 15。
  • 可以使用select 1 -> 来选择几号数据库。默认使用的是0号数据库
  • 可以使用move myset 1 -> 将myset移动到1号数据库
  1. 支持事务
    Redis使用multi exec discard来执行事务,事务中所有的命令都会被串行化执行,事务执行期间,redis不会为其他客户端提供服务,保证事务的原子性。与关系型数据库不同的是,redis事务中,如果某个命令执行失败,事务不会终止,而是继续执行后面的命令
  • 可以使用multi 来开启是一个事务 相当于start transaction
  • 通过exec相当于提交 相当于commit
  • 通过discard相当于回滚 相当于roolback

Redis的持久化

  • Redis的高效率源于Redis把数据都存储在内存当中,为了保证Redis在服务重启之后数据不丢失,就需要把Redis中的数据进行持久化(数据从内存同步到硬盘)。

持久化方式:

  1. RDB方式
  2. AOF方式

持久化使用的方式:

RDB方式
默认支持的,不需要设置。RDB方式就是在默认的时间间隔之后,将内存中的数据集快照写入到磁盘

AOF方式:
以日志的方式记录服务器所处理的每一个操作,在Redis服务器启动之初,会读取这个文件,然后重新构建,保证数据是完整的

无持久化:
通过配置禁用Redis持久化功能,这个时候Redis就是一个缓存的功能

同时使用RDB和AOF的方式:’
数据集快照+日志

Redis持久化的RDB方式

优势:

  1. 只有一个文件,对于文件备份而言很简单。
  2. 灾难恢复,RDB可以压缩文件之后转移个另一个服务器上
  3. 性能最大化,分叉出一些子进程,然后使用子进程来做持久化操作,可以极大的避免IO的影响
  4. 相比于AOF如果数据集很大,启动效率更高

劣势:

  1. 如果想保证数据的高可用性,是数据尽可能的不丢失RDB不是很好的选择,因为如果在系统定时持久化之前宕机,还没有来得及写数据,就会导致数据的丢失
  2. 由于RDB使用fork分叉来使用子进程完成数据的持久化操作,因此如果数据集很大,会导致整个服务器停止几百毫秒来等待持久化操作的完成。

配置:redis.conf

save 900 1 //表示每900s有一个key发生变化就会之久化一次
save 300 10 //每300s有10个key发生变化,会往硬盘上写一次
save 60 10000 //每60s有10000个key发生变化会写一次

保存在./dump.rdb

Redis持久化的AOF方式

优势:

  1. 更高的数据安全性。redis中提供了三种同步策略:每秒同步,每修改同步,和不同步;
  2. 对日志写入的过程是append追加的模式。因此就算宕机,也不会破坏已经写入的日志。如果写入一半的时候出现问题,也可以使用redis-cheak-aof这个工具来帮助我们解决数据一致性的问题
  3. 如果日志过大,redis会自动启动数据重写机制,以append的模式不断的写入老的磁盘文件当中,同时redis还会产生一个文件来记录此期间产生的修改命令。因此重写切换的时候还是可以保证数据的安全性。
  4. AOF包含的是格式清晰的日志文件,用于记录所有的修改操作。甚至可以通过这个文件来重建数据

劣势:

  1. AOF的文件比RDB的文件更大
  2. 同步策略的不同导致AOF运行的效率低于RDB

配置:redis.conf

appendonly no //默认不启动AOF
appendonly.aof //AOF文件

//同步方式:
# appendfsync always //每修改同步
# appendfsync everysec //每秒同步
# appendfsync no //不同步 

如果要使用AOF方式,应该首先修改第1行的appendonly 为yes;然后appendfsync为always保证数据的安全

参考:

https://github.com/xetorthio/jedis
https://redis.io/
https://redis.io/documentation
http://www.redis.cn/commands.html
https://www.imooc.com/learn/839

    原文作者:fungi8
    原文地址: https://www.jianshu.com/p/50548aa73055
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞