当前位置 博文首页 > 平遥:Redis学习笔记

    平遥:Redis学习笔记

    作者:平遥 时间:2021-05-05 18:15

    目录
    • Redis
      • NoSQL
        • NoSQL的四大分类
      • Redis入门
        • 概述
        • Windows安装
        • Linux安装
        • 性能测试
        • 基础的知识
      • 五大数据类型
        • String(字符串)
        • List(列表)
        • Set(集合)
        • Hash(哈希)
        • Zset(有序集合)
      • 三种特殊数据类型
        • Geospatial(地理位置)
        • Hyperloglog
        • Bitmap
      • 事务
      • Jedis
        • 常用API
      • SpringBoot整合
      • Redis.conf详解
      • Redis持久化
        • RDB(Redis DataBase)
        • AOF(Append Only File)
      • Redis发布订阅
        • Redis 发布订阅命令
      • Redis主从复制
        • 环境配置
        • 一主二从
        • 哨兵模式
      • Redis缓存穿透和雪崩
        • 缓存穿透(查不到)
        • 缓存击穿(量太大,缓存过期)
        • 缓存雪崩

    Redis

    REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。

    Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

    它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。

    NoSQL

    Redis:nosql(非关系型数据库)。

    NoSQL演变史参考:https://www.cnblogs.com/lukelook/p/11135209.html

    NoSQL 概述
    NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,
    泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题,包括超大规模数据的存储。

    (例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。

    MySQL的扩展性瓶颈:MySQL数据库也经常存储一些大文本字段,导致数据库表非常的大,在做数据库恢复的时候就导致非常的慢,不容易快速恢复数据库。比如1000万4KB大小的文本就接近40GB的大小,如果能把这些数据从MySQL省去,MySQL将变得非常的小。关系数据库很强大,但是它并不能很好的应付所有的应用场景。MySQL的扩展性差(需要复杂的技术来实现),大数据下IO压力大,表结构更改困难,正是当前使用MySQL的开发人员面临的问题。

    NoSQL代表:MongDB、 Redis、Memcache

    NoSQL特点:解耦!

    1. 方便拓展(数据之间没有关系,很好拓展!)

    2. 大数据量高性能(redis一秒读11完次,一秒写8完次,NoSQL是缓存记录级。是一种细粒度的缓存,性能比较高)

    3. 数据类型是多样的(不需要实现设计数据库,随取随用)

    4. 传统的RDBMS和NoSQL

      传统的RDBMS
      -结构化组织
      -SQL
      -数据和关系都存在单独的表中
      -操作数据,数据定义语言
      -严格的一致性
      -...
      
      NoSQL
      -不仅仅是数据
      -没有固定的查询语言
      -键值对存储,列存储,文档存储,图数据库
      -最终一致性
      -CAP定理和BASE理论(异地多活)
      -高性能,高可用,高扩展
      -...
      

    NoSQL的四大分类

    KV键值对:

    • 新浪:Redis
    • 美团:Redis+Tair
    • 阿里,百度:Redis + memcache

    文档型数据库(bson格式 和json一样)

    • MongoDB
      • MongoDB是一个基于分布式文件存储的数据库,C++编写,主要用于处理大量的文档。
      • MongoDB是一个基于关系型数据库和非关系型数据库中间的产品。MongoDB是非关系型数据库中最丰富,最像关系型数据库的。
    • ConthDB

    列存储数据库

    • HBase
    • 分布式文件系统

    图关系数据库

    • 放的是关系,不是图,比如朋友圈社交网络
    • Neo4j,infoGrid
    分类 Examples举例 典型应用场景 数据模型 优点 缺点
    键值(key-value)[3] Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB 内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统等等。[3] Key 指向 Value 的键值对,通常用hash table来实现[3] 查找速度快 数据无结构化,通常只被当作字符串或者二进制数据[3]
    列存储数据库[3] Cassandra, HBase, Riak 分布式的文件系统 以列簇式存储,将同一列数据存在一起 查找速度快,可扩展性强,更容易进行分布式扩展 功能相对局限
    文档型数据库[3] CouchDB, MongoDb Web应用(与Key-Value类似,Value是结构化的,不同的是数据库能够了解Value的内容) Key-Value对应的键值对,Value为结构化数据 数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构 查询性能不高,而且缺乏统一的查询语法。
    图形(Graph)数据库[3] Neo4J, InfoGrid, Infinite Graph 社交网络,推荐系统等。专注于构建关系图谱 图结构 利用图结构相关算法。比如最短路径寻址,N度关系查找等 很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群方案。[3]

    Redis入门

    概述

    Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

    redis与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

    免费,开源,是当下最热门的NoSQL技术之一,也被称之为结构化数据库。

    Redis能干什么:

    1. 内存存储,持久化,内存中是断电即失的,所以持久化非常重要(RDB,AOF)。
    2. 效率高,可以用于高速缓存。
    3. 发布订阅系统。
    4. 地图信息分析。
    5. 计时器,计数器(浏览量)。
    6. ...

    特点:

    1. 支持多种语言
    2. 持久化
    3. 集群
    4. 事务
    5. ...

    Redis中文网:https://www.redis.net.cn/

    Windows安装

    1. 下载安装包(github上)
    2. 解压压缩包
    3. 开启Redis,直接双击服务运行即可
    4. 使用Redis客户端来连接服务端(ping 测试连接,存值:set name zr,取值:get name)

    Windows下使用非常简单,但是Redis推荐我们使用Redis去开发使用。

    Linux安装

    1. 下载安装包(官网下载)

    2. 解压Redis的安装包到指定包

    3. 进入解压后的文件,可以看到Redis的配置文件(redis.conf)

    4. 环境安装

      [root@zhourui redis-6.0.9]# yum install gcc-c++
      
      [root@zhourui redis-6.0.9]# make
      
      make install
      

      再次make

      make install

    5. Redis的默认安装路径:/usr/local/bin

    6. 将redis的配置文件(redis.conf)复制到当前目录下

      [root@zhourui bin]# mkdir zconfig
      
      [root@zhourui bin]# cp /www/server/redis/redis-6.0.9/redis.conf zconfig/
      
      
    7. redis默认不是后台启动的,修改配置文件将 no 改为 yes

    8. 启动Redis服务,通过指定的配置文件启动服务

      [root@zhourui bin]# redis-server zconfig/redis.conf 
      
      
    9. 启动客户端redis-cli

      [root@zhourui bin]# redis-cli -p 6379
      127.0.0.1:6379> ping  #测试连接
      PONG
      127.0.0.1:6379> set name zr  #存值
      OK
      127.0.0.1:6379> get name  #取值
      "zr"
      127.0.0.1:6379> keys *  #查看所有的key
      1) "name"
      127.0.0.1:6379> 
      
      
    10. 查看redis的进程是否开启

    11. 关闭redis服务,在连接的客户端输入 shutdown

    12. 再次查看进程是否存在,ps -ef|grep redis

    13. 单机多redis修改端口即可

    性能测试

    redis-benchmark 是一个压力测试工具。

    官方自带的性能测试工具。

    redis-benchmark 命令参数!

    redis 性能测试工具可选参数如下所示:

    序号 选项 描述 默认值
    1 -h 指定服务器主机名 127.0.0.1
    2 -p 指定服务器端口 6379
    3 -s 指定服务器 socket
    4 -c 指定并发连接数 50
    5 -n 指定请求数 10000
    6 -d 以字节的形式指定 SET/GET 值的数据大小 2
    7 -k 1=keep alive 0=reconnect 1
    8 -r SET/GET/INCR 使用随机 key, SADD 使用随机值
    9 -P 通过管道传输 请求 1
    10 -q 强制退出 redis。仅显示 query/sec 值
    11 --csv 以 CSV 格式输出
    12 -l 生成循环,永久执行测试
    13 -t 仅运行以逗号分隔的测试命令列表。
    14 -I Idle 模式。仅打开 N 个 idle 连接并等待。

    测试:启动redis后新开一个窗口,执行

    # 测试:100个并发连接,100000个请求
    redis-benchmark -h localhost -p 6379 -c 100 -n 100000
    

    基础的知识

    redis默认有16个数据库(从 redis.conf 中可以看到)。

    默认使用的是第 0 个。

    可以使用 select 进行切换。

    flushdb:清空当前数据库,flushall:清空所有的数据库,dbsize :数据库的大小,keys * :查看所有的key。

    127.0.0.1:6379> select 3  #切换数据库
    OK
    127.0.0.1:6379[3]> dbsize
    (integer) 0
    127.0.0.1:6379[3]> set name zhou
    OK
    127.0.0.1:6379[3]> dbsize  #数据库的大小
    (integer) 1
    127.0.0.1:6379[3]> select 6
    OK
    127.0.0.1:6379[6]> dbsize
    (integer) 0
    127.0.0.1:6379[6]> get name
    (nil)
    127.0.0.1:6379[6]> select 3
    OK
    127.0.0.1:6379[3]> get name
    "zhou"
    127.0.0.1:6379[3]> flushdb  #清空数据库
    OK
    127.0.0.1:6379[3]> get name
    (nil)
    127.0.0.1:6379> flushall  #清空所有的数据库
    OK
    127.0.0.1:6379[3]> 
    
    

    Redis是单线程的!

    官方表示,Redis是基于内存操作的,CPU不是Redis的性能瓶颈,Redis的性能瓶颈是根据机器的内存和网络的带宽,既然可以使用单线程来实现,就使用单线程了。

    Redis是C语言写的,官方提供的数据100000+的QPS,这个完全不比同样是使用 key-value 的Memcache差!

    Redis是单线程为什么还这么快?

    误区1:认为高性能的服务器一定是多线程的.

    误区2:多线程(cpu会上下文切换)一定比单线程效率高。

    核心:Redis是将所有的数据放在内存中的,所以使用单线程去操作效率就是最高的,多线程(cpu会上下文切换,耗时的操作),对于内存系统来说没有上下文的切换效率就是最高的,多次读写都是在一个CPU上的,在内存情况下,这个就是最佳方案。

    五大数据类型

    Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库缓存消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

    Redis-Key

    127.0.0.1:6379> exists name  #判断键是否存在
    (integer) 1
    127.0.0.1:6379> move name 1  #移除1数据库的name键
    (integer) 1
    127.0.0.1:6379> set name zzrr
    OK
    127.0.0.1:6379> keys *  #查看所有的key
    1) "name"
    2) "age"
    127.0.0.1:6379> expire name 10  #设置key过期时间  单位是秒
    (integer) 1
    127.0.0.1:6379> keys *
    1) "name"
    2) "age"
    127.0.0.1:6379> ttl name  #查看当前key的剩余时间
    (integer) 6
    127.0.0.1:6379> ttl name
    (integer) 2
    127.0.0.1:6379> keys *
    1) "age"
    127.0.0.1:6379> type name  #查看当前key的类型
    string
    127.0.0.1:6379> type age
    string
    127.0.0.1:6379> 
    
    

    String(字符串)

    ###############################################################################
    127.0.0.1:6379> set name zr  #设置值
    OK
    127.0.0.1:6379> get name
    "zr"
    127.0.0.1:6379> keys *  #查看所有的key
    1) "name"
    127.0.0.1:6379> append name "hello"  #追加字符串,如果当前的key不存在,就相当于 set key
    (integer) 7
    127.0.0.1:6379> get name
    "zrhello"
    127.0.0.1:6379> strlen name  #查看字符串的长度
    (integer) 7
    127.0.0.1:6379> 
    
    ###############################################################################
    # 增量
    127.0.0.1:6379> set views 0  #初始值为0
    OK
    127.0.0.1:6379> get views  
    "0"
    127.0.0.1:6379> incr views  #自增1
    (integer) 1
    127.0.0.1:6379> incr views
    (integer) 2
    127.0.0.1:6379> get views  
    "2"
    127.0.0.1:6379> 
    127.0.0.1:6379> decr views  #自减1
    (integer) 1
    127.0.0.1:6379> get views
    "1"
    127.0.0.1:6379> incrby views 10  #设置步长,指定增量
    (integer) 11
    127.0.0.1:6379> decrby views 10  #设置步长,指定减量
    (integer) 1
    127.0.0.1:6379> 
    
    ###############################################################################
    # 字符串范围 range
    127.0.0.1:6379> flushdb  #清空数据库
    OK
    127.0.0.1:6379> set name zhour  #设置值
    OK
    127.0.0.1:6379> get name  #获取值
    "zhour"
    127.0.0.1:6379> getrange name 0 3  #截取字符串 [0,3]
    "zhou"
    127.0.0.1:6379> getrange name 0 -1  #获得全部的字符串,和getkey是一样的
    "zhour"
    127.0.0.1:6379> 
    
    # 替换
    127.0.0.1:6379> set key2 abcdefg
    OK
    127.0.0.1:6379> get key2
    "abcdefg"
    127.0.0.1:6379> setrange key2 1 xx  #替换指定位置开始的字符串
    (integer) 7
    127.0.0.1:6379> get key2
    "axxdefg"
    
    ###############################################################################
    # setex (set with expire)  设置过期时间
    # setnx (set if not exist) 不存在再设置  在分布式锁中常使用
    
    127.0.0.1:6379> setex key3 30 "hello"   #设置key3的值为hello,30秒后过期
    OK
    127.0.0.1:6379> ttl key3  #查看还有多长时间过期
    (integer) 25
    127.0.0.1:6379> setnx key4 "redis"  #如果key4不存在,就创建key4
    (integer) 1
    127.0.0.1:6379> setnx key4 "MongoDB"  #如果key4存在,就创建失败
    (integer) 0
    127.0.0.1:6379> get key4
    "redis"
    127.0.0.1:6379> 
    
    ###############################################################################
    # mset
    # mget
    127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3  #同时设置多个值
    OK
    127.0.0.1:6379> keys *
    1) "k2"
    2) "k1"
    3) "k3"
    127.0.0.1:6379> mget k1 k2 k3  #同时获取多个值
    1) "v1"
    2) "v2"
    3) "v3"
    127.0.0.1:6379> msetnx k1 v1 k4 v4  #msetnx是个原子性的操作,要么一起成功,要么一起失败
    (integer) 0
    127.0.0.1:6379> get k4
    (nil)
    
    # 对象
    set user:1 {name:zhour,age:3}  #设置一个user:1对象 值为json字符串来保存一个对象
    
    # user:{id}:{filed},这样设计在redis中是可以的
    127.0.0.1:6379> mset user:1:name zhour user:1:age 3
    OK
    127.0.0.1:6379> mget user:1:name user:1:age
    1) "zhour"
    2) "3"
    127.0.0.1:6379> 
    
    ###############################################################################
    # getset  先get再set
    127.0.0.1:6379> getset db redis  #如果不存在值就返回 nil
    (nil)
    127.0.0.1:6379> get db
    "redis"
    127.0.0.1:6379> getset db mongodb  #如果存在值,获取原来的值,并设置新的值
    "redis"
    127.0.0.1:6379> get db
    "mongodb"
    127.0.0.1:6379> 
    
    

    String 类型的使用场景:value除了是字符串还可以是数字。

    • 计数器
    • 统计多单位的数量
    • 粉丝数
    • 对象缓存存储

    List(列表)

    基本的数据类型,列表。

    在redis中,可以把list玩出成,栈,队列,阻塞队列。

    所有的 list 命令都是以 l 开头的。Redis不区分大小写命令。

    ###############################################################################
    # lpush
    127.0.0.1:6379> lpush list one  #将一个值或者多个值插入到列表的头部(左)
    (integer) 1
    127.0.0.1:6379> lpush list two  
    (integer) 2
    127.0.0.1:6379> lpush list three
    (integer) 3
    127.0.0.1:6379> lrange list 0 -1  #获取list的值
    1) "three"
    2) "two"
    3) "one"
    127.0.0.1:6379> lrange list 0 1  #获取区间内具体的值
    1) "three"
    2) "two"
    127.0.0.1:6379> rpush list right  #将一个值或者多个值插入到列表的尾部(右)
    (integer) 4
    127.0.0.1:6379> lrange list 0 -1
    1) "three"
    2) "two"
    3) "one"
    4) "right"
    127.0.0.1:6379> 
    
    ###############################################################################
    # lpop
    # rpop
    127.0.0.1:6379> lrange list 0 -1
    1) "three"
    2) "two"
    3) "one"
    4) "right"
    127.0.0.1:6379> lpop list  #移除列表的第一个元素
    "three"
    127.0.0.1:6379> rpop list  #移除列表的最后一个元素
    "right"
    127.0.0.1:6379> lrange list 0 -1
    1) "two"
    2) "one"
    127.0.0.1:6379> 
    
    ###############################################################################
    # lindex
    127.0.0.1:6379> lindex list 0  #通过下标获取指定下标的值
    "two"
    127.0.0.1:6379> lindex list 1
    "one"
    127.0.0.1:6379> 
    
    ###############################################################################
    #  llen
    127.0.0.1:6379> lrange list 0 -1
    1) "two"
    2) "one"
    127.0.0.1:6379> llen list  #获取列表的长度
    (integer) 2
    127.0.0.1:6379> 
    
    ###############################################################################
    # lrem 移除指定的值
    127.0.0.1:6379> lrange list 0 -1
    1) "four"
    2) "four"
    3) "three"
    4) "two"
    5) "one"
    127.0.0.1:6379> lrem list 1 one  #移除list集合中指定个数的value,精确匹配
    (integer) 1
    127.0.0.1:6379> lrem list 1 four
    (integer) 1
    127.0.0.1:6379> lrange list 0 -1
    1) "four"
    2) "three"
    3) "two"
    127.0.0.1:6379> lpush list four
    (integer) 4
    127.0.0.1:6379> lrem list 2 four  #移除list中的两个four
    (integer) 2
    127.0.0.1:6379> lrange list 0 -1
    1) "three"
    2) "two"
    
    ###############################################################################
    # ltrim 袖箭
    127.0.0.1:6379> rpush mylist hello
    (integer) 1
    127.0.0.1:6379> rpush mylist hello1
    (integer) 2
    127.0.0.1:6379> rpush mylist hello12
    (integer) 3
    127.0.0.1:6379> rpush mylist hello13
    (integer) 4
    127.0.0.1:6379> ltrim mylist 1 2  #通过下标截取指定的长度,只剩下截取的元素
    OK
    127.0.0.1:6379> lrange mylist 0 -1
    1) "hello1"
    2) "hello12"
    127.0.0.1:6379> 
    
    ###############################################################################
    # rpoplpush  移除列表的最后一个元素,并将它添加到一个新的列表中
    127.0.0.1:6379> rpush mylist hello
    (integer) 1
    127.0.0.1:6379> rpush mylist hello1
    (integer) 2
    127.0.0.1:6379> rpush mylist hello2
    (integer) 3
    127.0.0.1:6379> rpoplpush mylist myotherlist  #移除列表的最后一个元素,并将它添加到一个新的列表中
    "hello2"
    127.0.0.1:6379> lrange mylist 0 -1  #查看原来的列表
    1) "hello"
    2) "hello1"
    127.0.0.1:6379> lrange myotherlist 0 -1  #查看新的列表
    1) "hello2"
    127.0.0.1:6379> 
    
    ###############################################################################
    # lset  将列表中指定下标的值替换为另外一个值
    127.0.0.1:6379> exists list  #判断这个列表是否存在
    (integer) 0
    127.0.0.1:6379> lset list 0 item  #如果不存在列表,去更新就会报错
    (error) ERR no such key
    127.0.0.1:6379> lpush list value1
    (integer) 1
    127.0.0.1:6379> lrange list 0 0
    1) "value1"
    127.0.0.1:6379> lset list 0 item  #如果存在,会更新当前下标的值
    OK
    127.0.0.1:6379> lrange list 0 0
    1) "item"
    127.0.0.1:6379> lset list 1 other  #不存在这个下标,会报错
    (error) ERR index out of range
    
    ###############################################################################
    # linsert  将某个具体的value插入到某个元素的前面或者后面
    127.0.0.1:6379> rpush mylist hello
    (integer) 1
    127.0.0.1:6379> rpush mylist world
    (integer) 2
    127.0.0.1:6379> linsert mylist before world other
    (integer) 3
    127.0.0.1:6379> lrange mylist 0 -1
    1) "hello"
    2) "other"
    3) "world"
    127.0.0.1:6379> linsert mylist after  world new
    (integer) 4
    127.0.0.1:6379> lrange mylist 0 -1
    1) "hello"
    2) "other"
    3) "world"
    4) "new"
    
    

    list:实际上是一个链表,before Node after,left,right都可以插入值。

    • 如果key不存在,创建新的列表
    • 如果key存在,新增内容
    • 如果移除了所有值,空链表,代表不存在
    • 在两边插入或者改动值效率最高,中间元素,相对来说,效率低一点

    消息队列(Lpush,Rpop),栈(Lpush,Lpop)。

    Set(集合)

    set中的值是不能重复的!

    ###############################################################################
    # 存值,取值
    127.0.0.1:6379> sadd myset hello  #set中存值
    (integer) 1
    127.0.0.1:6379> sadd myset hellozr
    (integer) 1
    127.0.0.1:6379> sadd myset hellozhou
    (integer) 1
    127.0.0.1:6379> smembers myset  #查看指定set的所有值
    1) "hellozr"
    2) "hello"
    3) "hellozhou"
    127.0.0.1:6379> sismember myset hello  #判断某一个元素是否在set中,存在返回 1
    (integer) 1
    127.0.0.1:6379> sismember myset world  #不存在这个元素会返回 0
    (integer) 0
    127.0.0.1:6379> 
    
    ###############################################################################
    127.0.0.1:6379> scard myset  #获取set中元素的个数
    (integer) 3
    
    ###############################################################################
    # srem
    127.0.0.1:6379> srem myset hello  # 移除set中的指定元素
    (integer) 1
    127.0.0.1:6379> scard myset
    (integer) 2
    127.0.0.1:6379> smembers myset  #查看set中的元素
    1) "hellozr"
    2) "hellozhou"
    127.0.0.1:6379> 
    
    ###############################################################################
    # set 无序不重复集合 
    127.0.0.1:6379> sadd myset zhourr
    (integer) 1
    127.0.0.1:6379> smembers myset
    1) "zhourr"
    2) "hellozr"
    3) "hellozhou"
    127.0.0.1:6379> srandmember myset  #随机抽选出一个元素
    "hellozr"
    127.0.0.1:6379> srandmember myset
    "hellozhou"
    127.0.0.1:6379> srandmember myset
    "hellozr"
    127.0.0.1:6379> srandmember myset
    "hellozr"
    127.0.0.1:6379> 
    
    ###############################################################################
    # 删除指定的key  随机删除key
    127.0.0.1:6379> smembers myset
    1) "zhourr"
    2) "hellozr"
    3) "hellozhou"
    127.0.0.1:6379> spop myset  #随机移除元素
    "hellozr"
    127.0.0.1:6379> spop myset
    "hellozhou"
    127.0.0.1:6379> smembers myset
    1) "zhourr"
    127.0.0.1:6379> 
    
    ###############################################################################
    # 将一个指定的值移动到另外一个set集合中
    127.0.0.1:6379> sadd myset hello
    (integer) 1
    127.0.0.1:6379> sadd myset world
    (integer) 1
    127.0.0.1:6379> sadd myset zhour
    (integer) 1
    127.0.0.1:6379> sadd myset2 set2
    (integer) 1
    127.0.0.1:6379> smove myset myset2 zhour   # 将一个指定的值移动到另外一个set集合中
    (integer) 1
    127.0.0.1:6379> SMEMBERS myset
    1) "hello"
    2) "world"
    127.0.0.1:6379> SMEMBERS myset2
    1) "zhour"
    2) "set2"
    127.0.0.1:6379> 
    
    ###############################################################################
    # 共同关注(交集)
    # SDIFF 差集
    # SINTER 交集
    # SUNION 并集
    127.0.0.1:6379> sadd key1 a
    (integer) 1
    127.0.0.1:6379> sadd key1 b
    (integer) 1
    127.0.0.1:6379> sadd key1 c
    (integer) 1
    127.0.0.1:6379> sadd key2 c
    (integer) 1
    127.0.0.1:6379> sadd key2 d
    (integer) 1
    127.0.0.1:6379> sadd key2 e
    (integer) 1
    127.0.0.1:6379> SDIFF key1 key2  # 差集
    1) "a"
    2) "b"
    127.0.0.1:6379> SINTER key1 key2  # 交集 共同好友
    1) "c"
    127.0.0.1:6379> SUNION key1 key2  # 并集
    1) "a"
    2) "b"
    3) "c"
    4) "e"
    5) "d"
    127.0.0.1:6379> 
    
    

    可以将 A 的所有关注放在一个集合中,将它的粉丝放在另一个集合中!

    共同好友,共同爱好,二度好友,推荐好友!(六度分割理论)

    Hash(哈希)

    Map集合,key-map集合,value变成了map集合!本质和String类型没有太大的区别,还是一个简单的key-value。

    127.0.0.1:6379> hset myhash field1 zhourr  # set一个具体的 key value
    (integer) 1
    127.0.0.1:6379> hget myhash field1  # 获取一个字段值
    "zhourr"
    127.0.0.1:6379> hmset myhash field1 hello field2 world  # set 多个 key value
    OK
    127.0.0.1:6379> hmget myhash field1 field2  # 获取多个字段值
    1) "hello"
    2) "world"
    127.0.0.1:6379> hgetall myhash  # 获取全部的数据 key value
    1) "field1"
    2) "hello"
    3) "field2"
    4) "world"
    127.0.0.1:6379> 
    
    ###############################################################################
    
    127.0.0.1:6379> hdel myhash field1  # 删除hash指定的key字段,对应的value值也被删除
    (integer) 1
    127.0.0.1:6379> hgetall myhash
    1) "field2"
    2) "world"
    127.0.0.1:6379> 
    
    ###############################################################################
    # hlen 
    127.0.0.1:6379> hmset myhash field1 hello field2 world
    OK
    127.0.0.1:6379> hgetall myhash
    1) "field2"
    2) "world"
    3) "field1"
    4) "hello"
    127.0.0.1:6379> hlen myhash  # 获取hash 表的字段数量
    (integer) 2
    127.0.0.1:6379> 
    
    ###############################################################################
    # 判断 hash 中指定的key是否存在
    127.0.0.1:6379> HEXISTS myhash field1  #判断 hash 中指定的key是否存在
    (integer) 1
    127.0.0.1:6379> HEXISTS myhash field3
    (integer) 0
    
    ###############################################################################
    #只获得所有的field
    #只获得所有的value
    127.0.0.1:6379> hkeys myhash  #只获得所有的field
    1) "field2"
    2) "field1"
    127.0.0.1:6379> hvals myhash  #只获得所有的value
    1) "world"
    2) "hello"
    127.0.0.1:6379> 
    
    ###############################################################################
    # hincrby
    127.0.0.1:6379> hset myhash field3 5  # 指定增量
    (integer) 1
    127.0.0.1:6379> HINCRBY myhash field3 2  
    (integer) 7
    127.0.0.1:6379> HINCRBY myhash field3 -3
    (integer) 4
    127.0.0.1:6379> hsetnx myhash field4 hello  # 如果不存在,则可以设置
    (integer) 1
    127.0.0.1:6379> hsetnx myhash field4 world  # 如果存在,则不可用设置
    (integer) 0
    127.0.0.1:6379> 
    
    

    hash 变更的数据 user name age ,尤其是用户信息的保存,或经常变动的信息。hash更适合对象的存储,string更适合字符串的存储。

    Zset(有序集合)

    在set的基础上增加了一个值,set k1 v1 , zset k1 score1 v1.

    ###############################################################################
    127.0.0.1:6379> zadd myset 1 one  #添加一个值
    (integer) 1
    127.0.0.1:6379> zadd myset 2 two 3 three  # 添加多个值
    (integer) 2
    127.0.0.1:6379> zrange myset 0 -1  # 获取所有的值
    1) "one"
    2) "two"
    3) "three"
    127.0.0.1:6379> 
    
    ###############################################################################
    # 排序
    127.0.0.1:6379> zadd salary 2500 xiaohong  # 添加三个用户
    (integer) 1
    127.0.0.1:6379> zadd salary 5000 zhangsan
    (integer) 1
    127.0.0.1:6379> zadd salary 4000 zhour
    (integer) 1
    127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf  #显示全部用户,从负无穷到正无穷排序
    1) "xiaohong"
    2) "zhour"
    3) "zhangsan"
    127.0.0.1:6379> ZREVRANGE salary 0 -1  # 从大到小排序
    1) "zhangsan"
    2) "zhour"
    3) "xiaohong"
    127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf withscores  # 从小到大显示,并附带成绩
    1) "xiaohong"
    2) "2500"
    3) "zhour"
    4) "4000"
    5) "zhangsan"
    6) "5000"
    127.0.0.1:6379> ZRANGEBYSCORE salary -inf 4000 withscores  # 4000以下的员工的排序
    1) "xiaohong"
    2) "2500"
    3) "zhour"
    4) "4000"
    
    127.0.0.1:6379> ZREVRANGEBYSCORE salary +inf -inf  # 从大到小排序
    1) "zhangsan"
    2) "zhour"
    3) "xiaohong"
    
    ###############################################################################
    # 移除元素
    127.0.0.1:6379> zrange salary 0 -1
    1) "xiaohong"
    2) "zhour"
    3) "zhangsan"
    127.0.0.1:6379> zrem salary xiaohong  # 移除元素
    (integer) 1
    127.0.0.1:6379> zrange salary 0 -1
    1) "zhour"
    2) "zhangsan"
    127.0.0.1:6379> zcard salary  # 获取有序集合中的个数
    (integer) 2
    127.0.0.1:6379> 
    
    
    ###############################################################################
    # 获取指定区间的成员数量
    127.0.0.1:6379> zadd myset 1 hello
    (integer) 1
    127.0.0.1:6379> zadd myset 2 world 3 zhour
    (integer) 2
    127.0.0.1:6379> zcount myset 1 3  # 获取指定区间的成员数量
    (integer) 3
    
    
    
    
    下一篇:没有了