【狂神说】Redis

学习资料:
【狂神说Java】Redis最新超详细版教程通俗易懂_哔哩哔哩_bilibili

(72条消息) Redis(基于狂神说Java-Redis)_你给我把被子盖好了,别再踢了的博客-CSDN博客_狂神说redis

Redis 安装 | 菜鸟教程 (runoob.com)

学习目的

​ Redis等关系型数据库作缓存去缓存使用频率高的数据,减轻Mysql等关系型数据库的压力

1、NoSQL简介

1.1 什么是NoSQL

NoSQL翻译为Not Only SQL,译为不仅仅是SQL,意指非关系型数据库

web2.0的诞生,传统的关系型数据库已经很难对付web2.0时代!特别是指大规模高并发社区!会出现很多问题,NoSQL在大数据时代发展的十分迅速,尤其是Redis

很多的数据类型用户的个人信息,社交网络,地理位置,这些数据类型的存储不需要一个固定的格式,不需要太多操作就可以实现横向拓展,就比如Redis,它是使用类似于Java的Map<String, Object>来实现存储,键值对的形式存储,这只是NoSQL的解决方式之一

1.2 NoSQL 特点

1、方便扩展(数据之间没有联系可以快速拓展)

2、大数据量高性能,Redis可以支持8w的并发量(写操作),11w访问量(读操作),NoSQL的缓存记录级,是一种细粒度的缓存,性能比较高

