前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【分布式架构之旅】Redis入门

【分布式架构之旅】Redis入门

作者头像
用户2032165
发布2018-06-05 18:22:26
6150
发布2018-06-05 18:22:26
举报
文章被收录于专栏:cmazxiaoma的架构师之路
  • 易扩展
  • 灵活的数据模型
  • 高可用
  • 大数据量,高性能

Redis的概述

  • 高性能键值对数据库,支持的键值数据类型:
代码语言:txt
复制
- 字符串类型 - `String`
- 列表类型 - `Set`
- 有序集合类型 - `Sorted Set`
- 散列类型 - `Hash`
- 集合类型 - `List`
代码语言:txt
复制
- 缓存
- 任务队列
- 网站访问统计
- 应用排行榜
- 分布式集群架构中的session分离

Redis在Linux上的使用

可以看我这篇文章【Linux学习】 Redis常用的一些指令


Jedis的入门

  • 我们要在Java平台上使用redis,肯定需要Jedis这个客户端。首先在pom文件中引入Jedis的依赖
代码语言:javascript
复制
        <!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
  • 普通方式创建Jedis对象。
代码语言:javascript
复制
    public void methodOne() {
        Jedis jedis = new Jedis("100.64.84.47", 6379);
        jedis.set("name", "cmazxiaoma");
        String value = jedis.get("name");
        System.out.println(value);
        jedis.close();
    }
  • 通过线程安全的连接池来创建Jedis对象。
代码语言:javascript
复制
  public void methodTwo() {
        //获得连接池的配置对象
        JedisPoolConfig config = new JedisPoolConfig();
        //设置最大连接数
        config.setMaxTotal(30);
        //设置最大空闲连接数
        config.setMaxIdle(10);
        //获得连接池
        JedisPool jedisPool = new JedisPool(config, "100.64.84.47", 6379);

        Jedis jedis = null;

        try {
            jedis = jedisPool.getResource();
            String value = jedis.get("name");
            System.out.println(value);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (jedis != null) {
                jedis.close();
            }

            jedisPool.close();
        }
    }
}
  • 编写测试类。
代码语言:javascript
复制
public class JedisDemo1Test {
    private JedisDemo1 demo;

    @Before
    public void setUp() {
        demo = new JedisDemo1();
    }

    @Test
    public void methodOne() throws Exception {
        demo.methodOne();
    }

    @Test
    public void methodTwo() throws Exception {
        demo.methodTwo();
    }

}
  • 运行Test Case,测试成功。

image.png

  • 我们在Xshell软件,输入get name指令,也可以看到输出cmazxiaoma

image.png


Redis的数据结构

String
  • Key定义的注意点:
代码语言:txt
复制
- 不要过长。
- 不要过短。
- 统一的命名规范。存储
代码语言:txt
复制
- 二进制安全的,存入和获取的数据相同。
-  `Value`最多可以容纳的数据长度是`512M`。存储
代码语言:txt
复制
-  赋值

image.png

代码语言:txt
复制
-  取值

image.png

代码语言:txt
复制
-  删除

image.png

代码语言:txt
复制
- 数值增减

如果属性不存在的话,那么integer类型默认为0

image.png

如果name属性的值不能转换成integer类型,那么会抛出ERR is not an integer or out of range异常。

image.png

decr指令也是一样的。

image.png

  • 扩展命令 incrbydecrby也是一样的,很简单。

image.png

append指令可以拼接字符串。

image.png

如果append key cmazxiaoma。这个key不存在的话,首先会创建这个key,然后存入cmazxiaoma内容,接着输出cmazxiaoma

image.png


Hash
  • 赋值,可以使用hset myhash key value单一赋值、hmset myhash key value key value多次赋值。

image.png

  • 取值,可以用hget myhash key单一取值、hmget myhash key key 多个取值、hgetall取出所有key所对应的值。

image.png

  • 删除 ,可以用hdel myhash key删除单一的key

image.png

hdel myhash key key删除多个的key

image.png

del myhash删除myhash中所有的key

image.png

  • 数值增减,hincrby myhash key 100

image.png

  • 使用hexists myhash key 判断key是否在myhash中存在,存在返回1,不存在返回0

