(一)Redis入门和五大数据类型

一、NoSQL

1.1、概述

关系型数据库:依据关系模型来创建的数据库。所谓关系模型就是“一对一、一对多、多对多”等。

NoSQL = Not Only SQL,意思:不仅仅是SQL; 泛指非关系型的数据库。
非关系型数据库:

  1. 列模型:存储的数据是一列列的。关系型数据库以一行作为一个记录,列模型数据库以一列为一个记录。(这种模型,数据即索引,IO很快,主要是一些分布式数据库)
  2. 键值对模型:存储的数据是一个个“键值对”,比如name:liming,那么name这个键里面存的值就是liming
  3. 文档类模型:以一个个文档来存储数据,有点类似“键值对”

很多的数据类型用户的个人信息,社交网络,地理位置,这些数据类型的存储不需要一个固定的格式,不需要多余的操作就可以横向扩展。
NoSQL数据库的产生就是为了解决大规模数据集合多种数据种类带来的挑战,尤其是大数据应用难题,包括超大规模数据的存储。

1.2、NoSQL特点

  1. 方便扩展:数据之间没有关系,容易扩展
  2. 大数据量高性能:Redis一秒可以写8万次,读11万次。得益于它的非关系性,数据库的结构简单。 NoSQL的缓存是记录级的,是一种细粒度的缓存,性能会比较高。
  3. 多样灵活的数据模型:不需要事先设计数据库,随时可以存储自定义的数据格式。而在关系数据库中,大数据量的表增删字段是一件非常麻烦的事情
  4. 传统RDBMS和NoSQL
    传统的关系型数据库 RDBMS
    - 高度组织化结构化数据
    - 结构化查询语言(SQL)
    - 数据和关系都存储在单独的表中
    - 数据操纵语言,数据定义语言
    - 严格的一致性
    - 基础事务
    NoSQL
    - 代表着不仅仅是SQL
    - 没有声明性查询语言
    - 没有预定义的模式
    - 键值对存储,列存储,文档存储,图形数据库
    - 最终一致性,而非ACID属性
    - 非结构化和不可预知的数据
    - CAP定理
    - 高性能,高可用性 和 可伸缩性
    

1.3、3V+3高

大数据时代的3V : 主要是对问题的描述

  • 海量 Volume
  • 多样 Variety
  • 实时 Velocity

互联网需求的3高 : 主要是对程序的要求

  • 高并发
  • 高可用
  • 高性能

1.4、NoSQL的四大类

KV键值:

  • 新浪:BerkeleyDB+redis
  • 美团:redis+tair
  • 阿里、百度:memcache+redis

文档型数据库(bson格式较多,和json一样):

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

列存储数据库:

  • Cassandra, HBase
  • 分布式文件系统

图关系数据库:

  • 它不是放图形的,放的是关系比如:朋友圈社交网络、广告推荐系统
  • 社交网络,推荐系统等。专注于构建关系图谱
  • Neo4J, InfoGrid

四者对比:

二、Redis入门

2.1、概述

Redis:REmote DIctionary Server(远程字典服务器)
是一个开源的、使用C语言编写、支持网络、可基于内存也可以持久化的日执行、Key-Value型数据库,并提供多种语言的API。

Redis与其他key-value缓存产品有以下三个特点:

  • Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
  • Redis不仅仅支持简单的 key-value 类型的数据,同时还提供list、set、zset、hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份。

Redis功能:

  • 内存存储和持久化:redis支持异步将内存中的数据写到硬盘上,同时不影响继续服务(rdb、aof)
  • 效率高,可以用于高速缓存
  • 发布、订阅消息系统
  • 地图信息分析
  • 定时器、计数器

Redis特性:

  • 数据类型、基本操作和配置
  • 持久化和复制,RDB、AOF
  • 事务的控制

2.2、安装

2.2.1、 Windows安装

下载地址:https://github.com/dmajkic/redis/downloads
解压压缩包即可

双击 redis-server.exe 即可启动
通过客户端去访问

2.2.2、Linux安装

