评论

收藏

[NoSQL] redis 小白入门及深入讲解

数据库 数据库 发布于:2021-07-07 15:21 | 阅读数:548 | 评论:0

  
  文章目录

  • 一.Redis 介绍


    • 一.简介
    • 二.发展历史

  • 二.Redis 的安装与配置
  • 三.Redis 命令
  • 四.Redis 发布订阅模式
  • 五.Redis 事务操作
  • 六.Redis 性能测试
  • 七.Redis 连接以及通信原理
  • 八.Java 操作 Redis
  • 九.Redis 其他进阶操作


  
Redis 官网  Redis 中国官网
  Redis 官网在线测试
一.Redis 介绍
一.简介
  Remote Directory Server(Redis)是一个开源的使用 ANSI C 语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言 API 的一个高性能的支持主从同步的 Key-Value 存储系统。通常被称为数据结构服务器,因为其支持的类型有:String,Hash,list,set,sorted set
  feature

  • key-value 形式存储
  • 支持数据持久化,可以将内存中数据保存在磁盘中,重启的时候可以再次加载进行使用
  • 不仅仅支持简单的键值对类型的数据,同时还支持数据结构类型的存储(ist,set 等)
  • 支持数据的备份,及 master-slave(主从模式)的数据备份
  • 性能极高,read 11w 次/s,write 8w1k 次/s
  • 支持数据类型丰富
  • 所有操作皆为原子性,要么成功执行,要么失败完全不执行,单个操作是原子性,多个操作也支持事务,通过multi,exec 指令包起来
  • 还支持 publish/subscribe,通知 key 过期等特性

二.发展历史
  08 年的时候,意大利一家创业公司 Merzia 推出了一款基于 MySQL 的网站实时统计系统 LLOOGG,可是不久后该公司创始人 Salvatore Sanfilippo 便对 MySQL 的性能感到失望,于是他决定为 LLOOGG 系统量身打造一个数据库,并于 09 完成,这个数据库实际上就是 Redis 的前身,之后这个创始人不满足将这个数据库仅仅用于 LLOOGG,于是 Redis 开源了,并开始和 Redis 的另一名主要的代码贡献者 Pieter noordhuis 一起继续着 Redis 的开发直到如今。10 年的时候 VMware 开始赞助 Redis 的开发,Salvatore 和 Pieter 也于同年陆续加入 VMware 全职开发 Redis
二.Redis 的安装与配置  Redis Github 下载地址

  •   windows 安装以及配置:
      简单下载下来就行了,其支持 64 位或 32 位,可以配置 redis 目录的环境变量,方便命令启动
  •   linux 安装以及配置:
      如下载 2.8.17 压缩包并解压安装
    $ wget http://download.redis.io/releases/redis-2.8.17.tar.gz
    $ tar xzf redis-2.8.17.tar.gz
    $ cd redis-2.8.17
    $ make
      之后 redis-2.8.17 目录下会出现 redis 的相关程序,具体位于安装目录下的 src 下
  redis.conf 是 redis 默认配置文件
