Redis

Redis

1、概述

NoSQL

技术的发展

解决功能性的问题:JAVA、JSP、RDBMS、Tomcat、HTML、Linux、JDBC、SVN

解决扩展性的问题:Struts、Spring、SpringMVC、Hibernate、MyBatis

解决性能的问题:NoSQL、JAVA线程、Hadoop、Nginx、MQ、ElasticSearch

https://www.cnblogs.com/superxuezhazha/p/13643873.html

缓存数据库:减少IO操作

NoSQL: Not Only SQL,意为"不仅仅是SQL",泛指非关系型数据库。

NoSQL不依赖业务逻辑的方式进行存储,使用简单的Key-Value键值对进行存储。

  • 不遵循SQL标准
  • 不支持ACID(不支持四个特性,而不是不支持事务)
  • 远超于关系型数据库的性能
ACID,是指数据库管理系统(DBMS)在写入或更新资料的过程中,为保证事务(transaction)是正确可靠的,所必须具备的四个特性:
原子性(atomicity,或称不可分割性)
一致性(consistency)
隔离性(isolation,又称独立性)
持久性(durability)

适用场景

  • 高并发数据的读写
  • 海量数据的读写
  • 对数据高可扩展性的

不适用场景

  • 需要事务支持
  • 基于SQL的结构化查询存储,处理复杂的关系。
  • 用不着SQL,或者用SQL也不能解决

常见的NoSQL数据库

  1. Memcache

    • 很早出现的NoSQL数据库
    • 数据存储在内存中,一般不做持久化
    • 支持简单的Key-Value模式,支持的类型单一(字符串)
    • 作为缓存数据库辅助持久化的数据库
  2. Redis

    • 几乎覆盖了Memcache的绝大部分功能
    • 开源
    • 数据都在内存中,支持持久化,主要用作备份恢复
    • 除了支持简单的Key-Value模式,还支持多种数据结构的存储,比如List、Set、Hash、ZSet等
    • 一般是作为缓存数据库辅助持久化的数据库
  3. MongoDB

    • 高性能、开源、模式自由(schema free)的文档型数据库
    • 数据都在内存中,如果内存不足,把不常用的数据保存到硬盘
    • 虽然是Key-Value模式,但是对Value(尤其是Json)提供了丰富的查询功能
    • 支持二进制数据与大型对象
    • 可以根据数据的特点替代RDBMS(关系数据库管理系统),成为独立的数据库。或者配合RDBMS,存储特定的数据。

(120条消息) Redis和MongoDB的区别(面试受用)_孜孜不倦,不紧不慢的博客-CSDN博客_mongodb redis

2、安装

这里我使用的是Docker的虚拟环境,在官网下载并安装Docker,然后将WSL2问题(Linux的内核)处理完成之后,在DockerHUB中搜索Redis,然后往下找到quickStart,在控制台中输入,Docker自动构建运行环境。

主要步骤

  1. 检查电脑的CPU是否支持虚拟化
  2. 打开Docker官网
  3. 下载DockerWindows端
  4. 安装并重启电脑
  5. 打开Docker,检查是否有WSL2问题,若有问题继续往下步骤执行
  6. 打开提示的网页,根据提示的步骤进行更改计算机运行环境
  7. 下载安装Linux内核(大概16MB)
  8. 打开微软商店搜索Linux或者Ubuntu,选择习惯的版本进行安装
  9. 安装后打开,输入姓名和密码(也可以不进行设置)
  10. 然后重启电脑(重新加载内核)
  11. 打开Docker,跳过新手引导
  12. 打开DockerHUB–>https://hub.docker.com/
  13. 左上角搜索Redis
  14. 然后打开Redis的详情页面,找到【How to use this image】
  15. 打开Windows控制台,将【start a redis instance】中的代码去掉$执行
  16. 等待镜像安装
  17. 完成安装
  18. 打开Docker,发现创建的实例已经在Docker中,点击控制台即可。

3、相关知识

  • Redis的端口号为6379

  • 默认有16个数据库,下标从0开始

    • 使用select 来切换数据库,例如 select 8
  • 统一密码管理,所有库相同的密码

  • dbsize查看当前数据库的key数量

  • flushdb清空当前库

  • flushall清空所有库

Redis使用的技术

Redis使用的是单线程+多路IO复用技术

多路复用是指一个线程来检查多个文件描述符Socket的就绪状态,比如调用select和poll函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞直到超时。

得到就绪状态后进行真正的操作,可以在同一个线程里面执行,也可以启动线程执行(比如线程池)

4、基本操作

Key操作

添加key

set [key]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JmozSeVC-1690358602374)(./Redis.assets/image-20220902161447719.png)]

获取key的值

get [key]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FpFUpSIO-1690358602379)(./Redis.assets/image-20220902161451927.png)]

查看所有key

keys *

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ByiqJLFt-1690358602383)(./Redis.assets/image-20220902161201558.png)]

判断某个key是否存在

exists [key]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3J4LRNao-1690358602388)(./Redis.assets/image-20220902161233296.png)]

查看key的类型

type [key]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IYBeWQ3K-1690358602393)(./Redis.assets/image-20220902161318783.png)]

删除指定的key

del [key]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n5detPed-1690358602397)(./Redis.assets/image-20220902161529192.png)]

异步删除key

unlink [key]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CDuW0YAm-1690358602402)(./Redis.assets/image-20220902161618343.png)]

设置key的过期时间

empire [key] 10 

单位:秒。10秒后key将会自动销毁。当过期时间为-1时,永不过期。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jk1z0iT9-1690358602406)(./Redis.assets/image-20220902161837854.png)]

时间过了之后:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zyIf8kZm-1690358602411)(./Redis.assets/image-20220902161923495.png)]

get不到Key3

查看过期时间

ttl [key]

查看key还有多少秒过期,-1表示永不过期,-2表示已经过期

未过期:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P2GaagdF-1690358602415)(./Redis.assets/image-20220902161842607.png)]