下载地址 http://download.redis.io/releases

  1. 下载获得 redis-5.0.7.tar.gz 后将它放到Linux的目录下 /opt

  2. /opt 目录下,解压命令 : tar -zxvf redis-5.0.7.tar.gz

  3. 解压完成后出现文件夹:redis-5.0.7

  4. 进入目录: cd redis-5.0.7

  5. 在 redis-5.0.7 目录下执行 make 命令

    运行make命令时出现的错误解析:
    1. 安装gcc (gcc是linux下的一个编译程序,是c程序的编译工具)
        能上网: yum install gcc-c++
        版本测试: gcc-v
    2. 二次make
    3. Jemalloc/jemalloc.h: 没有那个文件或目录
        运行 make distclean 之后再make
    4. Redis Test(可以不用执行)
    
  6. make完成后继续执行 make install

  7. 查看默认安装目录:usr/local/bin

    /usr 这是一个非常重要的目录,类似于windows下的Program Files,存放用户的程序
    
  8. 拷贝配置文件

    cd /usr/local/bin
    ll
    # 在redis的解压目录下备份redis.conf
    mkdir config
    cp redis.conf config# 拷一个备份,养成良好的习惯,我们就修改这个文件
    # 修改配置保证可以后台应用
    vim redis.conf
    

    daemonize 设置yes或者no区别
    daemonize:yes
    redis采用的是单进程多线程的模式。当redis.conf中选项daemonize设置成yes时,代表开启守护进程模式。在该模式下,redis会在后台运行,并将进程pid号写入至redis.conf选项pidfile设置的文件中,此时redis将一直运行,除非手动kill该进程。
    daemonize:no
    当daemonize选项设置成no时,当前界面将进入redis的命令行界面,exit强制退出或者关闭连接工具(putty,xshell等)都会导致redis进程退出。

  9. 测试

    # 【shell】启动redis服务
    [root@192 bin]# cd /usr/local/bin
    [root@192 bin]# redis-server /opt/redis-5.0.7/redis.conf
    # redis客户端连接===> 观察地址的变化,如果连接ok,是直接连上的,redis默认端口号 6379
    [root@192 bin]# redis-cli -p 6379
    127.0.0.1:6379> ping
    PONG
    127.0.0.1:6379> shutdown  # 关闭连接
    

2.3、性能测试

**Redis-benchmark:**是一个官方自带的压力测试工具

性能测试可选参数:

# 测试一:100个并发连接,100000个请求,检测host为localhost 端口为6379的redis服务器性能
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
	====== SET ======
    100000 requests completed in 1.88 seconds # 对集合写入测试
    100 parallel clients # 每次请求有100个并发客户端
    3 bytes payload # 每次写入3个字节的数据,有效载荷
    keep alive: 1 # 保持一个连接,一台服务器来处理这些请求
    
    17.05% <= 1 milliseconds
    97.35% <= 2 milliseconds
    99.97% <= 3 milliseconds
    100.00% <= 3 milliseconds # 所有请求在 3 毫秒内完成
    53248.14 requests per second # 每秒处理 53248.14 次请求

2.4、基础知识说明

redis默认有16个数据库,默认使用的是第0个数据库
可以使用select切换数据库

127.0.0.1:6379> select 7
OK
127.0.0.1:6379[7]>
# 不同的库可以存不同的数据

# Dbsize查看当前数据库的key的数量
127.0.0.1:6379[7]> DBSIZE
(integer) 0

# 查看具体的key
127.0.0.1:6379> keys *

127.0.0.1:6379> flushdb # 清空当前库
127.0.0.1:6379> flushall # 清空全部库

redis是单线程的:

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

Redis单线程快的原因:

  1. 误区:高性能服务器一定是多线程的,多线程一定比单线程效率高
  2. redis核心:将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的。多线程(CPU上下文会切换,这个操作耗时),对于内存系统来说,如果没有上下文切换效率就是最高的。多次读写都是在一个CPU上的,但在内存情况下,这个就是最佳的方案

三、五大数据类型

3.1、Redis-key

127.0.0.1:6379> set age 1  # 存储键值对
OK
127.0.0.1:6379> get age # 获取值
"1"
127.0.0.1:6379> EXISTS age # 判断键是否存在
(integer) 1
127.0.0.1:6379> move age 1 # 移除当前数据库的键值对
(integer) 1
127.0.0.1:6379> EXPIRE age 10 # 设置过期时间默认秒
(integer) 1
127.0.0.1:6379> ttl age # 查看当前键的剩余时间,-1 表示永不过期,-2 表示已过期
(integer) 7
127.0.0.1:6379> type name # 查看当前键的类型
string

3.2、String(字符串)