image.png

  • hlen myhash获取myhash中存在key的数量。

image.png

  • hkeys myhash获取myhash中所有的key

image.png

  • hvals myhash获取myhash中所有的values

image.png


List
  • 存储list:
代码语言:txt
复制
-  `ArrayList`使用数组方式
-  `LinkedList`使用双向链表方式两端添加
代码语言:txt
复制
- 使用`lpush a b c` 命令在左端添加,那么`c`肯定是在最左端。

image.png

代码语言:txt
复制
- 使用`rpush a b c`命令在右端添加,那么`c`肯定是在最右端。

image.png

  • 两端弹出
代码语言:txt
复制
- 使用`lpop mylist`弹出`mylist`中头部元素、`rpop mylist2`弹出`mylist2`尾部中的元素。它们都是`3`。

image.png

代码语言:txt
复制
- 我们接着来查看`mylist`、`mylist2`。

image.png

  • 查看列表
    • 使用lrange mylist 0 5来查看mylist列表,mylist插入的方式从头结点开始添加的,那么输出肯定是321abc

image.png

代码语言:txt
复制
- 使用`lrange mylist2 0 5`查看`mylist2`列表,`mylist2`插入的方式是从最右端添加的,那么输出肯定是`abc123`

image.png

image.png

  • 获取列表元素的个数
代码语言:txt
复制
- 使用`llen mylist`命令

image.png

  • 扩展命令
代码语言:txt
复制
-  使用`lpushx mylist x`,使插入的元素在头部位置。

image.png

代码语言:txt
复制
-  使用`rpushx mylist x`,使插入的元素在尾部位置。

image.png

代码语言:txt
复制
-  使用`lrem mylist count element`,`count`代表是删除的次数,`element`代表是需要删除的元素。如果`count > 0` 代表删除的方式从头到尾,删除`count`个`element`,`count < 0`代表删除的方式从尾到头,删除`count`个`element`。如果`count = 0`,删除`mylist`中所有和`element`相同的元素。

image.png

image.png

代码语言:txt
复制
-  `lrem mylist 2 test1`

image.png

代码语言:txt
复制
-  `lrem mylist -2 test1`

image.png

代码语言:txt
复制
-  `lrem mylist 0 cmazxiaoma`

image.png

代码语言:txt
复制
-  在某一个下标位置插入元素。`lset mylist index element`

image.png

代码语言:txt
复制
-  在目标元素之前插入指定的元素。`linsert mylist before helloworl before_helloworld`

image.png

image.png

代码语言:txt
复制
-  在目标元素之后插入指定的元素。`linsert mylist helloworld after after_helloworld`

image.png

代码语言:txt
复制
-  弹出`mylist`中最后一个元素,并插入到`mylist`中的头部。`rpoplpush mylist mylist`

image.png

代码语言:txt
复制
-  `rpoplpush`使用场景

image.png


Set

List类型不同的是,Set集合中不允许出现重复的元素。

  • 添加/删除元素
    • 添加 sadd myset a b c,如果我们重复添加相同的元素,肯定是不成功的。比如sadd myset a

image.png

代码语言:txt
复制
- 删除 `srem myset a`,删除`myset`中的`a`元素。

image.png

代码语言:txt
复制
- 查看`myset`中的元素。`smembers myset`

image.png

代码语言:txt
复制
- 查看指定元素是否是`myset`中的成员。`sismember myset a`,返回`0`代表不存在,返回`1`代表存在。

image.png

  • 获得集合中的元素, smembers myset
  • 集合中的差集运算,sdiff myset2 mysetmyset2中元素有b,c,dmyset中元素有b,c。它们之间的差集运算结果应该为d

image.png

代码语言:txt
复制
-  集合中的交集运算,`sinter myset2 myset`,应该输出`cb`。

image.png

代码语言:txt
复制
-  集合中的并集运算,`sunion myset2 myse`t,应该输出`cbd`。

image.png

  • 扩展命令
代码语言:txt
复制
-  `scard myset` 查看`myset`有多少个元素。

image.png

代码语言:txt
复制
-  `srandmember myset` 随机返回`myset`中的一个元素。

image.png