已过期:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ssgTlVYA-1690358602420)(./Redis.assets/image-20220902161853806.png)]

切换数据库

select 

切换数据库,如select 1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tXCiISEd-1690358602424)(./Redis.assets/image-20220902162050873.png)]

查看当前数据库的key数量

dbsize

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xasJq1F2-1690358602429)(./Redis.assets/image-20220902162038735.png)]

清空当前库

flushdb

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wcDF1NS4-1690358602433)(./Redis.assets/image-20220902162201063.png)]

清空所有库

flushall

5、Redis的基本数据类型

5.1、String字符串

5.1.1、概要、数据结构

String是Redis最基本的类型。一个key对应一个Value。

String类型是二进制安全的,意味着Redis的String可以包含任何数据。比如jpeg图片或者序列化的对象。

String类型是Redis最基本的数据类型,一个Redis中字符串value最多可以是512M

数据结构

String的数据结构为简单动态字符串(Simple Dynamic String,SDS)。

是可以修改的字符串,内部结构实现类似于Java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配。

当前实际分配的空间一般要高于实际字符长度,当字符串小于1M时,扩容都是加倍现有的空间,扩容时一次只会多扩1M的空间。

需要注意的是字符串最大长度为512M。

5.1.2、常用命令

set

添加

set [key] [value]

设置key和value的一对一对应

除此之外,set还有其它的用法:

*nx:当数据库中key不存在时,才可以将key-value添加到数据库
*xx:当数据库中key存在时,才可以将key-value添加到数据库,与nx互斥
*ex:key的超时秒数
*px:key的超时毫秒数,与ex互斥

使用方法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PuV7RKfH-1690358602438)(./Redis.assets/image-20220902163638083.png)]

在set后面加上后缀即可(上图是 *nx 的效果,即只有当数据库中的key1不存在时,才可以将key1添加到数据库,第一次成功,第二次失败)。

同时添加过期时间

通过以下命令,在创建key时,同时赋值key的过期时间,单位:秒

setex age 10 22

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ggQpNQsY-1690358602442)(./Redis.assets/image-20220902170116919.png)]

get

获取某个key所对应的值

get [key]

getset

以新换旧

设置新值的时候同时获取旧值。

getset [key] [value]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wQzllhYH-1690358602447)(./Redis.assets/image-20220902170309138.png)]

append

在key后面追加内容

append [key] [value]

在该key原有的value后面添加value,如:

key1原value为a,在执行append key1 b后,key1的value变为 ab

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jxAqxmOT-1690358602451)(./Redis.assets/image-20220902163910755.png)]

strlen

长度

strlen [key]

获取某个键的value长度

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-85HGKRi0-1690358602456)(./Redis.assets/image-20220902164033078.png)]

自增和自减

与java、C++中的i++自增不同,Redis的自增操作具有原子性,操作一次完成,不会被其它操作打断。

原子操作指的是不会被线程调度机制打断的操作。

在单线程中,能够在单条指令中完成的操作都可以认为是[原子操作],因为终端只能发生于指令之间

在多线程中,不能被其它进程(线程)打断的操作就叫做[原子操作]。

Redis单命令的原子性主要得益于Redis是单线程操作。

incr

自增

incr [key]

要求该key必须为数字类型,即不能有任何的其它字符出现

若该key为空,则新增值为1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kh4TuEin-1690358602460)(./Redis.assets/image-20220902164235121.png)]

decr

自减

decr [key]

同样要求该key必须为数字类型,即不能有任何的其它字符出现

若key值为空,则新增值为-1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RMHykwMU-1690358602465)(./Redis.assets/image-20220902164246438.png)]

[根据步长]

自增/自减

incrby / decrby [key] [步长]

将key中存储的值(需为数字)按照步长增减。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NQifyJn0-1690358602469)(./Redis.assets/image-20220902164545669.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HKdi283n-1690358602474)(./Redis.assets/image-20220902164556151.png)]

多个Key操作

mset

添加多个

mset [key1] [value1] [key2] [value2] ...
或者与后缀结合使用
msetnx [key1] [value1] [key2] [value2] ...

可以同时设置多个key-value的键值对

原子性,有一个失败则全都失败

mget

获取多个key的值

mget [key1] [key2] [key3]

原子性,有一个失败则全都失败

getrange

切割字符串

getrange [key] [起始位置] [结束位置]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BdcHiszN-1690358602479)(./Redis.assets/image-20220902165804668.png)]

setrange

setrange [key] [起始位置] [value]

赋值字符串

用value覆盖key所在的字符串值,从[起始位置]开始。【默认索引从0开始】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1GhsR2z3-1690358602483)(./Redis.assets/image-20220902165918009.png)]

5.2、List列表

5.2.1、概要、数据结构

单键多值

Redis列表是简单的字符串列表,按照插入顺序排序。

可以添加元素到列表的左边或者右边(头部或者尾部)

底层实现是双向链表,对两端的操作性能很高,但是通过索引访问中间性能较差(链表的特效:查询效率低,插入效率高)

数据结构

List的数据结构为快速链表quickList

首先在列表元素较少的情况下会使用一块连续的内存进行存储,这个结构是zipList,也就是压缩列表。

它将所有的元素紧挨着一起存储,分配的是一块连续的内存。

当数据量较多时,会改为quickList。

因为普通的链表需要的附加指针空间太大,会比较浪费空间。

Redis将链表和ZipList结合起来组成了quickList。也就是将多个ZipList使用双向指针串起来使用。

这样既满足快速插入删除的性能,又不会出现太大的空间冗余

5.2.2、常用命令

lpush/rpush

lpush:left push 往列表左边添加(头插法)

rpush:right push 往列表右边添加(尾插法)

lpush/rpush [key1] [value1] [value2] [value3] ...

lrange

从左到右遍历

lrange [key] [start] [end]

当end为-1 时,取出所有值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aYfLusbp-1690358602488)(./Redis.assets/image-20220905111159533.png)]

注意lrange是从左边取过去的,如果插入时使用的是lpush,则会获得相反的答案

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OtqLlg4Z-1690358602492)(./Redis.assets/image-20220905110950198.png)]