3、数据类型多样性(不需要事先设计数据库,随取随用,数据量过大就无法设计

4、传统的关系数据库管理系统(Relational Database Management System:RDBMS)和NoSQL的区别

关系型数据库与非关系型数据库对比


​ 传统的RDBMS(关系型数据库)

  • 结构化
  • SQL
  • 数据和关系存在于单独的表中 row(行) column(列)
  • 数据操作,数据定义语言
  • 严格的一致性
  • 基础的事务

NoSQL(非关系型数据库)

  • 不仅仅是数据
  • 没有固定的查询语言
  • 键值对存储,列存储,文档存储,图形数据库
  • 最终一致性
  • CAP定律和BASE理论

5、大数据时代的3V + 3高

  • 大数据时代的3V

    • 海量Volume
    • 多样Variety
    • 实时Velocity
    • 大数据时代的3高
  • 高并发

    • 高可用(随时水平拆分,机器不够了,随时扩展)
    • 高性能(保证用户体验和性能)
    • 真正在公司中用到的实践,NoSQL + 关系型数据库,这是最强组合,也是阿里巴巴的架构演进

实际 NoSql+关系型数据库 一起使用

# 商品的基本信息
名称、价格、商家信息
MySQL / Oracle 去IOE化(IOE:IBM、Oracle、EMC存储设备)

# 商品描述
评论,文本信息多
文档型数据库,MongoDB

# 图片
分布式文件系统 FastDFS
淘宝:TFS
Google:GFS
Hadoop:HDFS
阿里云:OSS

# 商品关键字(搜索)
搜索引擎 solr elasticsearch
淘宝:ISearch,ISearch作者,阿里的多隆

# 商品热门波段信息
内存数据库
Redis  Tair  Memcached...

# 商品交易,外部支付接口
第三方应用

1.3 NoSQL的四大分类

1、KV键值对

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

2、文档型数据库(Bson,Binary Json,二进制Json)

  • MongoDB,需要掌握,它是一种基于分布式文件存储的数据库,由C++编写,主要用来处理大量的文档

  • MongoDB 是一种介于关系型数据库和非关系型数据库之间的一种中间产品,功能丰富,而且MongoDB是NoSQL中最像关系型数据库的产品

  • ConthDB

3、列存储数据库

  • HBASE
  • 分布式文件系统

4、图形关系数据库

  • 它不是存图片的!它存放的是关系,就好比一个人的社交圈,可以动态扩充
  • Neo4j,InfoGrid

4种分类的对比

在这里插入图片描述

2、Redis入门

本次使用的Redis的版本采用的是5.0.10

2.1 Redis简介

什么是Redis?

​ Redis(Remote Directory Server),中文译为远程字典服务,免费开源,由C语言编写,支持网络,可基于内存也可持久化的日志型,KV键值对数据库,并且提供多种语言的API,是当下NoSQL中最热门的技术之一!被人们称之为结构化数据库!

Redis能干嘛?

  1. 内存存储,持久化,因为内存断电即失,并且Redis支持两种持久化方式,RDB / AOF
  2. 效率高,可用于高速缓存
  3. 消息发布订阅(消息队列
  4. 地图信息分析
  5. 计数器(eg:微博浏览量)

​ …

特性

  1. 数据类型多样

  2. 持久化

  3. Redis集群

  4. 事务

官网:https://redis.io/

Redis中文文档:http://www.redis.cn/documentation.html

下载地址:进入官网下载即可(Windows版本需要在GitHub上下载,并且Redis版本已停更较长时间,不建议使用)

并且,Redis官方推荐在Linux服务器上进行搭建

2.2 windows 安装 Radis

D:\tool\Redis-x64-5.0.14

在这里插入图片描述

文件 作用
redis-benchmark.exe 测试性能
redis-check-aof.exe 检查AOF持久化 (Redis支持两种持久化方式,RDB / AOF)
redis-server.exe 启动服务
redis-cli.exe 客户端

1、运行服务

​ 双击redis-server.exe 启动Redis服务 或 打开一个 cmd 窗口 使用 cd 命令切换目录运行:

redis-server.exe redis.windows.conf

这时候另启一个 cmd 窗口,原来的不要关闭,不然就无法访问服务端了。

在这里插入图片描述

2、连接Redis

​ 使用 Redis客户端(redis-cli.exe)连接Redis服务

切换到 redis 目录下运行:

redis-cli.exe -h 127.0.0.1 -p 6379

redis-cli

3、连接成功

D:\tool\Redis-x64-5.0.14
λ redis-cli.exe
127.0.0.1:6379>

4、使用

127.0.0.1:6379> ping #测试连接
PONG
127.0.0.1:6379> set name zs
OK
127.0.0.1:6379> get name
"zs"
127.0.0.1:6379>

2.3 Linux安装Redis

安装Redis的第一种,官网下载安装包

1、下载安装包,redis-5.0.10.tar.gz

2、下载到Windows之后,用Xftp工具上传至Linux

3、解压安装包并将其解压

tar -zxvf redis-5.0.4.tar.gz 

在这里插入图片描述

并且解压之后可以看见Redis的配置文件redis.conf

4、同时还需要基本的环境搭建

# 保证Redis的正常运行,gcc的安装也是必要的
yum install gcc-c++

# 查看版本
g++ -v

# 安装Redis所需要的环境
make

# 此命令只是为了确认当前所有环境全部安装完毕,可以选择不执行
make install 

Redis的安装,默认在/usr/local/bin

在这里插入图片描述

5、之后,需要将Redis的配置文件复制到bin目录下,可以提前准备好一个目录,然后在复制到新创建好的目录中

[root@192 opt]# cd  /opt/redis-5.0.4/
[root@192 redis-5.0.4]# ls
00-RELEASENOTES  CONTRIBUTING  deps     Makefile   README.md   runtest          runtest-sentinel  src    utils
BUGS             COPYING       INSTALL  MANIFESTO  redis.conf  runtest-cluster  sentinel.conf     tests
[root@192 redis-5.0.4]# cp redis.conf /usr/local/bin/myconfig/
[root@192 redis-5.0.4]# 

6、然后修改复制之后的配置文件,修改一条信息,修改的信息就是图中划红线的位置,它的意思是指守护进程模式启动,即可以在后台运行Redis

vim 搜索 方法:/str daemonize

在这里插入图片描述

7、随后就可以开始启动Redis服务(通过指定的配置文件启动服务)

[root@192 bin]# cd /usr/local/bin
[root@192 bin]# redis-server /usr/local/bin/myconfig/redis.conf

在这里插入图片描述

8、连接

/usr/local/bin/

[root@192 bin]# redis-cli -p 6379
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set age 23
OK
127.0.0.1:6379> get age
"23"
127.0.0.1:6379> keys *
1) "age"

9 、查看进程运行

[root@192 ~]# ps -ef|grep redis
root       2057   1967  0 16:21 pts/0    00:00:00 grep --color=auto redis
[root@192 bin]# redis-server /usr/local/bin/myconfig/redis.conf # 启动Redis服务
#...
[root@192 bin]# ps -ef|grep redis
root       2063      1  1 16:25 ?        00:00:00 redis-server 127.0.0.1:6379
root       2069   1967  0 16:25 pts/0    00:00:00 grep --color=auto redis
[root@192 bin]# 

10、关闭服务

127.0.0.1:6379> shutdown
127.0.0.1:6379> shutdown
not connected> exit
[root@192 bin]# ps -ef|grep redis
root       2074   1967  0 16:29 pts/0    00:00:00 grep --color=auto redis

2.4 避免中文乱码

有时候会有中文乱码。

要在 redis-cli 后面加上 --raw

redis-cli --raw

就可以避免中文乱码了

[root@192 bin]# redis-cli --raw
127.0.0.1:6379> set name 张三
OK
127.0.0.1:6379> get name
张三

2.5 性能测试工具

redis-benchmark性能测试工具

在这里插入图片描述

  • 测试命令
# 当前命令表示,性能测试,在本机,端口号6379,并发连接数100,每个连接10w个请求数量
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
  • 测试结果
[root@192 bin]# redis-benchmark -h localhost -p 6379 -c 100 -n 100000
# 测试结果如下,以Redis的INLINE命令为例
====== PING_INLINE ======
  100000 requests completed in 5.24 seconds # 十万个请求在5.24秒之内被处理
  100 parallel clients # 每次请求都有100个客户端在执行
  3 bytes payload # 一次处理3个字节的数据
  keep alive: 1 # 每次都保持一个服务器的连接,只用一台服务器处理这些请求

0.37% <= 1 milliseconds
13.17% <= 2 milliseconds
# ...
100.00% <= 104 milliseconds # 所有的请求在104秒之内完成
19076.69 requests per second # 平均每秒处理19076.69个请求

====== PING_BULK ====== # set、get、ping等每个命令都会测试
  100000 requests completed in 4.45 seconds
  100 parallel clients
  3 bytes payload
  keep alive: 1

0.31% <= 1 milliseconds
# ...

2.6 Redis基础知识

备注:在Redis中,关键字语法不区分大小写!

Redis有16个数据库支持,为啥嘞,可以查看redis.conf配置文件
在这里插入图片描述

并且初始数据库默认使用0号数据库(16个数据库对应索引0到15)

  • 可以使用select命令切换数据库:select n(0-15)
127.0.0.1:6379> select 12
OK
127.0.0.1:6379[12]> select 0
OK
127.0.0.1:6379> dbsize # 查看当前库的key数量
(integer) 0

  • 清空数据库信息
127.0.0.1:6379> keys *
1) "myset:__rand_int__"
2) "mylist"
3) "key:__rand_int__"
4) "name"
5) "counter:__rand_int__"
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379>
# 还有一个清空的命令,叫做flushall,它的意思是清空16个数据库中的全部信息。
# 不管在那种数据库中,清空库一直都是需要慎重操作的