代码语言:txt
复制
-  `sdiffstore new_myset myset2 myset` 把`myset`和`myset2`差集元素的结果存储到`new_myset`中。(`sinterstore`, `sunionstore`也是一样的用法)

image.png

  • Set使用场景
代码语言:txt
复制
- 跟踪一些唯一性的数据。
- 用于维护数据对象之间的关联关系。

SortedSet

SortedSet中的成员在集合中的位置是有序的。

  • 添加元素 zadd mysort 70 cmazxiaoma 80 xiaoma 100 doudou

image.png

  • 获得元素
代码语言:txt
复制
-  `zcard mysort` 获得`mysort`中所有元素的个数

image.png

代码语言:txt
复制
-  获得`mysort`中`name`为`cmazxiaoma`对应的成绩。`zscore mysort cmazxiaoma`

image.png

  • 删除元素,zrem mysort cmazxiaoma deli doudou xiaoma

image.png

  • 范围查询 zrange mysort 0 -1,输出的key是按成绩正序排列。

image.png

代码语言:txt
复制
-  如果输出的数据项要带上成绩的话,指令应该是`zrange mysort 0 -1 withscores`

image.png

代码语言:txt
复制
-  如果输出的数据项想按成绩逆序排序,那么就应该`zrevrange mysort 0 -1 withscores`

image.png

代码语言:txt
复制
-  如果想按排名范围进行删除的话,那么应该`zremrangebyrank mysort 0 2`

image.png

代码语言:txt
复制
-  如果想按成绩范围进行删除的话,那么应该`zremrangebyscore mysort 0 10`。顾名思义删除成绩在`0-10`之内的数据项。

image.png

  • 扩展命令
代码语言:txt
复制
-  查看分数在`0-10`之内的学生信息,`zrangebyscore mysort 0 10 withscores`

image.png

代码语言:txt
复制
-  查看分数在`0-100`之内且在第`1`行-第`2`行的学生信息。`zrangebyscore mysort 0 100 withiscores limit 0 2`

image.png

代码语言:txt
复制
-  给`cmazxiaoma`的成绩加`100`分。`zincrby mysort cmazxiaoma 100`

image.png

代码语言:txt
复制
-  查看成绩`0-10`之间的学生的个数。`zcount mysort 0 10`

image.png

  • Sorted Set使用场景
代码语言:txt
复制
- 如大型在线游戏积分排行榜
- 构建索引数据

Redis中的通用命令

  • key * 获取所有redis中的key

image.png

  • keys my* 获取所有redis中以my开头的key

image.png

  • exists mylist 查看redis中是否存在mylist,0代表不存在,1代表存在。

image.png

  • rename name new_name 给名字为name的数据结构重命名为new_name

image.png

  • expire new_name 10 设置redisnew_name过期时间,通过ttl new_name看到其距离过期的时间。

image.png

  • type mylist,可以查看mylist对应的数据结构类型。

image.png


Redis的事务

  • Redis相关的特性:
代码语言:txt
复制
- 多数据库
- `Redis`事务一个

image.png

  • 我们想把第0号的数据库中某些key移动到第1号数据库里面,那么我们该怎么做呢。通过move cmazxiaoma_test_mayday_5 1就可以完成。

image.png

  • 我们可以通过multiexecdiscard来完成事务操作。事务执行期间,Redis不会为其他客户端提供任何服务,以保证事务中的所有命令原子执行。multi相当于开启事务,exec相当于提交,discard相当于回滚。
  • 首先我们在第一个客户端进行如下操作。我们在第一个客户端开启了事务,在事务中我们incr num 2次,按理来说,get num 应该等于4

redis第一个客户端.png

  • 我们在第二个客户端输入get num,发现num还是2。那么证明了我们的结论:事务执行期间,Redis不会为其他客户端提供任何服务,以保证事务中的所有命令原子执行。

image.png

  • 如果我们在第一个客户端提交了事务。

image.png

  • 接着我们在第二个客户端get num,发现可以num的值得到了更新。

image.png

  • 我们可以演示一下回滚操作,首先set user cmazxiaoma,接着开启事务,在事务中set user xiaoma,然后进行回滚操作,发现 get user 依然是cmazxiaoma