lpop/rpop

lpop/rpop [key] [count]

从左边或者右边弹出一个值。count可以不加,也可以加,表示要弹出的个数。

执行:

lpop k3 

可以看到lpop弹出的是第一个v1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f2xh9BI0-1690358602497)(./Redis.assets/image-20220905111841536.png)]

弹出之后,k3的v1元素消失了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tz7IC1mE-1690358602502)(./Redis.assets/image-20220905111905708.png)]

我们再执行

rpop k3

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tKOmMjKN-1690358602506)(./Redis.assets/image-20220905112038249.png)]

rpoplpush

rpoplpush [key1] [key2]

将key1列表中的最右边的数push刀key2的最左边

从key1尾部取出一个节点,使用头插法插到key2列表中。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eXgeMAu8-1690358602511)(./Redis.assets/image-20220905145359772.png)]

lindex

lindex [key] [index]

取出列表中对应下标index的数(下标从0开始)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9tRI00Ol-1690358602515)(./Redis.assets/image-20220905145711899.png)]

llen

llen [key]

获取列表的长度

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l8cMNl3S-1690358602520)(./Redis.assets/image-20220905145840240.png)]

linsert

linsert [key] before/after [value] [newvalue]

指定位置插入值,在key中的value值前/后插入newvalue

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qMy67J3N-1690358602524)(./Redis.assets/image-20220905150414570.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EAQn6sG3-1690358602529)(./Redis.assets/image-20220905150445921.png)]

lrem

lrem [key] [n] [value]

从左边删除n个Value

例如:删除0个v0

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GUttK1K4-1690358602534)(./Redis.assets/image-20220905150625286.png)]

lset

lset [key] [index] [value]

将key中下表为index的元素的值,替换为value

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lBIZ0uR4-1690358602538)(./Redis.assets/image-20220905150844379.png)]

5.3、Set无序集合

5.3.1、概要、数据结构

Redis Set对外提供的功能与List类似,是一个列表的功能。

其特殊之处在于set是可以自动排重(排除重复)的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择。

set提供了判断某个成员是否在一个set集合中的重要接口,这个也是list所不能提供的。

Redis 的 Set 是String类型的无序集合。它的底层其实是一个value为null的hash表,所以添加、删除、查找的复杂度都是0(1)。

O(1)是最低的时空复杂度,也就是耗时/耗空间与输入数据大小无关,无论输入数据增大多少倍,耗时/耗空间都不变。

无序集合:每次取出的顺序可能会不同

数据结构

Set数据结构是dict字典,字典是用哈希表实现的。

Java中的HashSet的内部实现使用的是HashMap,只不过所有的value都指向同一个对象。

Redis的Set结构也是一样,它的内部也使用hash结构,所有的value都指向同一个内部值。

5.3.2、常用命令

sadd

sadd [key] [value1] [value2] ...

添加一个或者多个数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WAJ1Z1sO-1690358602543)(./Redis.assets/image-20220905152408313.png)]

smembers

smembers [key]

取出所有值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U50VnX01-1690358602547)(./Redis.assets/image-20220905152451232.png)]

sismember

sismember [key] [value]

判断该key中是否有value,1为真,0为假。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tuSo9M9m-1690358602552)(./Redis.assets/image-20220905152631426.png)]

scard

scard [key]

查看set中元素的总个数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bIzPGb3C-1690358602556)(./Redis.assets/image-20220905152720709.png)]

srem

srem [key] [value1] [value2]

删除某个key中与value相同的元素

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cLJEcNHf-1690358602561)(./Redis.assets/image-20220905152838684.png)]

因为set是无序的,所以返回的顺序不一致。

spop

spop [key] [count]

从该集合中随机取出一个值,取出之后,对应的元素消失

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mnZ6PTbF-1690358602566)(./Redis.assets/image-20220905153025973.png)]

注意存入的顺序和取出的顺序。

存入的顺序和取出的顺序不一致,与列表不同,所以是随机取出一个值。

srandmember

随机从该集合中取出n个值,不会从集合中删除[srandmember]

srandmember [key] [n]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YasOERyl-1690358602571)(./Redis.assets/image-20220905153729110.png)]

[smove]

把集合中的某个值,移动到另一个集合

smove [key1] [key2] [value]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SyHwDZ6F-1690358602575)(./Redis.assets/image-20220905154004198.png)]

sinter

返回两个集合的交集

sinter [key1] [key2]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kojlLbFL-1690358602580)(./Redis.assets/image-20220905154245191.png)]

sunion

返回两个集合的并集

sunion [key1] [key2]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1xJVakOm-1690358602584)(./Redis.assets/image-20220905154258324.png)]

sdiff

返回两个元素的差集

sdiff [key1] [key2]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rGfq1aAS-1690358602589)(./Redis.assets/image-20220905154310040.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wcXdASsr-1690358602594)(./Redis.assets/image-20220905154313424.png)]

5.4、Hash哈希表

5.4.1、概要、数据结构

Redis Hash 是一个键值对集合

Redis Hash 是一个String类型的 field 和 value 的映射表,hash特别适合用于存储对象

类似Java里面的Map

用户ID为查找的Key,存储的Value对象包含姓名、年龄、生日等信息,如果使用普通的key/value机构来存储

数据结构

Hash类型对应的数据结构有两种:ZipList(压缩列表),HashTable(哈希表)。

当field-value长度较短且个数较少时,使用ZipList,否则使用HashTable。

5.4.2、常用命令

hset

创建一个hash对象,给key使用value赋值

hset [key] [field] [value]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RYPb47g8-1690358602598)(./Redis.assets/image-20220906154507999.png)]

执行完成之后,key为user1,value field中有id和name属性。

user1
user1.id = 1001
user1.name = zhangsan

hget

获取某个key的某个属性值

hget [key] [field]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QOAkJlVS-1690358602603)(./Redis.assets/image-20220906160920878.png)]

hmset