单值单value

# ===================================================
# set、get、del、append、strlen
# ===================================================
127.0.0.1:6379> set key1 value1 # 设置值
OK
127.0.0.1:6379> get key1 # 获得key
"value1"
127.0.0.1:6379> del key1 # 删除key
(integer) 1
127.0.0.1:6379> keys * # 查看全部的key
(empty list or set)
127.0.0.1:6379> exists key1 # 确保 key1 不存在
(integer) 0
127.0.0.1:6379> append key1 "hello" # 对不存在的 key 进行 APPEND ,等同于 SET
key1 "hello"
(integer) 5 # 字符长度
127.0.0.1:6379> APPEND key1 "-2333" # 对已存在的字符串进行 APPEND
(integer) 10 # 长度从 5 个字符增加到 10 个字符
127.0.0.1:6379> get key1
"hello-2333"
127.0.0.1:6379> STRLEN key1 # # 获取字符串的长度
(integer) 10

# ===================================================
# incr、decr 一定要是数字才能进行加减,+1 和 -1。
# incrby、decrby 命令将 key 中储存的数字加上指定的增量值。
# ===================================================
127.0.0.1:6379> set views 0 # 设置浏览量为0
OK
127.0.0.1:6379> incr views # 浏览 + 1
(integer) 1
127.0.0.1:6379> incr views # 浏览 + 1
(integer) 2
127.0.0.1:6379> decr views # 浏览 - 1
(integer) 1
127.0.0.1:6379> incrby views 10 # +10
(integer) 11
127.0.0.1:6379> decrby views 10 # -10
(integer) 1

# ===================================================
# getrange 获取指定区间范围内的值,类似substring,从零到负一表示全部
# ===================================================
127.0.0.1:6379> set key2 abcd123456 # 设置key2的值
OK
127.0.0.1:6379> getrange key2 0 -1 # 获得全部的值
"abcd123456"
127.0.0.1:6379> getrange key2 0 2 # 截取部分字符串
"abc"

# ===================================================
# setrange 设置指定位置开始的字符串,格式是setrange key 值 具体值
# ===================================================
127.0.0.1:6379> get key2
"abcd123456"
127.0.0.1:6379> SETRANGE key2 1 xx # 替换值
(integer) 10
127.0.0.1:6379> get key2
"axxd123456"

# ===================================================
# setex(set with expire)键秒值
# setnx(set if not exist)
# ===================================================
127.0.0.1:6379> setex key3 60 expire # 设置过期时间
OK
127.0.0.1:6379> ttl key3 # 查看剩余的时间
(integer) 55
127.0.0.1:6379> setnx mykey "redis" # 如果不存在就设置,成功返回1
(integer) 1
127.0.0.1:6379> setnx mykey "mongodb" # 如果不存在就设置,否则失败返回0
(integer) 0
127.0.0.1:6379> get mykey
"redis"

# ===================================================
# mset 用于同时设置一个或多个 key-value 对。
# mget 返回所有(一个或多个)给定 key 的值。
# 	   如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil 。
# msetnx 当所有 key 都成功设置,返回 1 。
# 	     如果所有给定 key 都设置失败(至少有一个 key 已经存在),那么返回 0 。原子操作
# ===================================================
127.0.0.1:6379> mset k10 v10 k11 v11 k12 v12
OK
127.0.0.1:6379> keys *
1) "k12"
2) "k11"
3) "k10"
127.0.0.1:6379> mget k10 k11 k12 k13
1) "v10"
2) "v11"
3) "v12"
4) (nil)
127.0.0.1:6379> msetnx k10 v10 k15 v15 # 原子性操作!
(integer) 0
127.0.0.1:6379> get key15
(nil)

# 传统对象缓存
set user:1 value(json数据)

# 可以用来缓存对象
mset user:1:name zhangsan user:1:age 2
mget user:1:name user:1:age

# ===================================================
# getset(先get再set)
# ===================================================
127.0.0.1:6379> getset db mongodb # 没有旧值,返回 nil
(nil)
127.0.0.1:6379> get db
"mongodb"
127.0.0.1:6379> getset db redis # 返回旧值 mongodb
"mongodb"
127.0.0.1:6379> get db
"redis"

String数据结构是简单的key-value类型,value其实不仅可以是String,也可以是数字。
常规key-value缓存应用:
常规计数:微博数,粉丝数等。