题外话:为什么Redis选用6379作为默认端口号?

6379在是手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字。MERZ长期以来被Redis作者antirez及其朋友当作愚蠢的代名词。后来Redis作者在开发Redis时就选用了这个端口。(摘自知乎)

Redis是单线程的(从Redis6.0.1开始支持多线程)

Redis的读写速度很快,官方表示,Redis基于内存操作,CPU不是Redis的性能瓶颈,Redis的性能瓶颈是根据机器的内存和带宽

Redis是C语言编写,官方提供的数据为10万+的QPS(Queries-Per-Second,每秒内的查询次数)

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

对于Redis,有两个误区:

​ 1、高性能的服务器一定是多线程的?
​ 2、多线程一定比单线程效率高?

​ Redis将所有的数据全部放在内存中,使用单线程去操作效率比较高,对于多线程,CPU有一种东西叫做上下文切换,这种操作耗时,对于内存系统来说,没有上下文切换,效率一定是最高的

​ Redis使用单进程的模式来处理客户端的请求,对大部分事件的响应都是通过epoll函数的加强封装,Redis的实际处理速度依靠主进程的执行效率,epoll可以显著提高程序在大量并发连接中系统的CPU利用率

Redis中文网翻译:

​ 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)。

3、基础语法

基础语法(命令小写) 作用
set key value 设置一个key
get key 获取一个key对应value
exists key 查询key是否存在
move key n(n是数字) 将当前key移动到指定的几号数据库中
keys * 查询当前数据库中全部的key
expire key time 设置当前key的过期时间
ttl key 查询当前key的存活时间
type key 查看key的数据类型
flushdb 清空当前数据库信息(慎用)
flushall 空16个数据库中的全部信息(慎用)
select n 选择数据库
基础语法(命令大写):         
SET key value	          设置一个key
GET key                 获取一个key对应value
EXISTS key              查询key是否存在          
MOVE key n(数字)	     将当前key移动到指定的几号数据库中
KEYS *                  查询当前数据库中全部的key
EXPIRE key time         设置当前key的过期时间
TTL key                 查询当前key的存活时间
TYPE key                查看key的数据类型

1、set key value

127.0.0.1:6379> set name 张三 # 设置key-value
OK
127.0.0.1:6379> get name # 查询key指定的value
张三

2、exists key

127.0.0.1:6379> exists name # 查看当前key是否存在
1
127.0.0.1:6379> exists name1
0

3、move

127.0.0.1:6379> move name 1
1
127.0.0.1:6379> KEYS *
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
name

4、expire key time

127.0.0.1:6379[1]> expire name 5 # 设置当前key的过期时间,单位是秒
1
127.0.0.1:6379[1]> ttl name  # 查看指定key的存活时间,
-2 # 返回-2表示当前key已经过期,如果为-1,表示永不过期
127.0.0.1:6379> KEYS * # name 过期被清空
(empty list or set)