跟hset类似,可以同时设置多个field的值

hmset [key] [field1] [value1] [field2] [value2] ...

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BEoLRuiL-1690358602607)(./Redis.assets/image-20220906161129406.png)]

hexists

判断给定的key中的field是否存在

非0为真,1为true,0为false

hexists [key] [field]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GSFPNmw8-1690358602612)(./Redis.assets/image-20220906161302006.png)]

hkeys

列出key中的所有field

hkeys [key]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-siRIuS2v-1690358602617)(./Redis.assets/image-20220906161418152.png)]

hvals

列出key的所有value

hvals [key]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nmaEHCx8-1690358602621)(./Redis.assets/image-20220906161443468.png)]

hincrby

为hash表key中的field中的值增加一定的值

increment为增加的步长

hincrby [key] [field] [increment]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TRqqL9TJ-1690358602626)(./Redis.assets/image-20220906161741266.png)]

hsetnx

只有key中没有该field时,将hash表中的field值设置为value

无法覆盖原有值

hsetnx [key] [field] [value]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QwDyK7Kp-1690358602630)(./Redis.assets/image-20220906162022376.png)]

5.5、ZSet有序集合

5.5.1、概要、数据结构

Redis有序集合zset与普通集合set非常相似,是一个没有重复元素的字符串集合。

不同之处是有序集合的每个成员都关联了一个评分(Score),这个评分被用来按照从低分到最高分的方式排序集合中的成员。

集合的成员是唯一的,但是评分可以重复。

因为元素是有序的,所以你也可以很快的根据评分或者次序来获取一个范围中的元素。

访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。

数据结构

SortedSet(zset)是Redis提供的一个非常特别的数据结构,一方面它等价于java中Map,可以给每个元素value赋予一个权重score

另一方面他又类似于TreeSet,内部的元素会按照权重score进行排序,可以得到每个元素的名次,还可以通过范围进行获取元素。

zset底层使用了两个数据结构:

1、hash。hash的作用就是关联数据元素value和权重score,保障元素value的唯一性,可以通过元素value找到相应的score值。

2、跳跃表。跳跃表的目的在于给元素value排序,根据score的范围获取元素列表。

跳跃表

有序集合在生活中比较常见,例如根据成绩对学生进行排名,根据得分对玩家排名等。

对于有序集合的底层实现,可以用数组、平衡树、链表等。

数组不便元素的插入和删除。

平衡树或者红黑树虽然效率高,但是结构复杂。

链表查询需要遍历所有的元素,效率低。

Redis采用的是跳跃表,跳跃表的效率跟红黑树差不多,但是比红黑树简单。

寻找51

有序链表:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XJQUEsoa-1690358602635)(./Redis.assets/image-20220906182233393.png)]

跳跃表:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hc7oRH6d-1690358602639)(./Redis.assets/image-20220906182247303.png)]

首先是往第二层找,找到1和21,由于我们要找的是51,21后面是空,所以根据几点21进入第一层

然后21后面连接了41,41比51小,所以继续往后,而41之后是61,51比61小,所以根据41找到第0层

到达第0层之后,就可以看到41后面指向51。经过了4次查找,寻找完成。

5.5.2、常用命令

zadd

将一个或多个member元素及其score值加入到有序集合key当中。

zadd [key] [score1] [value1] [score2] [value2] ...

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xdHjoon9-1690358602644)(./Redis.assets/image-20220906162901901.png)]

zrange

返回对应key中,满足设定范围的score对应的值。

按照从小到大排序。

zrange [key] [min] [max]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ga9dbmfL-1690358602648)(./Redis.assets/image-20220906163059329.png)]

zrangebyscore

在对应的key中,返回满足范围条件的score对应的值。(是具体的数值,不能使用-1来遍历所有的数据)

按照从大到小排序。且min和max为具体的数字。

withscores 是将分数也一起遍历

注意是先min 然后 输入max

zrangebyscore [key] [min] [max] [withscores] [limit offset count]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VQNWGU8k-1690358602653)(./Redis.assets/image-20220906173929352.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J6WRKWAN-1690358602658)(./Redis.assets/image-20220906173947514.png)]

withscores

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O3mGeeBv-1690358602662)(./Redis.assets/image-20220906174412050.png)]

zrevrangebyscore

返回所有score介于min和max之间(包括min或者max)的成员。

有序集合按score值递增**(从大到小)**排序。

注意是先max,后min

zrevrangebyscore [key] [max] [min] [withscores] [limit offset count]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vX5W8NAh-1690358602667)(./Redis.assets/image-20220906175127045.png)]

zincrby

为元素的score加上增量

zincrby [key] [increment] [value]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-roYuGOjh-1690358602671)(./Redis.assets/image-20220906180039329.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZOCu6Idd-1690358602676)(./Redis.assets/image-20220906180045443.png)]

然后为java添加50的score

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lMhafHJw-1690358602680)(./Redis.assets/image-20220906180758267.png)]

然后可以看到java排到了最后

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TthgesqV-1690358602685)(./Redis.assets/image-20220906180921872.png)]

zrem

删除该集合下,指定值的元素

zrem [key] [value]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0lv58LGL-1690358602689)(./Redis.assets/image-20220906181033406.png)]

zcount

统计区间中的所有元素个数

zcount [key] [min] [max]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TkEuf7SA-1690358602694)(./Redis.assets/image-20220906181117241.png)]

zrank

返回该值在集合中的排名,从0开始

zrank [key] [value]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7pDkDguV-1690358602699)(./Redis.assets/image-20220906181238967.png)]

6、Redis配置文件部分功能

https://blog.csdn.net/qq_19007335/article/details/124885668

需要更改的地方:1、注释 bind 2、更改protected-mode为no

6.1、###Units###

配置大小单位,开头定义了一些基本的度量单位,只支持byte,不支持bit

大小写不敏感

6.2、###Includes###

################################## INCLUDES ###################################