三.Redis 命令

  •   redis 最常规的命令

    •   windows 启动命令(启用默认的)
      redis-server.exe redis.windows.conf
    •   windows 启动命令(不启用默认的)
      redis-server.exe
    •   linux 启动命令(启用默认的)(先进入 redis 的 src 目录中)
      $ cd src
      $ ./redis-server ../redis.conf
    •   linux 启动命令(不启用默认的)(先进入 redis 的 src 目录中)
      $ cd src
      $ ./redis-server
    •   windows 设置键值对并取出键值(需要打开另一个 cmd)
      redis-cli.exe -h 127.0.0.1 -p 6379
      set myKey lalala
      get myKey
    •   linux 设置键值对并取出键值
      $ cd src
      $ ./redis-cli
      redis> set myKey lalala
      OK
      redis> get myKey
      "lalala"
    •   删除 key
      redis 127.0.0.1:6379> DEL myKey

  •   redis.conf(linux)或者 redis.windows.conf(windows)可以用 CONFIG 命令查看设置

    •   查看获取所有配置项
      redis 127.0.0.1:6379> CONFIG GET *
    •   修改配置并查看(直接是下面命令或者直接去改配置文件),如修改 loglevel 配置
      redis 127.0.0.1:6379> CONFIG SET loglevel "notice"
      OK
      redis 127.0.0.1:6379> CONFIG GET loglevel
        关于此配置文件中的参数说明,可以详见这里

  •   Hash 存储
    "Hash 存储"
    redis 127.0.0.1:6379> HMSET myHash field1 "lalala" field2 "gagaga"
    "OK"
    redis 127.0.0.1:6379> HGET myHash field2
    "gagaga"
  •   List 列表存储
    "List 存储(先从左边插再从右边插并显示)"
    redis 127.0.0.1:6379> lpush myList1 myValue3 myValue2 myValue1
    redis 127.0.0.1:6379> lrange myList1 0 2
    "myValue1" "myValue2" "myValue3"
    redis 127.0.0.1:6379> rpush myList2 myValue1 myValue2 myValue3
    redis 127.0.0.1:6379> rrange myList2 0 2
    "myValue1" "myValue2" "myValue3"
  •   Set 集合
      集合内元素具有唯一性
    "Set 存储(Set 集合不存在会返回错误,若元素存在于 Set 集合中则返回 0 ,不存在 Set 集合中则返回 1)"
    redis 127.0.0.1:6379> sadd mySet myValue1 myValue2 myValue2 myValue3
    redis 127.0.0.1:6379> smembers mySet
    "myValue1" "myValue2" "myValue3"
  •   ZSet 有序集(Sorted Set)
      ZSet 和 Set 一样也是 String 类型的元素集合,且不允许重复,不同的是每个元素都会关联一个 double 类型的分数,redis 正是通过该分数来为集合中成员进行从小到大的排序
    "ZAset 存数据"
    redis 127.0.0.1:6379> zadd myZSet 0 myValue1 1 myValue2 2 myValue3
    redis 127.0.0.1:6379> ZRANGEBYSCORE myZSet 0 2
  •   客户端启动

    •   连接本地 redis 服务
      $ redis-cli
      redis 127.0.0.1:6379>
      redis 127.0.0.1:6379> PING
    •   连接远程 redis 服务
      $ redis-cli -h 127.0.0.1 -p 6379 -a "123456"
      redis 127.0.0.1:6379>
      redis 127.0.0.1:6379> PING
        redis-cli --raw可以有效的避免中文乱码

  •   各种键命令
    "删除 key"
    DEL key
    "序列化给定 key 并返回序列化的值"
    DUMP key
    "检查给定 key 是否存在"
    EXISTS key
    "为给定 key 设置过期时间"
    EXPIRE key seconds
    "为给定 key 设置 unix 类型时间戳的多去时间"
    EXPIREAT key timestamp
    "查找所有给定模式的 key"
    KEYS pattern
    "将当前数据库的 key 移动到给定数据库 db 中"
    MOVE key db
    "移除 key 的过期时间"
    PERSIST key
    "以 ms 为单位返回 key 的剩余过期时间"
    PTTL key
    "以 s 为单位返回 key 的剩余过期时间"
    TTL key
    "从当前数据库中随机返回一个 key"
    RANDOMKEY
    "修改 key 的名称"
    RENAME key newkey
    "仅当 newkey 不存在时候,才能将 key 改为 newkey"
    RENAMENX key newkey
    "返回 key 所存储的值的类型"
    TYPE key