5、type key

127.0.0.1:6379[1]> set name 张三
OK
127.0.0.1:6379[1]> type name
string

4、Redis五大数据类型

以下命令记忆小写(命令提示大写),一是好记,二是java中与redis相关的方法与小写命令类似

4.1 String(字符串)

语法 作用
append key Value 对指定key实现字符串拼接,如果key不存在,等同于set
strlen key 查看指定key的长度
incr key 对指定key进行自增,类似于Java中的i++
decr key 自减,类似于Java的i–
incrby key n 对指定key按照指定的步长值进行自增
decrby key n 按照指定的步长值自减
setrange key index value 从指定key的索引开始,插入指定的value值。
getrange key index value 将指定key按照索引的开始和结束范围进行截取,成为一个新的key
setex key time value 设置一个有存活时间的key
setex key value 如果这个key不存在,即创建
mset key value … 设置多个key value
mget key value 获取多个key指定的value
getset key value 先获取指定的key,然后再设置指定的value
# 语法:
APPEND key appendValue      # 对指定key实现字符串拼接,如果key不存在,等同于set
STRLEN key                  # 查看指定key的长度
INCR key                    # 对指定key进行自增,类似于Java中的i++
DECR key                    # 自减,类似于Java的i--
INCRBY key n                # 对指定key按照指定的步长值进行自增
DECRBY key n				# 按照指定的步长值自减
SETRANGE key index value          #  从指定key的索引开始,插入指定的value值。如果key不存	在且索引>1,那么当前的索引之前的数据,会用\x00代替并占用一个索引位置,相当于ASCII码中的null

GETRANGE key startIndex endInde  #将指定key按照索引的开始和结束范围进行截取,成为一个新的key
SETEX key time value	   # 设置一个有存活时间的key
SETNX key value            # 如果这个key不存在,即创建
MSET key value ...	       #设置多个key value
MGET key ...			   #获取多个key指定的value
GETSET key value          # 先获取指定的key,然后再设置指定的value

1、简单使用

127.0.0.1:6379[1]> set name ab
OK
127.0.0.1:6379[1]> append ab cd
2
127.0.0.1:6379[1]> get name
ab
127.0.0.1:6379[1]> strlen name
2

2、实现自增自减效果

  • 注意:value的自增和自减只适用于Integer类型
127.0.0.1:6379[1]> incr age
26
127.0.0.1:6379[1]> decr age
25
127.0.0.1:6379[1]> incrby age 10
35
127.0.0.1:6379[1]> decrby age 24
11

3、实现字符串截取效果

127.0.0.1:6379> set k1 hello,xiaohuang
OK
127.0.0.1:6379> get k1
"hello,xiaohuang"
127.0.0.1:6379> GETRANGE k1 0 3 # 实现字符串截取,有起始索引和结束索引,相当于Java中的subString()
"hell"
# 如果结束索引为-1,则表示当前截取的字符串为全部
127.0.0.1:6379> GETRANGE k1 0 -1
"hello,xiaohuang"

4、实现字符串的替换效果

127.0.0.1:6379> set key2 abcdefg
OK
127.0.0.1:6379> get key2
"abcdefg"
127.0.0.1:6379> SETRANGE key2 2 hello # 实现字符串的替换效果,命令中的数字“2”表示从索引2的位置开始将其替换为指定字符串
(integer) 7
127.0.0.1:6379> get key2
"abhello"

5、设置过期时间

# setex(set with expire) # 设置过期时间
# setnx(set with not exist) # 如果key不存在,创建(分布式锁中常用)
127.0.0.1:6379[1]> setex name 10 张三
OK
127.0.0.1:6379[1]> keys *
name
127.0.0.1:6379[1]> get name

127.0.0.1:6379[1]> keys *
127.0.0.1:6379> setnx lan redis # 如果key不存在,即创建
(integer) 1 
127.0.0.1:6379> setnx lan mongodb
(integer) 0 # 0表示没有设置成功,也可理解为“有0行受到影响”
127.0.0.1:6379> get lan
"redis"

6、一次性设置(获取)多个键值对

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"
# 也可以在这边的语法前面加上一个m,代表设置多个
127.0.0.1:6379> msetnx k1 vv1 k4 v4 
(integer) 0
# 但是这边同时设置多个值,如果有一个key已经存在,那么这一条设置语句便不会执行成功,
# 因为Redis单条语句是原子操作,要么同时成功,要么同时失败
127.0.0.1:6379> keys * 
1) "k2"
2) "k1"
3) "k3"
# 在Redis中,还推荐了一个比较有意思的东西
# 这是Redis中关于key的命名,可以用“:”来代表层次结构,可以对指定的key进行分类存储
127.0.0.1:6379> mset user:1:name xiaohuang user:1:age 21
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "xiaohuang"
2) "21"
127.0.0.1:6379> getset sqlan redis # 先获取当前key指定的value,如果不存在,会返回nil(null),然后设置新值
(nil)
127.0.0.1:6379> get sqlan
"redis"
127.0.0.1:6379> getset sqlan hbase
"redis"
127.0.0.1:6379> get sqlan
"hbase"