3.3、List(列表)

单值多Value
在redis里面,可以把list做成栈、队列、阻塞队列
所有的list命令都是用l开头的

# ===================================================
# Lpush:将一个或多个值插入到列表头部。(左)
# rpush:将一个或多个值插入到列表尾部。(右)
# lrange:返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。
# 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。
# 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
# ===================================================
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> RPUSH list "right"
(integer) 3
127.0.0.1:6379> Lrange list 0 -1
1) "two"
2) "one"
3) "right"
127.0.0.1:6379> Lrange list 0 1
1) "two"
2) "one"

# ===================================================
# lpop 命令用于移除并返回列表的第一个元素。当列表 key 不存在时,返回 nil 。
# rpop 移除列表的最后一个元素,返回值为移除的元素。
# ===================================================
127.0.0.1:6379> Lpop list
"two"
127.0.0.1:6379> Rpop list
"right"
127.0.0.1:6379> Lrange list 0 -1
1) "one"

# ===================================================
# Lindex,按照索引下标获得元素(-1代表最后一个,0代表是第一个)
# ===================================================
127.0.0.1:6379> Lindex list 1
(nil)
127.0.0.1:6379> Lindex list 0
"one"
127.0.0.1:6379> Lindex list -1
"one"

# ===================================================
# llen 用于返回列表的长度。
# ===================================================
127.0.0.1:6379> flushdb
OK
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> Llen list # 返回列表的长度
(integer) 3

# ===================================================
# lrem key 根据参数,移除列表中与参数 VALUE 相等的元素。
# ===================================================
127.0.0.1:6379> lrem list 1 "two"
(integer) 1
127.0.0.1:6379> Lrange list 0 -1
1) "three"
2) "one"

# ===================================================
# Ltrim key 对一个列表进行修剪(trim),让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
# ===================================================
127.0.0.1:6379> RPUSH mylist "hello"
(integer) 1
127.0.0.1:6379> RPUSH mylist "hello"
(integer) 2
127.0.0.1:6379> RPUSH mylist "hello2"
(integer) 3
127.0.0.1:6379> RPUSH mylist "hello3"
(integer) 4
127.0.0.1:6379> ltrim mylist 1 2
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "hello2"

# ===================================================
# rpoplpush 移除列表的最后一个元素,并将该元素添加到另一个列表并返回。
# ===================================================
127.0.0.1:6379> rpush mylist "hello"
(integer) 1
127.0.0.1:6379> rpush mylist "foo"
(integer) 2
127.0.0.1:6379> rpush mylist "bar"
(integer) 3
127.0.0.1:6379> rpoplpush mylist myotherlist
"bar"
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "foo"
127.0.0.1:6379> lrange myotherlist 0 -1
1) "bar"

# ===================================================
# lset key index value 将列表 key 下标为 index 的元素的值设置为 value 。
# ===================================================
127.0.0.1:6379> exists list # 对空列表(key 不存在)进行 LSET
(integer) 0
127.0.0.1:6379> lset list 0 item # 报错
(error) ERR no such key
127.0.0.1:6379> lpush list "value1" # 对非空列表进行 LSET
(integer) 1
127.0.0.1:6379> lrange list 0 0
1) "value1"
127.0.0.1:6379> lset list 0 "new" # 更新值
OK
127.0.0.1:6379> lrange list 0 0
1) "new"
127.0.0.1:6379> lset list 1 "new" # index 超出范围报错
(error) ERR index out of range

# ===================================================
# linsert key before/after pivot value 用于在列表的元素前或者后插入元素。
# 将值 value 插入到列表 key 当中,位于值 pivot 之前或之后。
# ===================================================
redis> RPUSH mylist "Hello"
(integer) 1
redis> RPUSH mylist "World"
(integer) 2
redis> LINSERT mylist BEFORE "World" "There"
(integer) 3
redis> LRANGE mylist 0 -1
1) "Hello"
2) "There"
3) "World"

总结:

  1. 它是一个字符串链表,left,right 都可以插入添加
  2. 如果键不存在,创建新的链表
  3. 如果键已存在,新增内容
  4. 如果值全移除,对应的键也就消失了
  5. 链表的操作无论是头和尾效率都极高,但假如是对中间元素进行操作,效率就很惨淡了。