四.Redis 发布订阅模式

  •   具体业务场景

    •   异步消息通知场景(实际大多接口用回调通知,因为用Redis发布订阅限制条件苛刻,系统间必须共用一套Redis)
        比如渠道在调支付平台的时候,我们可以用回调的方式给支付平台一个我们的回调接口来通知我们支付状态,还可以利用Redis的发布订阅来实现。比如我们发起支付的同时订阅频道pay_notice_ + wk (假如我们的渠道标识是wk,不能让其他渠道也订阅这个频道),当支付平台处理完成后,支付平台往该频道发布消息,告诉频道的订阅者该订单的支付信息及状态。收到消息后,根据消息内容更新订单信息及后续操作。
        当很多人都调用支付平台时,支付时都去订阅同一个频道会有问题。比如用户A支付完订阅频道pay_notice_wk,在支付平台未处理完时,用户B支付完也订阅了pay_notice_wk,当A收到通知后,接着B的支付通知也发布了,这时渠道收不到第二次消息发布。因为同一个频道收到消息后,订阅自动取消,也就是订阅是一次性的。
        所以我们订阅的订单支付状态的频道就得唯一,一个订单一个频道,我们可以在频道上加上订单号pay_notice_wk+orderNo保证频道唯一。这样我们可以把频道号在支付时当做参数一并传过去,支付平台处理完就可以用此频道发布消息给我们了。(实际大多接口用回调通知,因为用Redis发布订阅限制条件苛刻,系统间必须共用一套Redis)
        调用支付接口
        订阅频道
        发布支付结果给 Redis 频道
        将消息发给关注者
        订单系统
        支付系统
        redis

        
    •   任务通知场景
        如系统跑批完成后通知指定的用户
        订阅Redis频道
        运行完成发布消息到频道
        用户系统收到消息
        用户系统
        Redis
        跑批系统

        
    •   参数刷新加载场景
        我们使用 Redis 无非是将系统中不怎么变动的,查询比较麻烦的数据给缓存起来,如系统首页轮播图,页面动态链接,一些系统参数,公共数据可以加载到 Redis 中,然后再有个后台管理系统去配置修改这些数据
        如轮播图要增加一个图片,我们可以在后台系统中去加上,这样就完了吗?不,此时后台系统中加上了图片,但是 Redis 中还是老数据,要想 Redis 中的数据立即刷新成后台系统中的新数据,可以用到 Redis 的发布订阅机制来做到
        订阅频道
        后台修改数据
        发布消息给指定频道
        消息传给关注者
        用户系统
        Redis
        后台系统
        刷新或者点确认
        

  •   实际命令演示

    •   开两个 redis-cli 先创建可订阅的频道 redisChat 并订阅它

      •   redis-cli 1(消息订阅者 1)
        redis 127.0.0.1:6379> SUBSCRIBE redisChat
        redis 127.0.0.1:6379> PSUBSCRIBE redisChannel*
      •   redis-cli 2(消息订阅者 2)
        redis 127.0.0.1:6379> SUBSCRIBE redisChat
        redis 127.0.0.1:6379> PSUBSCRIBE redisChannel*

    •   开第三个 redis-cli 用于发布信息到 redisChat 频道上

      •   redis-cli 3(消息发布者)
        publish redisChat '您有一条新信息'
        publish redisChannelllll '您又有一条新信息'

    这个时候前面的两个消息订阅者可以收到”您有一条新信息“,还可以收到”您又有一条新信息“
  •   C 源码分析

    •   pubsub_channels
      DSC0000.jpeg

        源码中有个 pubsub.c文件,此文件中redisServer这个机构中有个数据结构是dict *pubsub_channels,key 为 channel 即订阅的频道, value 是一个 list 存放的是订阅者 client,这个 list 就是这个list *pubsub_patterns结构
    •   pubsubSubscribeChannel 与 subscribeCommand
        subscribe 原理很简单,就是创建一个频道,然后将当前 client 插入到这个频道(key)对应的 client 队列中
      DSC0001.jpeg

    •   pubsubPublishMessage 与 publishCommand
        publish 命令原理很简单,即找到字典中频道 key 对应的 value,也就是 client 队列,遍历这个队列给 client 发送消息
      DSC0002.png


五.Redis 事务操作  单个 redis 命令执行时原子性的,但是 redis 没有在事务上增加任何维持原子性的机制,所以 redis 事务的执行不是原子性的,事务可以理解成一个打包的批量执行脚本,但是批量指令并非原子化操作,中间即使某条指令失败了,也并不会导致前面指令进行回滚,也不会造成后续指令不去执行

  •   redis 事务可以一次执行多个命令,并且可以保证:

    • 批量操作在发送 EXEC 命令前被放入队列缓存。
    • 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败了,其余命令依然被执行。
    • 在事务执行过程中,其他客户端提交的命令请求不会插入到事务执行命令中去。

  •   redis 事务执行 3 个必经阶段:

    • 开始事务
    • 命令入队
    • 执行事务

  •   事务操作命令实例
    "MULTI 用于开始一个事务"
    redis 127.0.0.1:6379> MULTI
    OK
    "一系列事务操作添加到队里中"
    redis 127.0.0.1:6379> SET name "LiMing"
    QUEUED
    redis 127.0.0.1:6379> GET name
    QUEUED
    redis 127.0.0.1:6379> SADD tag "a" "b" "c"
    QUEUED
    redis 127.0.0.1:6379>SMEMBERS tag
    QUEUED
    "通过 EXEC 来触发事务"
    redis 127.0.0.1:6379> EXEC
  •   其他事务操作命令
    "取消事务,放弃执行事务块内的所有命令"
    DISCARD
    "监视一个或多个 key"
    WATCH key [key ...]
    "取消 WATCH 命令对所有 key 的监视"
    UNWATCH