类似于Redis中String这样的使用场景,value值可以是字符串,也可以是其他类型

String的存储的字符串长度最大可以达到512M

主要用途

  • 计数器
  • 统计多单位的数量
  • 一个用户的粉丝数
  • 一个有过期时间的验证码

4.2 List(列表)

Redis中的List列表可以做很多事情,可以将其看成数据结构中的栈,也可以是队列,或者阻塞队列

命令 作用 关键字
LPUSH key value1 value2 … 设置一个key,从头部插入数据(头插法) lpush
RPUSH key value1 value2 … 设置一个key,从尾部插入数据(尾插法) rpush
LRANGE key startIndex endIndex 返回列表中从开始索引到结束索引位置的value值 lrange
LPOP key 从key头部弹出一个value lpop
RPOP key 从尾部弹出一个value rpop
LINDEX index 返回key中指定索引的value值 lindex
LREM key n value 删除key中的指定的value值,n代表删除几个 lrem
LLEN key 返回key的长度 llen
LTRIM key startIndex endIndex 截取key,截取的范围从开始索引到结束索引 ltrim
LSET key index value 从当前key的索引开始插入指定的value值 lset
RPOPLPUSH key1 key2 从key1的尾部弹出一个元素,将此元素从key2的头部插入 (转移)
LINSERT key BEFORE 从指定key中已存在的value的前面插入一个指定的value
AFTER oldValue newValue 从指定key后面插入一个指定的value

1、插入

127.0.0.1:6379> lpush mylist a b c # 头插法
3
127.0.0.1:6379> lrange mylist 0 2 # 查看
c
b
a
127.0.0.1:6379> RPUSH list2 a b c #尾插法
3
127.0.0.1:6379> lrange list2 0 2
a
b
c
127.0.0.1:6379> llen list2 # 返回长度
2

2、弹出

127.0.0.1:6379> lpop mylist # 头出
c
127.0.0.1:6379> lrange mylist 0 2
b
a
127.0.0.1:6379> rpop list2  #尾出
c
127.0.0.1:6379> lrange list2 0 2
a
b
127.0.0.1:6379> lindex list2  1 # 定位
b
127.0.0.1:6379> lpush list4 a b c d
4
127.0.0.1:6379> LREM list4 2 b # 删除
1
127.0.0.1:6379> lrange list4 0 8
d
c
a

3、截取

127.0.0.1:6379> lpush list3 a b c d  
4                                   
127.0.0.1:6379> ltrim list3 1 2    # 截取
OK                                  
127.0.0.1:6379> lrange list3 0 8     
c                                 
b      
127.0.0.1:6379> lpush list4 a b c d
4
127.0.0.1:6379> RPOPLPUSH list3 list4 # 转移
sss
127.0.0.1:6379> lrange list4 0 8
sss
d
c
b
a

4、指定value插入

127.0.0.1:6379> lpush list5 a b c d
4
127.0.0.1:6379> lrange list5 0 -1
d
c
b
a
127.0.0.1:6379> lrange list5 0 8
d
c
b
a
127.0.0.1:6379> linsert list5 before b ssr # 从指定 value值的前面 插入
5
127.0.0.1:6379> lrange list5 0 8
d                                         
c                                         
ssr                                       
b                                         
a                                                                              
127.0.0.1:6379> linsert list5 after b ddt  # 从指定 value值的后面 插入
7                                         
127.0.0.1:6379> lrange list5 0 8          
d                                         
c                                         
ssr                                       
b                                         
ddt 
a

4.3 set(集合)

set集合无序不重复

命令 作用 关键词
SADD key value1 value2 … 设置一个key sadd
SMEMBERS key 查看当前key smembers
SISMEMBER key value 查看key中指定的value是否存在 sismember
SCARD key 查看key的长度 scard
SREM key value 删除key中的指定value srem
SPOP key 随机删除key中的一个value spop
SRANDMEMBER key [n] 随机查看当前key中的一个或者多个value srandmember
SMOVE key1 key2 key1Value 将key1中的value移动到key2中 smove
SDIFF key1 key2 两个key相交,求第一个key的补集 sdiff
SINTER key1 key2 两个key相交,求交集 sinter
SUNION key1 key2 两个key相交,求并集 sunion