使用List结构,我们可以轻松地实现最新消息排行等功能。
另一个应用就是消息队列,可以利用List的PUSH操作,将任务存在List中,然后工作线程再用POP操作将任务取出进行执行。

3.4、Set(集合)

单值多value

# ===================================================
# sadd 将一个或多个成员元素加入到集合中,不能重复
# smembers 返回集合中的所有的成员。
# sismember 命令判断成员元素是否是集合的成员。
# ===================================================
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 "world"
(integer) 0
127.0.0.1:6379> SMEMBERS myset
1) "world"
2) "hello"
127.0.0.1:6379> SISMEMBER myset "hello"
(integer) 1
127.0.0.1:6379> SISMEMBER myset "zhangsan"
(integer) 0

# ===================================================
# scard,获取集合里面的元素个数
# ===================================================
127.0.0.1:6379> scard myset
(integer) 2

# ===================================================
# srem key value 用于移除集合中的一个或多个成员元素
# ===================================================
127.0.0.1:6379> srem myset "world"
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "hello"

# ===================================================
# srandmember key 命令用于返回集合中的一个随机元素。
# ===================================================
127.0.0.1:6379> SMEMBERS myset
1) "zhangsan"
2) "world"
3) "hello"
127.0.0.1:6379> SRANDMEMBER myset
"hello"
127.0.0.1:6379> SRANDMEMBER myset 2
1) "world"
2) "zhangsan"
127.0.0.1:6379> SRANDMEMBER myset 2
1) "zhangsan"
2) "hello"

# ===================================================
# smove SOURCE DESTINATION MEMBER
# 将指定成员 member 元素从 source 集合移动到 destination 集合。
# ===================================================
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 "zhangsan"
(integer) 1
127.0.0.1:6379> sadd myset2 "set2"
(integer) 1
127.0.0.1:6379> smove myset myset2 "zhangsan"
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "world"
2) "hello"
127.0.0.1:6379> SMEMBERS myset2
1) "zhangsan"
2) "set2"

# ===================================================
# 数字集合类
# 差集: 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 # 查看key1中存在但key2中不存在的,差集
1) "a"
2) "b"
127.0.0.1:6379> SINTER key1 key2 # 查看key1,key2都存在的,交集
1) "c"
127.0.0.1:6379> SUNION key1 key2 # key1,key2合并,并集
1) "a"
2) "b"
3) "c"
4) "e"
5) "d"

在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能。

3.5、Hash(哈希)

kv模式不变,但V是一个键值对

# ===================================================
# hset、hget 命令用于为哈希表中的字段赋值 。
# hmset、hmget 同时将多个field-value对设置到哈希表中。会覆盖哈希表中已存在的字段。
# hgetall 用于返回哈希表中,所有的字段和值。
# hdel 用于删除哈希表 key 中的一个或多个指定字段
# ===================================================
127.0.0.1:6379> hset myhash field1 "zhangsan"
(integer) 1
127.0.0.1:6379> hget myhash field1
"zhangsan"
127.0.0.1:6379> HMSET myhash field1 "Hello" field2 "World"
OK
127.0.0.1:6379> HGET myhash field1
"Hello"
127.0.0.1:6379> HGET myhash field2
"World"
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "Hello"
3) "field2"
4) "World"
127.0.0.1:6379> HDEL myhash field1
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "World"

# ===================================================
# hlen 获取哈希表中字段的数量。
# ===================================================
127.0.0.1:6379> hlen myhash
(integer) 1
127.0.0.1:6379> HMSET myhash field1 "Hello" field2 "World"
OK
127.0.0.1:6379> hlen myhash
(integer) 2

# ===================================================
# hexists 查看哈希表的指定字段是否存在。
# ===================================================
127.0.0.1:6379> hexists myhash field1
(integer) 1
127.0.0.1:6379> hexists myhash field3
(integer) 0

# ===================================================
# hkeys 获取哈希表中的所有域(field)。
# hvals 返回哈希表所有域(field)的值。
# ===================================================
127.0.0.1:6379> HKEYS myhash
1) "field2"
2) "field1"
127.0.0.1:6379> HVALS myhash
1) "World"
2) "Hello"

# ===================================================
# hincrby 为哈希表中的字段值加上指定增量值。
# ===================================================
127.0.0.1:6379> hset myhash field 5
(integer) 1
127.0.0.1:6379> HINCRBY myhash field 1
(integer) 6
127.0.0.1:6379> HINCRBY myhash field -1
(integer) 5
127.0.0.1:6379> HINCRBY myhash field -10
(integer) -5