# Include one or more other config files here.  This is useful if you
# have a standard template that goes to all Redis servers but also need
# to customize a few per-server settings.  Include files can include
# other files, so use this wisely.
#
# Notice option "include" won't be rewritten by command "CONFIG REWRITE"
# from admin or Redis Sentinel. Since Redis always uses the last processed
# line as value of a configuration directive, you'd better put includes
# at the beginning of this file to avoid overwriting config change at runtime.
#
# If instead you are interested in using includes to override configuration
# options, it is better to use include as the last line.
#
# include /path/to/local.conf
# include /path/to/other.conf

配置包含、引入的其它配置文件

在这里引入一个或者多个配置文件。如果你有标准的配置模板的话会非常有用,可以将标准的模板配置到所有的Redis服务器上,并为每个单独的服务器配置少量的配置。

引入的文件中可以引入其他的文件,所以需要明智的使用。

要注意Include属性不会管理员或者Redis Sentinel的“config rewrite”命令重写。Redis总是使用最后处理的行作为配置指令的值,你最好将include放在文件的头部,避免在运行时配置文件的重写和更改。

6.3、###Network###

################################## NETWORK #####################################

# By default, if no "bind" configuration directive is specified, Redis listens
# for connections from all the network interfaces available on the server.
# It is possible to listen to just one or multiple selected interfaces using
# the "bind" configuration directive, followed by one or more IP addresses.
# 默认情况下,如果“bind"未被明确指定,Redis会监听此 服务器来自所有可用的网络接口的连接。
# 可能
# Examples:
#
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1 ::1
#
# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the
# internet, binding to all the interfaces is dangerous and will expose the
# instance to everybody on the internet. So by default we uncomment the
# following bind directive, that will force Redis to listen only into
# the IPv4 loopback interface address (this means Redis will be able to
# accept connections only from clients running into the same computer it
# is running).
#
# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES
# JUST COMMENT THE FOLLOWING LINE.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#bind 127.0.0.1

# Protected mode is a layer of security protection, in order to avoid that
# Redis instances left open on the internet are accessed and exploited.
#
# When protected mode is on and if:
#
# 1) The server is not binding explicitly to a set of addresses using the
#    "bind" directive.
# 2) No password is configured.
#
# The server only accepts connections from clients connecting from the
# IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain
# sockets.
#
# By default protected mode is enabled. You should disable it only if
# you are sure you want clients from other hosts to connect to Redis
# even if no authentication is configured, nor a specific set of interfaces
# are explicitly listed using the "bind" directive.
protected-mode no

# Accept connections on the specified port, default is 6379 (IANA #815344).
# If port 0 is specified Redis will not listen on a TCP socket.
port 6379

# TCP listen() backlog.
#
# In high requests-per-second environments you need an high backlog in order
# to avoid slow clients connections issues. Note that the Linux kernel
# will silently truncate it to the value of /proc/sys/net/core/somaxconn so
# make sure to raise both the value of somaxconn and tcp_max_syn_backlog
# in order to get the desired effect.
tcp-backlog 511

# Unix socket.
#
# Specify the path for the Unix socket that will be used to listen for
# incoming connections. There is no default, so Redis will not listen
# on a unix socket when not specified.
#
# unixsocket /tmp/redis.sock
# unixsocketperm 700

# Close the connection after a client is idle for N seconds (0 to disable)
timeout 0

# TCP keepalive.
#
# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence
# of communication. This is useful for two reasons:
#
# 1) Detect dead peers.
# 2) Take the connection alive from the point of view of network
#    equipment in the middle.
#
# On Linux, the specified value (in seconds) is the period used to send ACKs.
# Note that to close the connection the double of the time is needed.
# On other kernels the period depends on the kernel configuration.
#
# A reasonable value for this option is 300 seconds, which is the new
# Redis default starting with Redis 3.2.1.
tcp-keepalive 300

网络部分,配置网络

6.3.1、bind

默认情况bind=127.0.0.1只能接受本机的访问请求

不写的情况下,无限制接收任何IP地址的访问

在生产环境下,需要写你应用服务器的地址。

服务器是需要远程访问的,所以需要注释掉。

6.3.2、protected-mode

如果开启了protected-mode,那么在没有设定bind ip且没有设置密码的情况下,redis只允许接收本机的响应

protected yes/no 

6.3.3、Port

port 6379

端口号,默认为6379

6.3.4、tcp-backlog

tcp-backlog 511

设置tcp的back-log,back-log其实是一个连接队列,back-log队列总和=未完成三次握手的队列+已经完成三次握手的队列。

在高并发环境下,你需要一个高back-log值来避免客户端连接问题。

注意Linux内核会将这个值减少到 /proc/sys/net/core/somaxconn 的值(128),所以需要确认增大 /proc/sys/net/core/somaxconn 和 /proc/sys/net/ipv4/tcp_max_syn_backlog 的值(128),需要增大这两个值来达到想要的效果。

6.3.5、timeout

timeout 0

设置超时时间,以秒为单位。

6.3.6、tcp-keepalive

tcp-keepalive 300

保存连接时间,如果长时间(单位:秒)没有操作,则会释放连接。

6.4、###GENERAL###

################################# GENERAL #####################################

# By default Redis does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
# daemonize yes

# If you run Redis from upstart or systemd, Redis can interact with your
# supervision tree. Options:
#   supervised no      - no supervision interaction
#   supervised upstart - signal upstart by putting Redis into SIGSTOP mode
#   supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET
#   supervised auto    - detect upstart or systemd method based on
#                        UPSTART_JOB or NOTIFY_SOCKET environment variables
# Note: these supervision methods only signal "process is ready."
#       They do not enable continuous liveness pings back to your supervisor.
supervised no

# If a pid file is specified, Redis writes it where specified at startup
# and removes it at exit.
#
# When the server runs non daemonized, no pid file is created if none is
# specified in the configuration. When the server is daemonized, the pid file
# is used even if not specified, defaulting to "/var/run/redis.pid".
#
# Creating a pid file is best effort: if Redis is not able to create it
# nothing bad happens, the server will start and run normally.
pidfile /var/run/redis_6379.pid

# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel notice

# Specify the log file name. Also the empty string can be used to force
# Redis to log on the standard output. Note that if you use standard
# output for logging but daemonize, logs will be sent to /dev/null
logfile ""

# To enable logging to the system logger, just set 'syslog-enabled' to yes,
# and optionally update the other syslog parameters to suit your needs.
# syslog-enabled no

# Specify the syslog identity.
# syslog-ident redis

# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.
# syslog-facility local0

# Set the number of databases. The default database is DB 0, you can select
# a different one on a per-connection basis using SELECT  where
# dbid is a number between 0 and 'databases'-1
databases 16

# By default Redis shows an ASCII art logo only when started to log to the
# standard output and if the standard output is a TTY. Basically this means
# that normally a logo is displayed only in interactive sessions.
#
# However it is possible to force the pre-4.0 behavior and always show a
# ASCII art logo in startup logs by setting the following option to yes.
always-show-logo yes

6.4.1、daemonize

daemonize

是否为后台进程,默认为yes

守护进程,后台启动

6.4.2、pidfile

存放pid文件的位置,每个实例会产生一个不同的pid文件

pidfile /var/run/redis_6379.pid

6.4.3、loglevel

表示日志级别

loglevel notice/debug/verbose/warning

debug (a lot of information, useful for development/testing)

​ Debug (大量的信息,对开发和测试非常有帮助)

verbose (many rarely useful info, but not a mess like the debug level)

​ Verbose (一些少量有用的信息,但是不像Debug一样杂乱)

notice (moderately verbose, what you want in production probably)

​ Notice(moderately 适量长度,大概是你在生产环境中想要的信息)

warning (only very important / critical messages are logged)

​ Warning(只有特别重要/关键的信息会被打印到日志)

6.4.4、logfile

设置日志的输出目录,默认为空

logfile ""

6.4.5、database

设置数据库的数量,默认是16个

database 16

6.5、###SECURITY###

################################## SECURITY ###################################

# Require clients to issue AUTH  before processing any other
# commands.  This might be useful in environments in which you do not trust
# others with access to the host running redis-server.
#
# This should stay commented out for backward compatibility and because most
# people do not need auth (e.g. they run their own servers).
#
# Warning: since Redis is pretty fast an outside user can try up to
# 150k passwords per second against a good box. This means that you should
# use a very strong password otherwise it will be very easy to break.
#
# requirepass 111111

# Command renaming.
#
# It is possible to change the name of dangerous commands in a shared
# environment. For instance the CONFIG command may be renamed into something
# hard to guess so that it will still be available for internal-use tools
# but not available for general clients.
#
# Example:
#
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
#
# It is also possible to completely kill a command by renaming it into
# an empty string:
#
# rename-command CONFIG ""
#
# Please note that changing the name of commands that are logged into the
# AOF file or transmitted to replicas may cause problems.

6.5.1、requirepass

访问密码的查看、设置和取消

#requirepass foobared

默认没有密码,此行被注解

在命令中设置密码是暂时的,重启redis服务器之后,密码就会被还原

而在文件中设置的密码是永久的,每次启动服务器都需要。

config get requirepass
config set requirepass "123456"

auth 123456

6.6、###LIMITS###

6.6.1、maxclients

设置redis同时可以与多少个客户端进行连接

默认情况下可为10000个客户端

如果达到了此限制,redis则会拒绝新的连接请求,并且向这些连接请求方发出“max number of client reached”作为回应。

#maxclients 10000

6.6.2、maxmemory

建议必须设置,否则内存占满会导致服务器宕机

设置redis可以使用的内存大小。

一旦内存使用达到上线,redis便会试图移除内部数据,移除规则可以通过 maxmemory-policy 来指定。

6.6.3、maxmemory-policy

用来设置内存满时,redis对内部数据删除的策略

volatile-lru:使用LRU算法移除key,只对设置了过期时间的键;(最近最少使用)

allkeys-lru:在所有集合key中,使用LRU算法移除key;

volatile-random:在过期的集合中,随机删除key,只对设置了过期时间的key

allkeys-random:在所有集合的key中,随机删除key

volatile-ttl:移除那些TTL值最小的key(最近要过期的key)

noeviction:不进行移除。(针对写操作,只返回错误信息)

6.6.4、maxmemory-samples

设置样本数量。

LRU算法和最小TTL算法都并非是精确算法,而是一个估算值,所以可以设置样本的大小,redis会去检查样本数量的key并选择需要淘汰哪一个。

一般设置3-7个样本即可,数字越小样本越不准确,同样的性能损耗也会变小。

7、redis的发布和订阅

7.1、什么是发布和订阅

Redis发布/订阅(pub/sub)是一种消息通信模式。【publish:发布/subscribe:订阅】

发送者发送消息,订阅者接收消息。

Redis客户端可以订阅任意数量的频道。【频道】有点类似观察者模式

7.2、发布订阅命令行实现

1、打开一个客户端,订阅channel1

SUBSCRIBE channel1

2、打开另一个客户端,给channel1发布消息hello

publish channel1 hello

3、打开第一个客户端可以看到发送的消息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-58YuyV4Q-1690358602703)(./Redis.assets/image-20220907163031712.png)]

发布的信息没有持久化,如果在订阅的客户端收不到hello,只能收到订阅后发布的消息。

8、Redis中的新数据类型

8.1、BitMaps-位图

8.1.1、介绍

BitMaps本身不是一种数据类型,实际上他只是一个字符串(key-value),但是它可以对字符串的位进行操作。

BitMaps单独提供了一套操作命令,可以把BitMaps看做以位为单位的数组,且这个数组只能存储0和1,数组的下标在BitMaps中叫做偏移量。

key [0,1,0,1,0,0,0,0,1,0,1,0,1,0]

8.1.2、命令

setbit

设置bitmaps中某个偏移量的值(offset:偏移量,从0开始)

setbit [key] [offset] [value]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p2m5uvak-1690358602708)(./Redis.assets/image-20220907163807183.png)]