1、设置set

127.0.0.1:6379> sadd set1 a b c # 向集合添加元素
3                              
127.0.0.1:6379> smembers set1   # 查看所有
c                              
b                              
a                              
127.0.0.1:6379> sadd set1 a b c # 集合无序不重复
0                              
127.0.0.1:6379> sadd set1 d    
1                              
127.0.0.1:6379> smembers set1  
d                              
c                              
b                              
a    
127.0.0.1:6379> scard set1 # 查看key的长度
4

2、删除

127.0.0.1:6379> sismember set1 a # 查看key中指定的value是否存在
1  # 1 表示存在
127.0.0.1:6379> sismember set1 s
0  # 1 表示不存在         
127.0.0.1:6379> SMEMBERS set1  # 查看所有
d                            
c                            
b                            
a                            
127.0.0.1:6379> srem set1 d    # 指定的value 
1                             
127.0.0.1:6379> spop set1   # 随机删除        
c
127.0.0.1:6379> SMEMBERS set1 
b                             
a   
127.0.0.1:6379> sadd set2  f g    
2                                 
127.0.0.1:6379> smove set2 set1 f # 移动
1                                 
127.0.0.1:6379> SMEMBERS set1     
f                                 
b                                 
a
127.0.0.1:6379> SRANDMEMBER set1 # 随机抽取
f

2、集合

生活中的一个小现象,就比如说微信公众号,会有共同关注,还有QQ的共同好友

数学集合关系中的:交、并、补。微信公众号中的共同关注,以及QQ的共同好友,就是关系中的交!

127.0.0.1:6379> sadd set3 a b c  
3                                
127.0.0.1:6379> sadd set4 a c d  
3                                
127.0.0.1:6379> sdiff set3 set4  # 求第一个key的补集
b                                
127.0.0.1:6379> sinter set3 set4 # 求交集
c                                
a                                
127.0.0.1:6379> sunion set3 set4 # 求交集
c                                
b                                
a                                
d                                          

命令都可以在英语单词中找到一些规律
把SDIFF、SINTER还有SUNION这三个单词首字母去掉,可以得到
DIFF:different,它代表不同的,用一句Redis官网的翻译来描述:返回的集合元素是第一个key的集合与后面所有key的集合的差集
INTER:intersection,翻译过来为交叉,同样的,意指数学关系中的交集
UNION:union,翻译为联合,与数学关系中的并集也是可以沾边的

4.4 Hash(哈希)

Redis中的哈希,本质上KV相同但是KV中的V,它也是一个键值对,本质和操作字符串区别不大

命令 作用 关键字
HSET key field value 设置单个hash hset
HGET key field 获取单个 hget
HMSET key field1 v1 field2 v2 设置多个 hmset
HMGET key field 获取多个 hmget
HGETALL key 获取hash中全部的field-value hgetall
HLEN key 获取hash长度 hlen
HEXISTS key field 查询hash中指定的field是否存在 hexists
HKEYS key 只获取hash中的field hkeys
HVALS key 只获取hash中value hvals
HINCRBY key field n 对hash中指定的field设置自增自减 hincrby

1、创建hash

127.0.0.1:6379> hset hash1 name zs    #  设置单个  hash  
1                                              
127.0.0.1:6379> hget hash1 name      # 获取单个 hash         
zs                                             
127.0.0.1:6379> hmset hash2 name joy age 23    #  设置多个
OK                                             
127.0.0.1:6379> hmget hash2 name age      #    获取多个  
joy                                            
23                                                                

2、获取

127.0.0.1:6379> hgetall hash1  # 获取hash中全部的 键值对
name
zs
127.0.0.1:6379> hlen hash1  # 获取长度
1
127.0.0.1:6379> hkeys hash2 # 获取全部的键
name
age
127.0.0.1:6379> hvals hash2 # 获取全部的值
joy
23
127.0.0.1:6379> hset hash3 age 23 
1
127.0.0.1:6379> hincrby hash3 age 25 # 自增23
48

3、使用“:”

可以使用hash做一些临时变更的数据,可以是用户信息,或者是经常变动的信息,上面的String也提到了使用“:”进行层次分割,不过hash更适合对象存储,String适合于文本的存储

127.0.0.1:6379> HMSET user:1 name xiaohuang age 21 sex boy
OK
127.0.0.1:6379> HGETALL user:1
1) "name"
2) "xiaohuang"
3) "age"
4) "21"
5) "sex"
6) "boy"

4.5 Zset(有序集合)

在set的基础上增加了一个score的值,相当于zset k1 score v1,使用score来对当前key中元素进行排序