# ===================================================
# hsetnx 为哈希表中不存在的的字段赋值 。
# ===================================================
127.0.0.1:6379> HSETNX myhash field1 "hello"
(integer) 1 # 设置成功,返回 1 。
127.0.0.1:6379> HSETNX myhash field1 "world"
(integer) 0 # 如果给定字段已经存在,返回 0 。
127.0.0.1:6379> HGET myhash field1
"hello"

Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。
存储部分变更的数据,如用户信息等。

3.6、有序集合Zset

在set基础上,加一个score值。之前set是k1 v1 v2 v3,现在zset是 k1 score1 v1 score2 v2。

# ===================================================
# zadd 将一个或多个成员元素及其分数值加入到有序集当中。
# zrange 返回有序集中,指定区间内的成员
# ===================================================
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"

# ===================================================
# zrangebyscore 返回有序集合中指定分数区间的成员列表。有序集成员按分数值递增(从小到大)
次序排列。
# ===================================================
127.0.0.1:6379> zadd salary 2500 xiaoming
(integer) 1
127.0.0.1:6379> zadd salary 5000 xiaohong
(integer) 1
127.0.0.1:6379> zadd salary 500 zhangsan
(integer) 1
# Inf无穷大量+∞,同样地,-∞可以表示为-Inf。
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf # 显示整个有序集
1) "zhangsan"
2) "xiaoming"
3) "xiaohong"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf withscores # 递增排列
1) "zhangsan"
2) "500"
3) "xiaoming"
4) "2500"
5) "xiaohong"
6) "5000"
127.0.0.1:6379> ZREVRANGE salary 0 -1 WITHSCORES # 递减排列
1) "xiaohong"
2) "5000"
3) "xiaoming"
4) "2500"
5) "zhangsan"
6) "500"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf 2500 WITHSCORES # 显示工资 <=2500
的所有成员
1) "zhangsan"
2) "500"
3) "xiaoming"
4) "2500"

# ===================================================
# zrem 移除有序集中的一个或多个成员
# ===================================================
127.0.0.1:6379> ZRANGE salary 0 -1
1) "zhangsan"
2) "xiaoming"
3) "xiaohong"
127.0.0.1:6379> zrem salary zhangsan
(integer) 1
127.0.0.1:6379> ZRANGE salary 0 -1
1) "xiaoming"
2) "xiaohong"

# ===================================================
# zcard 命令用于计算集合中元素的数量。
# ===================================================
127.0.0.1:6379> zcard salary
(integer) 2
OK

# ===================================================
# zcount 计算有序集合中指定分数区间的成员数量。
# ===================================================
127.0.0.1:6379> zadd myset 1 "hello"
(integer) 1
127.0.0.1:6379> zadd myset 2 "world" 3 "zhangsan"
(integer) 2
127.0.0.1:6379> ZCOUNT myset 1 3
(integer) 3
127.0.0.1:6379> ZCOUNT myset 1 2
(integer) 2

# ===================================================
# zrank 返回有序集中指定成员的排名。其中有序集成员按分数值递增(从小到大)顺序排列。
# ===================================================
127.0.0.1:6379> zadd salary 2500 xiaoming
(integer) 1
127.0.0.1:6379> zadd salary 5000 xiaohong
(integer) 1
127.0.0.1:6379> zadd salary 500 zhangsan
(integer) 1
127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES # 显示所有成员及其 score 值
1) "zhangsan"
2) "500"
3) "xiaoming"
4) "2500"
5) "xiaohong"
6) "5000"
127.0.0.1:6379> zrank salary zhangsan# 显示 zhangsan的薪水排名,最少
(integer) 0
127.0.0.1:6379> zrank salary xiaohong # 显示 xiaohong 的薪水排名,第三
(integer) 2

# ===================================================
# zrevrank 返回有序集中成员的排名。其中有序集成员按分数值递减(从大到小)排序。
# ===================================================
127.0.0.1:6379> ZREVRANK salary zhangsan# zhangsan第三
(integer) 2
127.0.0.1:6379> ZREVRANK salary xiaohong # xiaohong 第一
(integer) 0

可以用sorted set来做带权重的队列,比如普
通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让
重要的任务优先执行。
排行榜应用,取TOP N操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值