很多应用的用户ID以一个指定的数字(例如10000)开头,直接将用户ID和BitMaps的偏移量进行对应势必会造成一定的浪费,通常的做法是将每次做setbit操作时,将用户id减去这个指定的数字。

在第一次初始化BitMaps时,假如偏移量特别大,那么整个初始化执行过程会比较慢,可能会造成阻塞。

getbit

获取BitMaps中某个偏移量的值。(偏移量从0开始算,默认为0)

getbit [key] [offset]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JJtfS9pE-1690358602712)(./Redis.assets/image-20220907164128465.png)]

bitcount

统计字符串被设置为1的bit数。

一般情况下,给定的整个字符串都会被进行计数,通过指定额外的start或者end参数,可以让计数在指定的范围内进行。

start和end参数的设置都可以使用负数值如:-1 表示最后一个位,-2表示倒数第二个位

start、end也会被包含在内。

bitcount [key] [start end]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jqBZmnJb-1690358602717)(./Redis.assets/image-20220907164412587.png)]

是以字节为单位,并非为位

举例:

viewer [01000001 01000000 00000000 00100001]

bitcount viewer 1 2
	统计下标为1、2字节组中bit=1的个数,即[01000000 00000000]中1的个数=1
	返回1
	
bitcount viewer 1 3
	统计下标为1到下标为3中bit=1的个数,即[01000000 00000000 00100001]中1的个数=3
	返回3
	
bitcount viewer 0 -2
	统计下标为0开始到下标倒数第二个字节中bit=1的个数,即[01000001 01000000 00000000]中1的个数=3
	返回3

Redis中setbit设置或者清除的是以bit为单位,而bitcount计算的是以byte为单位

bitop

bitop是一个复合操作,可以做多个BitMaps的 and(交集)、or(并集)、not(非)、xor(异或)等操作并将结果保存在destkey中。

bitop and/or/not/xnot [destkey] [bitmap1] [bitmap2]

举例:

20201104访问的用户:
setbit unique:users:20201104 1 1
setbit unique:users:20201104 2 1
setbit unique:users:20201104 5 1
setbit unique:users:20201104 9 1

20201103访问的用户:
setbit unique:users:20201103 0 1
setbit unique:users:20201103 1 1
setbit unique:users:20201103 4 1
setbit unique:users:20201103 9 1

1、计算出两天都访问过的用户数量:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iPEOgFTQ-1690358602721)(./Redis.assets/image-20220907170420833.png)]

127.0.0.1:6379> bitop and bothviewer unique:users:20201103 unique:users:20201104
(integer) 2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nWrTKiZr-1690358602726)(./Redis.assets/image-20220907170506832.png)]

可以看到,两天都访问过的用户有1和9共2位用户。

2、计算出任意一天都访问过网站的用户数量(例如月活跃度),可以使用or求并集

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kz9U7TRH-1690358602731)(./Redis.assets/image-20220907170803376.png)]

127.0.0.1:6379> bitop or activekey unique:users:20201104 unique:users:20201103
(integer) 2
127.0.0.1:6379> bitcount activekey
(integer) 6
127.0.0.1:6379> 

8.1.3、BitMaps与set对比

假设有1亿用户,每天独立访问用户有五千万,如果每天用集合类型和BitMaps分别存储活跃用户可以得到表:

数据类型 每个用户id占用空间 需要存储的用户量 需要的内存量
集合类型 64位 5000 0000 64*5000 0000=400mb
BitMaps 1位 1 0000 0000 1*1 0000 0000=12.5mb
数据类型 一天 一个月 一年
集合 400mb 12gb 144gb
BitMaps 12.5mb 375mb 4.5gb

但是BitMaps并不是万金油,加入该网站每天独立访问的用户很少,例如只有10w,那么两者的对比如下,很显然这时候使用bitmaps就不太合适了,因为基本上大部分位都是0

数据类型 每个用户id占用空间 需要存储的用户量 需要的内存量
集合类型 64位 10 0000 64*10 0000=800kb
BitMaps 1位 1 0000 0000 1*1 0000 0000=12.5mb

8.2、HyperLogLog-基数统计

8.2.1、介绍

在工作当中我们经常会遇到与统计相关的功能需求,比如统计网站的PV(pageView页面访问量),可以使用Redis的incr,incrby轻松实现。

但是像UV(UniqueVisitor,独立访客)、独立IP数、搜索记录等需要去重和技术的问题如何解决?

这种求集合中不重复元素个数的问题称为基数问题。

Redis HyperLogLog是用来做基数统计的算法。HyperLogLog的优点是,在输入元素的数量或者体积非常大时,计算基数所需的空间总是固定的,并且是很小的。

在Redis里,每个HyperLogLog键只需要花费12kb的内存,就可以计算接近2的64次方个不同元素的基数。

HyperLogLog只会根据输入元素来进行计算基数,而不会存储输入元素本身,所以HyperLogLog不能像集合那样返回输入的各个元素。

什么是基数?

举例:

数据集{1,2,2,3,4,7,8,9,9,9,9}

则基数集为{1,2,3,4,7,8,9},基数为7。

基数估计就是在误差可接受的范围内,快速计算基数。(可以去掉重复的)

8.2.2、命令

pfadd

添加指定元素到HyperLogLog

pfadd [key] [element] [element]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MA8oFglJ-1690358602735)(./Redis.assets/image-20220913132942979.png)]

是取基数,所以在添加重复的对象时会失败。

如果执行之后HLL估计的近似基数发生变化则会返回1,否则返回0。

pfcount

计算HLL的近似基数,可以计算多个HLL,比如用HLL存储每天的UV

pfcount [key]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tGR7aQiE-1690358602740)(./Redis.assets/image-20220913135337580.png)]

pfmerge

合并

总的来说就是用一个新的key来存放两个key的并集

pfmerge [destkey] [sourcekey1] [sourcekey2] ...

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WHHHG4N7-1690358602744)(./Redis.assets/image-20220914102543044.png)]