命令 作用 关键字
ZADD key score1 value1 score2 value2 … zset中添加一个或多个元素 zadd
ZRANGE key startIndex endIndex 查询从开始到结束索引的zset集合 zrange
ZRANGEBYSCORE key min max [WITHSCORES] 对hash中按照指定数值进行升序排列
ZREVRANGE key startIndex endIndex 对指定开始和结束索引进行降序排列
ZREM key field 删除hash中指定的field zrem
ZCARD key 查询hash长度 zcard
ZCOUNT key [min max] 查询hash数量,还可以增加最大值和最小值的范围 zcount

1、

127.0.0.1:6379> zadd set1 1 one # 添加一个元素
1
127.0.0.1:6379> zadd set1 2 tew 3 three # 添加多个元素
2
127.0.0.1:6379> zrange set1 0 -1 # 查询从开始到结束索引的zset集合
one
tew
three
127.0.0.1:6379>

2、实现元素的排序

# 根据zset中score的值来实现元素的排序
127.0.0.1:6379> ZADD salary 3500 xiaohong 6500 xiaohuang 3900 zhangsan
(integer) 3
# 当前命令,inf在Unix系统中代表的意思是无穷,所以当前命令是指,将当前zset,以从小到大的形式进行排列
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf 
1) "xiaohong"
2) "zhangsan"
3) "xiaohuang"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf withscores # 在排列的同时,将score和指定的元素全部展示
1) "xiaohong"
2) "3500"
3) "zhangsan"
4) "3900"
5) "xiaohuang"
6) "6500"
127.0.0.1:6379> ZREVRANGE salary 0 -1 withscores # 将数据从大到小进行排列
1) "xiaohuang"
2) "6500"
3) "zhangsan"
4) "3900"
5) "xiaohong"
6) "3500"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf 4000 withscores # 展示的同时还可以指示score的查询最大值,指定查询范围
1) "xiaohong"
2) "3500"
3) "zhangsan"
4) "3900"
127.0.0.1:6379> ZREM salary zhangsan # 删除zset中的一个元素
(integer) 1
127.0.0.1:6379> ZRANGE salary 0 -1 
1) "xiaohong"
2) "xiaohuang"
127.0.0.1:6379> ZCARD salary
(integer) 2

3、

127.0.0.1:6379> ZADD myset 1 hello 2 world 3 xiaohuang 4 xiaohei 5 xiaolan
(integer) 5
# 语法:ZCOUNT key min max ,min和max包左也包右,它是一个闭区间
127.0.0.1:6379> ZCOUNT myset 2 5 # 获取指定区间的成员数量
(integer) 4
127.0.0.1:6379> 

其他

其他的API,如果说在工作中出现了,可以查看Redis的官方文档:http://www.redis.cn/commands.html

案例:zset是Redis的数据类型,可以排序,生活中也有案例,班级成绩,员工工资

设置权重,1、普通消息;2、重要消息;添加权重进行消息判断其重要性

来一个更接地气的案例,可以打开B站,排行榜,B站会根据视频的浏览量和弹幕量进行综合评分,进行排名

5、三种特殊数据类型

5.1 geospatial 地理位置

微信朋友圈中的朋友的位置,或者是QQ中也有的附近的人,饿了么中外卖小哥的位置距离

这个在Redis中被定为特殊的数据类型可叫做Geo,它是Redis3.2正式推出的一个特性,可以推导出两个地方的地理位置,两地之间的距离,方圆几千米之内的人。

对于这个关于地理的数据类型,它有6个命令

关键词 命令 作用
geoadd GEOADD key 经度 纬度 城市名称 添加地理位置
geodist GEODIST key member1 member2 [unit] 指定两个位置的距离
geohash GEOHASH key member 返回一个或多个元素的GeoHash表示,该命令返回11个字符组成的GeoHash字符串
geopos GEOPOS key member1 member2 … 获取一个或多个地理信息
georadius GEORADIUS key 经度 纬度 半径 [单位] [WITHCOORD(搜寻到的目标的经纬度)] [WITHDIST(直线距离)] [count] 自己所在的地址为圆心,半径查找
georadiusbymember GEORADIUSBYMEMBER key member 长度 [unit]单位 找出指定元素周围的其他元素,就是以城市为中心,一定长度为半径搜索

因为这个特殊的数据类型和地理相关,需要用到地理的经纬度,可以推荐一个网站查看指定城市的经纬度:http://www.jsons.cn/lngcode/

1、geoadd 添加地理位置

​ 语法:GEOADD key 经度 纬度 城市名称 …

​ 注意:南北极无法直接添加。用添加城市数据来说,一般都会使用Java的Jedis来操作,而这些城市数据都是被下载下来通过JavaAPI调用
​ 有效经度从-180到180度
​ 有效纬度从-85.05112878 到 85.05112878 度。超过范围会出现(error) ERR invalid longitude,latitude pair