image.png


Redis的持久化

Redis的性能体现在它把数据都保存在内存当中。我们把内存中的数据同步到硬盘当中的操作称之为持久化。

  • Redis持久化方式:
代码语言:txt
复制
- `RDB`方式,在指定的时间内,把内存中的数据快照写入到硬盘当中。
- `AOF`方式,将以日志的形式记录服务器所处理的每一个操作。当`Redis`服务器启动之初,它会读取该`aof`文件,会重新构建我们的数据库。保证我们启动之后,保证数据的完整性。
- 无持久化,我们可以通过配置禁止`Redis`服务器的持久化,我们认为`Redis`就是缓存的一种机制了。
- 同时使用。
代码语言:txt
复制
- 默认情况下,每隔一段时间`redis`服务器程序会自动对数据库做一次遍历,把内存快照写在一个叫做`"dump.rdb"`的文件里,这个持久化机制叫做`SNAPSHOT`。有了`SNAPSHOT`后,如果服务器宕机,重新启动`redis`服务器时,`redis`会自动加载`"dump.rdb"`,将数据库状态恢复上一次`SNAPSHOT`的状态。
- `Redis`服务器初始化过程中,设定了定时时间,每隔一段时间就会触发持久化操作,进入定时事件处理程序中,就会`fork`出子进程来进行持久化操作。
- `Redis`服务器预设了`save`指令,客户端可要求服务器进程中断服务,执行持久化操作。
-  我们可以通过`vim /etc/redis.conf`打开配置文件,可以看到以下配置。

image.png

代码语言:txt
复制
-  同时我们还可以看到内存快照输出在`file`文件名。

image.png

优缺点:

代码语言:txt
复制
- 如果数据集很大,`RDB`相对于`AOF`启动效率很更高。
- 如果想保证数据的高可用性,最大限度的避免数据的丢失,`RDB`将不是一个好的选择。因为系统在定时持久化操作之前,还没来得及在硬盘写入数据就发生宕机的话,就造成了数据的丢失。
- `RDB`通过`fork`出子线程来完成数据持久化操作,如果当数据集很大的时候,可能会导致服务器停止几百`ms`,或者几`s`。

RDB.png

  • AOF(append only file):
  • 对于Redis服务器而言,其缺省的机制是RDB,如果需要使用AOF,则需要修改appendonly no改成appendonly yesRedis在每一次收到数据修改的命令之后,都会将其追加到AOF文件中。在Redis下一次重新启动时,需要加载AOF文件中的信息来构建最新的数据到内存中。

image.png

image.png

  • 可以记录服务器的所有写操作。在服务器重新启动时,会把所有的写操作重新执行一遍从而实现数据的备份。当写操作集过大(比原有的数据集还大),Redis会重写写操作集。
  • 带来更好的数据安全性,有3种同步策略,每秒同步,每修改同步,不同步。 每秒同步也是异步完成的,效率也非常高。缺点是一旦系统发生宕机的现象,那么这一秒中的修改的数据就会发生丢失。每修改同步,我们可以视为同步持久化。每一次发生数据的变化,就会立即的记录在磁盘,这种效率很低,但是很安全。
  • 采用append追加的模式,就算系统发生宕机,也不会影响我们日志文件中已经存在的内容。然而我们本次操作中,只写入了一半数据就出现了系统崩溃的问题。在Redis下一次启动之前,我们可以通过"redis-check-aof --fix <filename>"命令来修复坏损的AOF文件,解决数据一致性的问题。
  • 对于相同数量的数据集而言,AOF文件通常要大于RDB文件。
  • AOF在运行效率上往往会慢于RDB

AOF.png

  • RDBAOF的区别 前者是保存了数据本身,而后者是记录了数据的变更。

尾言

这篇文章最后在网吧完成的,勿以善小而不为。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.12.04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • NoSQL概述
  • Redis的概述
  • Redis在Linux上的使用
  • Jedis的入门
  • Redis的数据结构
    • String
      • Hash
        • List
          • Set
            • SortedSet
            • Redis中的通用命令
            • Redis的事务
            • Redis的持久化
            • 尾言
            相关产品与服务
            云数据库 Redis
            腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档