六.Redis 性能测试  此测试是在 redis 目录下执行,而不是 redis 客户端内部指令,下面会同时执行 10000 个 请求 来检测性能
$ redis-benchmark -n 10000 -q
序号选项描述默认值1-h指定服务器主机名127.0.0.12-p指定服务器端口63793-s指定服务器 socket 4-c指定并发连接数505-n指定请求数100006-d以字节的形式指定 SET/GET 值的数据大小27-k1=keep alive 0=reconnect18-rSET/GET/INCR 使用随机 key, SADD 使用随机值 9-P通过管道传输 请求110-q强制退出 redis。仅显示 query/sec 值 11–csv以 CSV 格式输出 12-l生成循环,永久执行测试 13-t仅运行以逗号分隔的测试命令列表。 14-IIdle 模式。仅打开 N 个 idle 连接并等待。 七.Redis 连接以及通信原理

  •   连接原理:

    •   原理概述
        redis 通过监听一个 TCP 端口或者 UNIX socket 的方式来接收来自客户端的连接,当一个连接建立之后,redis 内部会进行一下一些操作:

      • 首先,客户端的 socket 会被设置成非阻塞态,因为 redis 在网络事件处理上采用非阻塞多路复用模型
      • 然后,为这个 socket 设置 TCP_NODELAY 属性,禁用 Nagle 算法
      • 最后,创建一个可读的文件事件用于监听这个客户端 socket 的数据发送

    •   最大连接数
        最大连接数 maxclients 默认值是 10000,可在 redis.conf 中进行修改
    •   客户端命令
      S.N.命令描述1CLIENT LIST返回连接到 redis 服务的客户端列表2CLIENT SETNAME设置当前连接的名称3CLIENT GETNAME获取通过 CLIENT SETNAME 命令设置的服务名称4CLIENT PAUSE挂起客户端连接,指定挂起的时间以毫秒计5CLIENT KILL关闭客户端连接

  •   管道技术:
      redis 是一种基于 client-server 模型以及请求响应协议的 tcp 服务,也就是说一个请求会遵循一下几步:client 先向 server 发送一个查询,client 同时监听 socket 返回,以阻塞模式等待服务器响应,服务器处理命令并将结果返回给客户端。redis 管道可以在 server 未响应时,client 可以继续向 server 发送请求,并最终一次性读取所有 server 的响应。管道技术显著提升了 redis 服务的性能
八.Java 操作 Redis

  •   前置条件
      已经安装了 redis 服务和 java redis 驱动(jedis.jar)
  •   连接 redis 服务的 java 代码
    public class RedisJava{
      public static void main(String[] args){
        //连接本地 redis 服务
        Jedis jedis = new Jedis("127.0.0.1");
        System.out.println("连接成功");
        //查看服务是否运行
        System.out.println("服务正在运行:" + jedis.ping());
      }
    }
  •   redis 存取操作
    public class RedisJava{
      public static void main(String[] args){
        /* ========= 连接 redis ========= */
        Jedis jedis = new Jedis("127.0.0.1");
        System.out.println("连接成功");
        /* ========= String 存取 ========= */
        jedis.set("string", "字符串");
        System.out.println("redis 存储的字符串是:" + jedis.get("string"));
        /* ========= list 存取 ========= */
        jedis.lpush("list", "表数据1");
        jedis.lpush("list", "表数据2");
        jedis.lpush("list", "表数据3");
        List<String> list = jedis.lrange("list", "0", "2");
        for(String str : list){
          System.out.println("列表数据为:" + str);
        }
        /* ========= keys 读取 ========= */
        Set<String> keys = jedis.keys("*");
        Iterator<String> it = keys.iterator();
        while(it.hasNext()){
          String key = it.next();
          System.out.println(key);
        }
      }
    }
九.Redis 其他进阶操作

  •   数据备份以及恢复

    •   备份当前数据库
      redis 127.0.0.1:6379> SAVE
    •   将之前产生的备份文件 dump.rdb 移动到 redis 安装目录并启动服务即可
    •   在后台备份
      redis 127.0.0.1:6379> BGSave

  •   连接服务密码查看及修改

    •   查看是否设置了密码验证(默认情况这个参数里头是空的,意味无需通过密码验证直接可连接到 redis 服务)
      127.0.0.1:6379> CONFIG get requirepass
    •   修改密码
      127.0.0.1:6379> CONFIG set requirepass "123456"
    •   身份认证
      127.0.0.1:6379> AUTH "123456"
      OK

  •   redis 分区结构

    •   意义
        通过多态计算机允许创造更大的数据库,拓展计算能力。涉及到多个 key 的操作是不被支持的,使用分区时,数据处理会变的复杂
    •   分区理性

      •   范围分区
          映射一定范围的对象到特定的 redis 实例中。如 ID 0~10000 的用户会保存到 R0,10001~20000 的用户保存到 R1
      •   哈希分区
          这对任何 key 都适用,用一个 hash 函数将 key转换成一个数字,对这个整数取模,可以将其转化成 0~3 之间的数字(若存在 4 个分区),这样就可以存在指定的一个分区中了



  

  
关注下面的标签,发现更多相似文章