127.0.0.1:6379> GEOADD china:city 116.40 39.90 beijing 121.47 31.23 shanghai # 添加
2
127.0.0.1:6379> GEOHASH china:city beijing   # 返回GeoHash字符串
wx4fbxxfke0                                  
127.0.0.1:6379> ZRANGE china:city 0 -1      # 使用zset命令查看geospatial
shanghai                                     
beijing 
127.0.0.1:6379> ZREM china:city beijing # 使用zset的基本命令即可删除
1
127.0.0.1:6379> ZRANGE china:city 0 -1 
shanghai

2、geodist

单位:m表示单位米、km表示千米、mi表示英里、ft表示英尺

语法:GEODIST key member1 member2 [unit]

# 查看beijing和shanghai两个位置的直线距离
127.0.0.1:6379> GEOADD china:city 116.40 39.90 beijing 121.47 31.23 shanghai 
1
127.0.0.1:6379> GEODIST china:city beijing shanghai # 单位米
1067378.7564
127.0.0.1:6379> GEODIST china:city beijing shanghai km # 单位千米
1067.3788

3、georadius

自己所在的地址为圆心,半径查找

对于社交软件来说,附近的人,就相当于,你现在所在的地址,再加上一定的半径来进行查找

GEORADIUS key 经度 纬度 半径 [单位] [WITHCOORD(搜寻到的目标的经纬度)] [WITHDIST(直线距离)] [count]

# 以111经度31纬度为中心,1000km为半径搜寻在器范围之内的城市
127.0.0.1:6379> GEORADIUS china:city 111 31 1000 km 
1) "shenzhen"
2) "guangzhou"
3) "fuzhou"
4) "shanghai"

# 追加参数,目标经纬度,直线距离
127.0.0.1:6379> GEORADIUS china:city 111 31 1000 km WITHCOORD WITHDIST 
# ...

# 还可以限制查询的结果条数,只显示两条
127.0.0.1:6379> GEORADIUS china:city 111 31 1000 km WITHCOORD WITHDIST count 2 
1) 1) "guangzhou"
   2) "905.0108"
   3) 1) "113.27999979257583618"
      2) "23.1199990030198208"
# ...

4、GEORADIUSBYMEMBER

找出指定元素周围的其他元素,就是以城市为中心,一定长度为半径搜索

# 找出以shanghai为中心,1000km为半径搜索
127.0.0.1:6379> GEORADIUSBYMEMBER china:city shanghai 1000 km 
1) "xiamen"
2) "fuzhou"
3) "shanghai"

5.2 Hyperloglog

在讲Hyperloglog之前,什么是基数?

集合中包含的不重复元素即为基数,就比如一个A数据集,A{1,3.7,9,11},它的基数为5,可以接受误差

Hyperloglog是Redis2.8.9更新的,它是一种数据结构,主要是针对于基数统计的算法

优点,占用的内存很小,只需要使用12KB的内存即可统计2^64的数据

​ 在实际业务中,网页的UV(Unique Visitor,独立访客),一个人访问一个网站多次,只能算作是一个,用传统的方式,set集合保存用户的id,然后统计set中元素个数作为标准来判断。使用这种方式来进行数据统计的话,大量的内存用来浪费给保存用户id了,目的是为了计数,而不是为了保存用户id

Hyperloglog计数的错误率在0.81%,用来执行UV任务,可以忽略不计

关键词 命令 作用
pfadd PFADD key value1 value2… 创建一组数据集,如果数据集中有相同的元素就会有去重效果
pfcount PFCOUNT key 查看元素的长度
pfmerge PFMERGE key3 key1 key2 将两组元素合并成一个新数组,并带有去重效果,相当于数学中的并集
127.0.0.1:6379> pfadd pf1 a b c d e f g h i j # 创建
1                                            
127.0.0.1:6379> pfcount pf1      # 查看元素的长度            
10                                           
127.0.0.1:6379> pfadd pf2 1 2 3 4            
1                                            
127.0.0.1:6379> PFMERGE pf1 pf2    # 合并数组          
OK                                           
127.0.0.1:6379> pfcount pf1                  
14                                           

如果在项目中允许容错,可以使用Hyperloglog

如果不行,就可以直接使用set或者Java的HashMap来实现

5.3 Bitmaps

Bitmaps是一种位存储的数据类型,在Redis2.2.0被推出,

生活中可以实现的场景,统计活跃用户,在线状态,用户签到,这些都是表示两种状态之间的,可以使用Bitmaps

Bitmaps,译为位图,也是一种数据结构,操作二进制位进行记录,只有0和1两种状态。Bitmaps通过最小的单位bit来进行存储

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值