8.3、Geospatial

8.3.1、介绍

Redis3.2中增加了对GEO类型的支持。

GEO,Geographic,地理信息

该类型就是元素的二维坐标,在地图上的经纬度。redis基于该类型提供了经纬度设置、查询、范围查询、距离查询、经纬度hash等常见操作。

8.3.2、命令

geoadd

添加一个或者多个地区的坐标和名称

longitude 经度

latitude 纬度

member 名称

geoadd [key] [longitude] [latitude] [member] ...

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VnyxdAID-1690358602749)(./Redis.assets/image-20220914103247183.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2z1aePZx-1690358602753)(./Redis.assets/image-20220914103252172.png)]

两极无法直接添加,一般会下载城市数据,通过java一次性导入。

有效的经度从-180到180。

有效的纬度从-85.05112878 到 85.05112878

当坐标位置超出指定范围时,该命令将会返回一个错误。

已经添加的数据,是无法再次往里面添加的。

geopos

获取指定地区的坐标值

浮点数有经度丢失

不存在的返回 nil。

geopos [key] [member] [menber] ...

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9883oaWJ-1690358602758)(./Redis.assets/image-20220914103616925.png)]

geodist

获取两个坐标点之间的直线距离

geodist [key] [member1] [member2] ...[m|km|ft|mi]

m表示单位为米

km表示单位为千米

mi表示单位为英里

ft表示单位为英尺

如果用户没有指定单位参数,默认为m米。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5hBzX5bi-1690358602762)(./Redis.assets/image-20220914104408973.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WbynJkPK-1690358602767)(./Redis.assets/image-20220914104528502.png)]

georadius

以给定的经纬度为中心,找出某一半径内的元素

georaduis [key] [longitude] [latitude] raduis [m|km|ft|mi]

longitude 经度

latitude 纬度

raduis 半径距离

[m|km|ft|mi] 单位

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ys8PHTKq-1690358602771)(./Redis.assets/image-20220914104735686.png)]

9、Jedis操作Redis6

类似于JDBC,Jedis是Redis提供给java的一个接口工具,可以使用java控制redis。

9.1、准备工作

1.创建maven项目

2.引入相关依赖:


    redis.clients
    jedis
    4.2.3

3.准备Redis镜像

docker run命令:https://www.runoob.com/docker/docker-run-command.html

docker run -itd --name myredis -p 6379:6379 redis//将对应的端口映射到本机

//itd:   -i 以交互模式运行容器,-t: 为容器重新分配一个伪输入终端,-d: 后台运行容器,并返回容器ID;

docker ps //查看运行中的镜像

docker exec -it [name] bash //测试是否能进入redis镜像

5.使用命令行,开启端口映射,开启镜像

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9lKp8FBf-1690358602776)(./Redis.assets/image-20220914131243455.png)]

bind 127.0.0.1 # 注释掉这部分,这是限制redis只能本地访问 7.0版本及以上改为默认注释掉了,不用手动注释

protected-mode no # 默认yes,开启保护模式,限制为本地访问

daemonize no # 默认no,改为yes意为以守护进程方式启动,可后台运行,除非kill进程,改为yes会使配置文件方式启动redis失败

databases 16 # 数据库个数(可选)

dir ./ # 输入本地redis数据库存放文件夹(可选)

appendonly yes # redis持久化(可选)

Linux 关掉系统防火墙(不推荐):

systemctl stop firewalld

systemctl status firewalld

推荐:可以直接开放6379端口,但是要小心端口攻击(开启后记得重启redis)

*阿里云服务器需要在安全组中设置6379端口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PRDFI39e-1690358602780)(./Redis.assets/image-20220914133058990.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2EZWrxJp-1690358602785)(./Redis.assets/image-20220914131644525.png)]

如果这里显示的是如上图所示的样子,则成功开启了端口映射。

6.写测试代码

package org.lobo;

import redis.clients.jedis.Jedis;

public class Main {
    public static void main(String[] args) {
        //创建Jedis对象,参数是host和port
        Jedis jedis=new Jedis( "127.0.0.1",6379);

        //测试
        String ping = jedis.ping();
        System.out.println(ping);
    }
}

7.运行结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FqIdS6Sq-1690358602789)(./Redis.assets/image-20220914132831910.png)]

9.2、测试Jedis

既然已经连接好了Redis,现在可以通过java来使用Jedis操作redis了。

在操作之前,我们先进行一次清除数据库内的数据:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JlzC7NTK-1690358602794)(./Redis.assets/image-20220914133612080.png)]

在java中添加以下语句

jedis.setnx("k1","v1");
jedis.setnx("k2","v2");
jedis.setnx("k3","v3");

然后我们再回到redis中通过keys *查看所有的key

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JV1bp8oN-1690358602799)(./Redis.assets/image-20220914133817454.png)]

继续进行测试:

//创建Jedis对象,参数是host和port
Jedis jedis=new Jedis( "127.0.0.1",6379);

//测试
String ping = jedis.ping();
System.out.println(ping);
//设置非重复key-value
jedis.setnx("k1","v1");
jedis.setnx("k2","v2");
jedis.setnx("k3","v3");
//查询所有的key
Set<String> keys = jedis.keys("*");
System.out.println("keys.size()="+keys.size());
System.out.println("keys * =");
for (String key:keys){
    System.out.println(key);
}
//查询key的属性
System.out.println("jedis.exists(\"k1\")="+jedis.exists("k1"));
System.out.println("jedis.ttl(\"k1\")="+jedis.ttl("k1"));
System.out.println("jedis.get(\"k1\")="+jedis.get("k1"));

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-thwqT1wM-1690358602803)(./Redis.assets/image-20220914134229971.png)]

//设置多个key-value
jedis.mset("key1","value1","key2","value2");
List<String> mget = jedis.mget("key1", "key1");
System.out.println(mget);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QFzGmxCM-1690358602808)(./Redis.assets/image-20220920103007098.png)]

结尾

你可能感兴趣的:(redis,数据库,缓存)