Redis介绍
redis 是完全开源免费的,遵守BSD协议,是一个高性能的 key-value数据库
这里提到的提到了key-value数据库,这是什么那,其实我们在之前就学习过数据库分为两种,一种是关系型数据库,一种为非关系型的数据库,其实Redis就是一种非关系型数据库,并且可基于内存且可持久化的日志性,key-value数据库,并提供多种语言的API。其实这种数据库有一个名词叫做NoSql.
NoSQL
NoSQL指的是非关系型数据库。NoSQL也称之为Not Only SQL(不仅仅只是SQL)的缩写,是对不同于传统的关系型数据库管理系统的统称。
为什么需要使用NoSL
传统关系型数据库在应付超大规模和高并发网站时就会出现各种问题,甚至是力不从心了,比如:
1.对数据库高并发读写需求:
关系型数据库应对上万次的SQL查询,勉勉强强顶得住,但是一旦面对上万次的写操作,硬盘 IO 就已经无法承受了。
2.海量数据高效存储及访问
比较大型的网站,每天用户产生的数据是非常庞大的,因为现在的应用系统一般都需要有日志的功能来记录用户的行为以及系统信息等,所以有一些大型网站一个月就达到了2.5亿的用户动态,如果我们想在一张如此庞大的数据库中查询某一条数据信息,效率之差是我们无法忍受的。
3.数据库的高拓展和高可用需求
基于 web 框架当中,数据库是最难进行横向拓展的,它不会像 webserver 或者 AppServer 那样进行简单的硬件和服务节点的拓展就能提高性能和负载,对于很多24小时不间断的服务来说,对数据库进行升级和拓展是一件非常痛苦的事情。
针对以上提到的问题,促使产生了NoSQL数据库来解决问题,因为它就是用于解决超大规模数据的存储和多重数据种类所带来的问题,这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
总结:
今天我们可以通过第三方平台(如:Google Facebook等) 可以很容易的访问和抓取数据。用户的个人信息,社交网络,地理位置,用户生成的数据和用户操作日志已经成倍的增加,我们如果要对这些用户数据进行挖掘,那SQL数据库已经不适合这些应用了,NoSQL数据库的发展却能很好的处理这些大的数据。
NoSQL的优点/缺点
优点:
高可扩展性
分布式计算
低成本
架构的灵活性,半结构化数据
没有复杂的关系
缺点:
没有标准化
有限的查询功能(到目前为止)
最终一致性
集群
NoSQL类别
NoSQL分为以下的类别
类型 | 部分代表 | 特点 |
---|---|---|
列存储 | Hbase ,Cassandra,Hypertable | 顾名思义,是按列存储数据的。最大的特点是方便存储结构化和半结构化数据,方便做数据压缩,对针对某一列或者某几列的查询有非常大的 IO 优势。 |
文档存储 | MongoDB CouchDB | 文档存储一般用类似 json 的格式存储,存储的内容是文档型的。这样也就有机会对某些字段建立索引,实现关系数据库的某些功能。 |
key-value存储 | Tokyo Cabinet Tyrant MemcacheDB Redis | 可以通过 key 快速查询到其 value.一般来说,存储不管 value 的格式,照单全收。(Redis包含了其他功能) |
图存储 | Neo4j FlockDB | 图形关系的最佳存储。使用传统关系数据库来解决的话性能低下,而且设计使用不方便。 |
对象存储 | db40 Versant | 通过类似面向对象语言的语法操作数据库,通过对象的方式存取数据 |
xml数据库 | Berkeley DB XML BaseX | 高效的存储XML数据,并支持XML的内部查询语法,比如XQuery,Xpath |
MySQL关系型数据库可以理解为是一张表,新建一张表时,他需要有对应的列和行,行代表一行数据,当前的列可以说是你需要定义数据类型,比如id,name,age,
id(int) | name(string) | age(int) | ||
---|---|---|---|---|
1 | Tom | 18 | ||
2 |
这就是我们常见的关系型数据表。
对应的需要有每一行,每一列的这种结构以及对应的数据类型要求的。你在设计表的时候就需要将他们都设计好。
但是对于我们的NoSQL,非关系型数据库。nosql的这种表的话,我们不用这么费劲,简单来说,我们以Redis为列
redis就是 key-value [k:v] 模式
{id: 1,name: Tom,age: 18}
他不需要单独去设计 id 是什么类型,name 是什么类型,age 是什么类型,都不需要,这就是他简单的地方,说白了,他的这种架构表比较灵活。
MySQL的用户表,会跟订单表,购物表,物流表等像关联,关系型数据表是可以通过主id键将他们关联的,每张表之间会存在关联的,
但是NoSQL是没有关联性的,没有标准的格式化:
K: 一般 用 id
V: 一般用 json 字符串
json字符串里面存储的就是像 name,age等用户数据,只需要用id就可以查询字符串,查出这条用户信息,这样就可以大大简化数据,这就是NoSQL的好处。
Redis入门
Redis是由C语言编写的一个远程内存数据库,他不仅性能强劲,而且有复制特性以及为解决问题而生的独一无二的数据模型。
Redis是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库,并提供多种语言的API。
Redis 与其他key-value缓存产品有以下三个特点:
redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加我进行使用
redis不仅仅支持简单的key-value类型的数据,同时还提供 list,set,zset,hash等数据结构的存储。
redis支持数据的备份,即 master-slave模式的数据备份
为什么要使用Redis
以往,我们系统的只需要从数据库读取数据,展示在页面就可以了,后来随着时代的发展系统越来越复杂了,传统的模式越来越难以支撑,缓存技术也在系统中占据越来越重要的角色,而Redis就是目前市场使用量最多的缓存技术。
Redis特点
性能极高-Redis能读的速度是110000次/s,写的速度是81000次/s.
丰富的数据类型-Redis支持二进制案例的 strings,hashes,sets 及 Ordered Sets 数据类型操作。
原子-Redis的所有操作都是原子性的,同时 Redis 还支持对几个操作前后的原子性执行。
丰富的特性-Redis还支持 publish/subscribe,通知 key 过期等等特性。
高速读写-Redis使用自己实现的分离器,代码量短,没有使用 Lock(锁MySQL),因此效率高。
持久化 Redis 直接将数据存储到内存中,要将数据保存到磁盘上,Redis可以通过两种方式实现持久化。
定时快照(snapshot):每隔一段时间将整个数据库内容写入到磁盘上,因为每次都是全部数据,代价比较高。
基于语句追加(aof): 只追踪变化的数据,但是追加的log可能很大,同时所有的操作均重新执行一次,回复速度慢。
因为Redis所有操作都是原子性(要么都成功,要么都失败),同时还没有锁,所以 Redis 的每个命令都是线程安全的
Redis 优势
1.高性能:
假设下如果所有的数据都从数据库中读取,特别是一些复杂的数据,每次都查询 mysql 性能必定非常差。所以对于一些复杂操作耗时查出来的结果且后面不怎么变化的数据放到缓存,能大幅提高系统响应。
2. 高并发:
mysql单机一般只能支撑到2000Qps,而Redis由于是K/V模式的操作,单机可以支撑并发量可达到几万到几十万。
Redis 缺点
1.数据库容量受到物理内存的限制,不能用作海量数据的高性读写,因此 Redis 适合的场景主要局限在较小数据量的高性能操作和运算上。
2. Redis 不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的 IP 才能恢复。
3. 主机宕机,宕机前有部分数据未能及时同步到从机,切换 IP 后还会引入数据不一致的问题,降低了系统的可用性。
4. Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费。
Redis应用场景
根据业内项目的实战经验及企业开发中总结的应用场景:
缓存
秒杀
计数器
排行榜
热点数据(经常查询,但是不经常修改或者删除的数据)
分布式锁
分布式ID
消息系统
等等大部分与系统性能密切相关的场景
Redis安装
首先各位要知道 Redis 本身就没有针对windows系统进行开发,所以大家如果能下载到的win版本的Redis其实都是微软自行研发的,我们正常使用也都是基于 Linux,所以整体安装我们都是针对 Linux 来进行的。所以首先需要准备一台虚拟机系统采用:
CentOS7即可
官网地址: Redis - The Real-time Data Platform
官网下载地址:Downloads - Redis
https://download.redis.io/releases/
我们采用最新版本安装
在这可以直接点击下载 Download 7.0.11, 下载之后启动虚拟机,通过远程工具连接然后将下载好的Redis上传到虚拟机中进行安装即可,这是整体方式,但是要注意首先我们需要先安装GCC依赖
GCC依赖
Redis是基于C语言编写的,需要此依赖对 Redis 源码进行编译
yum install -y gcc tcl
apt install -y gcc tcl make make-guile
apt install -y make
apt install -y make-guile
apt install -y gcc tcl
具体步骤
1, 上传 redis-7.0.11.tar.gz到虚拟机opt目录
root@redis:/opt# ls
redis-7.0.11.tar.gz
root@redis:/opt# ll
total 2928
drwxr-xr-x 2 root root 4096 Jun 24 08:55 ./
drwxr-xr-x 20 root root 4096 Jun 24 06:01 ../
-rw-r--r-- 1 root root 2988485 Jun 24 07:08 redis-7.0.11.tar.gz
root@redis:/opt#
2, 解压此文件
tar -zxvf redis-7.0.11.tar.gz
root@redis:/opt# tar -zxvf redis-7.0.11.tar.gz
root@redis:/opt# ls
redis-7.0.11 redis-7.0.11.tar.gz
root@redis:/opt# ll
total 2932
drwxr-xr-x 3 root root 4096 Jun 24 09:09 ./
drwxr-xr-x 20 root root 4096 Jun 24 06:01 ../
drwxrwxr-x 8 root root 4096 Apr 17 2023 redis-7.0.11/
-rw-r--r-- 1 root root 2988485 Jun 24 07:08 redis-7.0.11.tar.gz
root@redis:/opt#
3.进入到安装目录
root@redis:~# cd /opt
root@redis:/opt# ls
redis-7.0.11 redis-7.0.11.tar.gz
root@redis:/opt# cd redis-7.0.11/
root@redis:/opt/redis-7.0.11# ls
00-RELEASENOTES CODE_OF_CONDUCT.md COPYING INSTALL MANIFESTO redis.conf runtest-cluster runtest-sentinel sentinel.conf tests utils
BUGS CONTRIBUTING.md deps Makefile README.md runtest runtest-moduleapi SECURITY.md src TLS.md
root@redis:/opt/redis-7.0.11# ll
total 292
drwxrwxr-x 8 root root 4096 Apr 17 2023 ./
drwxr-xr-x 3 root root 4096 Jun 24 09:09 ../
-rw-rw-r-- 1 root root 43972 Apr 17 2023 00-RELEASENOTES
-rw-rw-r-- 1 root root 51 Apr 17 2023 BUGS
-rw-rw-r-- 1 root root 5027 Apr 17 2023 CODE_OF_CONDUCT.md
drwxrwxr-x 2 root root 4096 Apr 17 2023 .codespell/
-rw-rw-r-- 1 root root 2634 Apr 17 2023 CONTRIBUTING.md
-rw-rw-r-- 1 root root 1487 Apr 17 2023 COPYING
drwxrwxr-x 7 root root 4096 Apr 17 2023 deps/
-rw-rw-r-- 1 root root 405 Apr 17 2023 .gitattributes
drwxrwxr-x 4 root root 4096 Apr 17 2023 .github/
-rw-rw-r-- 1 root root 535 Apr 17 2023 .gitignore
-rw-rw-r-- 1 root root 11 Apr 17 2023 INSTALL
-rw-rw-r-- 1 root root 151 Apr 17 2023 Makefile
-rw-rw-r-- 1 root root 6888 Apr 17 2023 MANIFESTO
-rw-rw-r-- 1 root root 22441 Apr 17 2023 README.md
-rw-rw-r-- 1 root root 106545 Apr 17 2023 redis.conf
-rwxrwxr-x 1 root root 279 Apr 17 2023 runtest*
-rwxrwxr-x 1 root root 283 Apr 17 2023 runtest-cluster*
-rwxrwxr-x 1 root root 1613 Apr 17 2023 runtest-moduleapi*
-rwxrwxr-x 1 root root 285 Apr 17 2023 runtest-sentinel*
-rw-rw-r-- 1 root root 1695 Apr 17 2023 SECURITY.md
-rw-rw-r-- 1 root root 14005 Apr 17 2023 sentinel.conf
drwxrwxr-x 4 root root 4096 Apr 17 2023 src/
drwxrwxr-x 11 root root 4096 Apr 17 2023 tests/
-rw-rw-r-- 1 root root 3055 Apr 17 2023 TLS.md
drwxrwxr-x 8 root root 4096 Apr 17 2023 utils/
--------------------------------------
root@redis:/opt/redis-7.0.11# ll
total 300
drwxrwxr-x 8 root root 4096 Apr 17 2023 ./
drwxr-xr-x 3 root root 4096 Jun 24 09:09 ../
-rw-rw-r-- 1 root root 43972 Apr 17 2023 00-RELEASENOTES
-rw-rw-r-- 1 root root 51 Apr 17 2023 BUGS
-rw-rw-r-- 1 root root 5027 Apr 17 2023 CODE_OF_CONDUCT.md
drwxrwxr-x 2 root root 4096 Apr 17 2023 .codespell/
-rw-rw-r-- 1 root root 2634 Apr 17 2023 CONTRIBUTING.md
-rw-rw-r-- 1 root root 1487 Apr 17 2023 COPYING
drwxrwxr-x 7 root root 4096 Jun 24 09:33 deps/
-rw-rw-r-- 1 root root 405 Apr 17 2023 .gitattributes
drwxrwxr-x 4 root root 4096 Apr 17 2023 .github/
-rw-rw-r-- 1 root root 535 Apr 17 2023 .gitignore
-rw-rw-r-- 1 root root 11 Apr 17 2023 INSTALL
-rw-rw-r-- 1 root root 151 Apr 17 2023 Makefile
-rw-rw-r-- 1 root root 6888 Apr 17 2023 MANIFESTO
-rw-rw-r-- 1 root root 22441 Apr 17 2023 README.md
-rw-rw-r-- 1 root root 106545 Apr 17 2023 redis.conf
-rwxrwxr-x 1 root root 279 Apr 17 2023 runtest*
-rwxrwxr-x 1 root root 283 Apr 17 2023 runtest-cluster*
-rwxrwxr-x 1 root root 1613 Apr 17 2023 runtest-moduleapi*
-rwxrwxr-x 1 root root 285 Apr 17 2023 runtest-sentinel*
-rw-rw-r-- 1 root root 1695 Apr 17 2023 SECURITY.md
-rw-rw-r-- 1 root root 14005 Apr 17 2023 sentinel.conf
drwxrwxr-x 4 root root 12288 Jun 24 09:34 src/
drwxrwxr-x 11 root root 4096 Apr 17 2023 tests/
-rw-rw-r-- 1 root root 3055 Apr 17 2023 TLS.md
drwxrwxr-x 8 root root 4096 Apr 17 2023 utils/
4, 编译且安装
make && make install
# 看到如下内容表示 redis 安装成功
Hint: It's a good idea to run 'make test' ;)
INSTALL redis-server # redis 服务端启动命令
INSTALL redis-benchmark # redis 测试压力命令
INSTALL redis-cli # redis 客户端命令
make[1]: Leaving directory '/opt/redis-7.0.11/src'
注意,redis在安装的时候就已经把环境变量设置好了,你可以在任意位置启动redis
5. 默认安装路径存在于:/usr/local/bin
Redis启动
Redis启动方式有多种:
1. 默认启动
2. 指定配置启动
3. 开机自启
首先我们进入到默认的Redis安装目录:/usr/local/bin
root@redis:/opt/redis-7.0.11# ll /usr/local/bin/
total 22084
drwxr-xr-x 2 root root 4096 Jun 24 09:34 ./
drwxr-xr-x 10 root root 4096 Feb 16 18:37 ../
-rwxr-xr-x 1 root root 5509096 Jun 24 09:34 redis-benchmark*
lrwxrwxrwx 1 root root 12 Jun 24 09:34 redis-check-aof -> redis-server*
lrwxrwxrwx 1 root root 12 Jun 24 09:34 redis-check-rdb -> redis-server*
-rwxr-xr-x 1 root root 5392000 Jun 24 09:34 redis-cli*
lrwxrwxrwx 1 root root 12 Jun 24 09:34 redis-sentinel -> redis-server*
-rwxr-xr-x 1 root root 11698248 Jun 24 09:34 redis-server*
此目录包含所有 redis 相关默认的配置,我们可以运行一下命令
redis-cil # redis 提供的命令行客户端
redis-server # redis 服务端启动脚本
redis-sentinel # redis 哨兵启动脚本
默认启动
我们首先启动 redis 服务端,当然启动 redis 可以在任何目录位置都行,因为已经加入环境变量了,不一定非要进入安装目录
redis-server
# 看到如下图所示表示 redis 已经启动成功
root@redis:/opt/redis-7.0.11# redis-server
7377:C 24 Jun 2024 09:51:05.903 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
7377:C 24 Jun 2024 09:51:05.903 # Redis version=7.0.11, bits=64, commit=00000000, modified=0, pid=7377, just started
7377:C 24 Jun 2024 09:51:05.903 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
7377:M 24 Jun 2024 09:51:05.904 * Increased maximum number of open files to 10032 (it was originally set to 1024).
7377:M 24 Jun 2024 09:51:05.904 * monotonic clock: POSIX clock_gettime
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 7.0.11 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 7377
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | https://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
7377:M 24 Jun 2024 09:51:05.905 # Server initialized
7377:M 24 Jun 2024 09:51:05.905 # WARNING Memory overcommit must be enabled! Without it, a background save or replication may fail under low memory condition. Being disabled, it can can also cause failures without low memory condition, see https://github.com/jemalloc/jemalloc/issues/1328. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
7377:M 24 Jun 2024 09:51:05.905 * Ready to accept connections
以上是前台启动,退出 ctrl+c 就可以了
前台启动是它的一种默认启动方式,它会出现一个什么问题,它现在是一种前台启动方式,如果我们想要通过客户端来连接 redis 服务端,我们需要在此时重新开启一个窗口,再连接服务器主机,这就比较麻烦了。
当然此时这种启动方式为:前台启动,也就是说,我们如果此时想去连接 Redis 服务端,需要再开启一个窗口,此窗口状态一致保存,如果此时停止,Redis也就停止了,所以这种方式并不是很友好
指定配置启动
如果我们想要的方式是 redis 直接在这个窗口也可以启动,不影响我们正常去操作,然后再通过一个客户端来进行连接,这样的方式如何完成呢?
如果想要进行后台启动,我们就需要修改 Redis 配置,我们需要修改的文件为: redis.conf
在咱们的 Redis 解压目录中
进入默认的安装目录
root@redis:/opt/redis-7.0.11# cd /usr/local/bin/
root@redis:/usr/local/bin# ls
redis-benchmark redis-check-aof redis-check-rdb redis-cli redis-sentinel redis-server
root@redis:/usr/local/bin# ll
total 22084
drwxr-xr-x 2 root root 4096 Jun 24 09:34 ./
drwxr-xr-x 10 root root 4096 Feb 16 18:37 ../
-rwxr-xr-x 1 root root 5509096 Jun 24 09:34 redis-benchmark*
lrwxrwxrwx 1 root root 12 Jun 24 09:34 redis-check-aof -> redis-server*
lrwxrwxrwx 1 root root 12 Jun 24 09:34 redis-check-rdb -> redis-server*
-rwxr-xr-x 1 root root 5392000 Jun 24 09:34 redis-cli*
lrwxrwxrwx 1 root root 12 Jun 24 09:34 redis-sentinel -> redis-server*
-rwxr-xr-x 1 root root 11698248 Jun 24 09:34 redis-server*
root@redis:/usr/local/bin#
注意:如果要修改配置我们一般情况下需要先备份
cp redis.conf redis.conf.bak
执行一下命令修改具体配置
vim redis.conf
root@redis:/opt/redis-7.0.11# cp redis.conf redis.conf.bak
root@redis:/opt/redis-7.0.11# ll
total 412
drwxrwxr-x 8 root root 4096 Jun 24 10:46 ./
drwxr-xr-x 3 root root 4096 Jun 24 09:09 ../
-rw-rw-r-- 1 root root 43972 Apr 17 2023 00-RELEASENOTES
-rw-rw-r-- 1 root root 51 Apr 17 2023 BUGS
-rw-rw-r-- 1 root root 5027 Apr 17 2023 CODE_OF_CONDUCT.md
drwxrwxr-x 2 root root 4096 Apr 17 2023 .codespell/
-rw-rw-r-- 1 root root 2634 Apr 17 2023 CONTRIBUTING.md
-rw-rw-r-- 1 root root 1487 Apr 17 2023 COPYING
drwxrwxr-x 7 root root 4096 Jun 24 09:33 deps/
-rw-r--r-- 1 root root 89 Jun 24 09:56 dump.rdb
-rw-rw-r-- 1 root root 405 Apr 17 2023 .gitattributes
drwxrwxr-x 4 root root 4096 Apr 17 2023 .github/
-rw-rw-r-- 1 root root 535 Apr 17 2023 .gitignore
-rw-rw-r-- 1 root root 11 Apr 17 2023 INSTALL
-rw-rw-r-- 1 root root 151 Apr 17 2023 Makefile
-rw-rw-r-- 1 root root 6888 Apr 17 2023 MANIFESTO
-rw-rw-r-- 1 root root 22441 Apr 17 2023 README.md
-rw-rw-r-- 1 root root 106545 Apr 17 2023 redis.conf
-rw-r--r-- 1 root root 106545 Jun 24 10:46 redis.conf.bak
-rwxrwxr-x 1 root root 279 Apr 17 2023 runtest*
-rwxrwxr-x 1 root root 283 Apr 17 2023 runtest-cluster*
-rwxrwxr-x 1 root root 1613 Apr 17 2023 runtest-moduleapi*
-rwxrwxr-x 1 root root 285 Apr 17 2023 runtest-sentinel*
-rw-rw-r-- 1 root root 1695 Apr 17 2023 SECURITY.md
-rw-rw-r-- 1 root root 14005 Apr 17 2023 sentinel.conf
drwxrwxr-x 4 root root 12288 Jun 24 09:34 src/
drwxrwxr-x 11 root root 4096 Apr 17 2023 tests/
-rw-rw-r-- 1 root root 3055 Apr 17 2023 TLS.md
drwxrwxr-x 8 root root 4096 Apr 17 2023 utils/
配置具体修改
# 监听地址,默认为127.0.0.1,所以只能本地访问,我们可以修改为 0.0.0.0,表示任意IP访问,但是注意,此设置仅用于测试 bind 0.0.0.0
参数说明
'0.0.0.0' 表示任意 IP 的访问
# 将守护进程,从默认的关闭改为开启,即为后台运行
daemonize yes
# 设置 redis 访问密码,任意访问,但是需要密码
requirepass 753159
# -----------常见配置(按情况自行调整,建议增加日志)----------------
# 监听的端口
port 6379
# 工作空间,默认是当前目录,运行redis-server时的命令,日志,持久化等文件会保存在这个目录
dir ./
# 数据库数量,设置为1,代表只使用1个库,默认有16个库,编号0~15(MySQL可以自己创建 Redis 不需要但是可以指定数量)
databases 16
# 设置 redis 能够使用的最大内存
maxmemory 512MB
# 日志文件,默认不记录日志,可以指定日志文件名来开启记录日志
logfile "redis.log"
# 将 'protected yes' 修改为 'protected no'
启动测试
此时的启动我们需要带着配置文件进行,我们此时正好在 redis 配置文件所在的路径中,所以可以不写全路径,直接启动带上配置文件即可 ,若在其他目录,需要写配置文件全路径(绝对路径)
redis-server redis.conf
root@redis:/opt/redis-7.0.11# redis-server redis.conf
root@redis:/opt/redis-7.0.11# ps -ef | grep redis
root 7449 1 0 12:20 ? 00:00:00 redis-server 0.0.0.0:6379
root 7455 1292 0 12:20 pts/0 00:00:00 grep --color=auto redis
root@redis:/opt/redis-7.0.11#
此时变成后台启动,所以没有日志,我们可以通过以下命令查看启动情况,当然停止的话直接杀死进程即可
ps -ef | grep redis # 查看 redis 运行的进程号
kill -9 xxxx # 杀死进程
开启自启动
Redis最简单的启动方式就是开机自启动,就好像 MySQL那样,通过系统服务来进行自启动,Redis 也可以做到。
1. 新建系统服务
vim /etc/systemd/system/redis.service
具体内容如下:
[Unit]
Description=redis-server
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/bin/redis-server /opt/redis-7.0.11/redis.conf
PrivateTmp=true
[Install]
WantedBy=multi-user.target
2. 重载系统服务
systemctl daemon-reload
3. 执行此命令让 redis 服务开启开机自启动
systemctl enable redis
4. 通过一下命令操作 redis 系统服务
启动
systemctl start redis
systemctl restart redis
root@redis:/opt/redis-7.0.11# vim /etc/systemd/system/redis.service
root@redis:/opt/redis-7.0.11# systemctl daemon-reload
root@redis:/opt/redis-7.0.11# systemctl start redis
root@redis:/opt/redis-7.0.11# systemctl enable redis
Created symlink /etc/systemd/system/multi-user.target.wants/redis.service → /etc/systemd/system/redis.service.
root@redis:/opt/redis-7.0.11#
Redis客户端访问
和MySQL一样,Redis自带一个命令行客户端: redis-cli,具体使用方式如下
redis-cli [options]
options 代表具体的一些选项,比如常见的如下:
1 -h 127.0.0.1: 指定要连接的redis节点 ip 地址,默认是本机
2 -p 6379: 指定要连接的redis节点的端口
3 -a 753159: 指定redis访问密码
redis-cli -p 6379 -a 123456
redis-cli -p 6378 -a 123456
root@redis:~# redis-cli -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379>
ping命令
ping命令使用客户端向Redis服务器发送一个PING,如果服务器运作正常的话,会返回一个PONG.
通常用于测试与服务器的连接是否仍然生效,或者用于测量延迟值。
我们可以通过这样的命令来进行测试:
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>set name tom # redis存储数据
ok
127.0.0.1:6379>get name # redia 取出数据
"tom"
127.0.0.1:6378> dbsize # redis 查看数据库大小
(integer) 1
127.0.0.1:6379> set name jerry
OK
127.0.0.1:6379> get name
"jerry"
127.0.0.1:6379> dbsize # 当key(name)值相同时,后面的key值会覆盖前面的值
(integer) 1
127.0.0.1:6379> set age 18
OK
127.0.0.1:6379> get name
"jerry"
127.0.0.1:6379> get age
"18"
127.0.0.1:6379> DBSIZE
127.0.0.1:6378> keys * # 查看所有的key
1) "age"
2) "name"
(integer) 2
127.0.0.1:6379> flushdb # 清空数据
OK
127.0.0.1:6379> DBSIZE # 查看数据大小
(integer) 0
127.0.0.1:6379> select 0 # 切换数据库(select index[0-15])
OK
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> select 5
OK
127.0.0.1:6378> TYPE name # 返回 key 所存储的 value 的数据结构类型
string
127.0.0.1:6378> DEL [name age] # 删除指定的一批 keys
(integer) 0
127.0.0.1:6378> set name kerry
OK
127.0.0.1:6378> set age 18
OK
127.0.0.1:6378> exists age # 判断当前 key 是否存在
(integer) 1
127.0.0.1:6378> exists tom
(integer) 0
127.0.0.1:6378> flushall
OK
127.0.0.1:6378> get name
(nil)
127.0.0.1:6378> get age
(nil)
127.0.0.1:6379> set hot aaa # 设置热点
OK
127.0.0.1:6379> get hot # 获取热点
"aaa"
127.0.0.1:6379> expire hot 10 # 设置热点过期时间
(integer) 1
127.0.0.1:6379> ttl hot # 返回 key 剩余的过期时间
(integer) -2 # 如果 key 不存在或者已过期,返回-2
127.0.0.1:6379> get hot # 再次查看热点值已经不存在了
(nil)
127.0.0.1:6379> ttl age
(integer) -1 # 如果 key 存在并且没有设置过期时间 (永久有效),返回 -1
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> MOVE age 1 # 把当前数据库中的 'age' 移动到 编号为1的数据库
(integer) 1
127.0.0.1:6379> keys * # 查看当前数据库中的key为 'age' 发现已经没有age了
(empty array)
127.0.0.1:6379> select 1 # 切换到编号为1的数据库
OK
# 查看该数据库中是否有 key 为 age 的数据 有如下三种方式可以查看
127.0.0.1:6379[1]> get age
"18"
127.0.0.1:6379[1]> keys *
1) "age"
127.0.0.1:6379[1]> exists age
(integer) 1
127.0.0.1:6379[1]> TYPE age
string # redis 默认采用 string 来存储数据
127.0.0.1:6379[1]> set phone 123
OK
127.0.0.1:6379[1]> keys *
1) "age"
2) "phone"
127.0.0.1:6379[1]> set key qf
OK
127.0.0.1:6379[1]> keys *
1) "age"
2) "key"
3) "phone"
127.0.0.1:6379[1]> del key # 删除 key
(integer) 1
127.0.0.1:6379[1]> keys *
1) "age"
2) "phone"
127.0.0.1:6379[1]> del age phone # 删除多个key,各个key用空格分开就可以了
(integer) 2
127.0.0.1:6379[1]> keys *
(empty array)
注意:Redis默认从16个数据库,默认使用第0个
可以通过Select进行切换,当然我们还可以查看当前库大小
select 0 # 切换数据库(index[0-15]) index最大值为15
dbsize # 查看数据库大小
flushdb # 清除当前数据库数据
flushall # 清除全部数据(flushall)
当然因为它是 key:value 结构的,我们还可以直接通过 set 与 get 来添加数据,当然还有一些基础命令如下:
set name qf # 存入数据
get qf # 取出数据
keys * # 查看所有的key [keys pattern]
flushall # 清除全部数据
flushdb # 清空当前数据
Redis认知补充
Redis快的真正原因
1 内存存储: Redis 将所有数据保存在内存中,内存读写速度非常快,远快于硬盘。这也是 redis 最主要的性能优势。
2 数据结果简单:redis 支持的数据结构比较简单(例如字符串,哈希,列表,集合和有序集合),这也在一定程度是提高了其效率。
3 非阻塞 IO:redis 使用单线程和非阻塞I/O多路复用库处理并发连接。在处理大量并发连接时,这种模型比多线程和阻塞 I/O 的模型要高效
4 持久化策略:redis 提供了多种灵活的数据持久化方式,包括RDB 快照和AOF 日志。用户可以根据需求选择最合适的持久化策略,以平衡性能和数据安全之间的关系。
5 优化的数据结构:redis 为了高效地实现其命令,使用了许多优化的数据结构和算法,例如 快速列表,跳跃列表和压缩列表
总结:因此,redis 可以处理大量的读写操作,特别是在需要高速缓存,会话缓存,队列和发布/订阅等高性能场景中,redis的性能表现非常出色。
Redis 是单线程的吗?
Redis 在处理命令请求时是单线程的,也就是说在任意时刻,redis只会使用一个CPU核心。redis 的作者 Antirez(Salvatore Sanfilippo)设计redis时,就选择了这种单线程模型,因为在很多场景下,单线程能够更好地避免竞态条件和复杂的同步问题,简化了系统的设计和运行机制。
然而,这并不意味着 redis 的所有操作都是单线程的。例如,redis 的某些后台操作,如持久化,数据清理和复制等,是由单独的线程完成的。另外,从redis4.0开始,某些耗时的操作,如删除大key 和 LRU 过期等,也可以由后台线程异步处理。
所以,在理解 redis 是单线程的时候,需要理解这是指 redis 主线程处理网络请求和执行命令是单线程的。这种设计充分利用了CPU 和内存的高速性能,避免了多线程之间的上下文切换和资源竞争,保证了极高的执行效率。
Redis 的数据类型
其实最经典就是五大数据类型,具体如下:
当然因为 redis 是一个 key-value 的数据库,key 一般是String类型
String
List
Set
Hash
SortedSet(Zset)
当然除了这些以外还有一些特殊的类型,总体凑起来目前应该有10个数据类型,所以我们先从主要的数据类型开始
这里说一下,如果想详细学习每个类型具体的一些命令和使用,我们其实可以参照官网:
https://redis.io/docs/data-types/tutorial/#keys
https://redis.io/docs/latest/#keys
VScode编辑工具官网:
https://code.visualstudio.com/
Rediskey的基本命令
keys * # 查看所有的 key
Exists key {key...} # 判断当前 key 是否存在
ExPIRE key seconds 设置 key 的过期时间,超过时间后,将会自动删除该 key,单位是秒。(热点数据)
TTL key 返回 key 剩余的过期时间。这种反射能力允许 Redis 客户端检查指定 key 在数据集里面的有效期。
如果 key 不存在或者已过期,返回-2
如果 key 存在并且没有设置过期时间 (永久有效),返回 -1.
Move key db 将当前数据库的 key 移动到给定的数据库 db 当中。如果当前数据库(源数据库)和给定数据库(目标数据库)有相同名字的给定 key,或者 key 不存在于当前数据库,那么 MOVE 没有任何效果
TYPE key 返回 key 所存储的 value 的数据结构类型。
DEL key [key...] 删除指定的一批 keys,如果删除中的某些 key 不存在,则直接忽略
flushall清除全部库数据
flushdb 清空当前库数据
Redis数据类型-String
String 类型可以是说Redis最基本也是最常用的数据类型了,一个key对应一个value.
String 类型基本上可以包含任何数据,比如图片或者序列化的对象等。
一个Redis中的字符串 value 最多可以是512M
String的常见命令:
SET: 添加或者修改已经存在的一个String类型的键值对(如果key不存在则是新增,如果存在则是修改)
GET: 根据key获取String类型的value
GETSET: 先获取在设置,如果get时值不存在返回空,然后在进行设置,如果get时值存在,返回对应的值,在进行修改
APPEND: Append命令用于为指定的 key追加值,如果key已经存在并且是一个字符串,APPEND命令将value值追加到key原来的值的末尾,如果key不存在,APPEND就简单地将给定key设为value,就像执行SET key value一样
MSET:批量添加多个String类型的键值对
MGET : 根据多个key获取多个String类型的value
MSETNX: 命令用于所有给定key都不存在时,同时设置一个或多个key-value对。(原子性操作)
INCR: 命令将key中存储的数字值增一。如果key不存在,那么key的值会先被初始化为0,然后再执行INCR操作。如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。本操作的值限制在64位(bit)有符号数字表示至内。
INCRBY: 让一个整型的值自增并指定步长 (例如:num5让num值自增5,其余与INCR一致)
DECR: 命令将key中存储的数字值减一(与INCR命令相反,其余一致)
DECRBY: 让一个整型的值自增并指定步长(与INCRBY相反,其余一致)。
SETNX: 添加一个String类型的键值对,前提是这个key不存在,否则不执行(与MSETNX区别在于,此命令只能设置一组key-value)
SETEX: 命令为指定的key设置值及其过期时间。如果key已经存在,SETEX命令将会替换旧的值
注意:mset与msetnx区别
在Redis中,SET和SETNX命令用于设置字符串类型的键值,但他们在处理键已经存在的情况下的行为是不同的。当然MSET与MSETNX与之同理,只是添加MSET与MSETNX可以批量添加数据
1. SET命令: 如果键已经存在,SET会直接覆盖旧的值,无论键是否存在,都将设置新值。例如: SET mykey "hello"
2. SETNX命令: SETNX表示 "SET if Not exist",也就是只有在键不存在的情况下,才会设置新的值。如果键已经存在,SETNX将不做任何操作。例如: SETNX mykey "hello"
SETNX命令常常被用于实现锁和其他需要保证原子性的操作。例如,你可以使用SETNX来实现一个分布式锁,只有第一个请求的客户端可以获取锁(设置成功),后来的客户端因为键已经存在,所以设置失败,从而实现锁的功能。
总的来说。SET和SETNX的主要区别在于他们任何处理键已经存在的情况
常用命令实践
[root@mail ~]# redis-cli -p 6378 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# getset 先获取在设置,如果get时值不存在返回空,然后在进行设置,如果get时值存在,返回对应的值,在进行修改
127.0.0.1:6378> set age 18
OK
127.0.0.1:6378> get age
"18"
127.0.0.1:6378> getset age 20
"18"
127.0.0.1:6378> get age
"20"
127.0.0.1:6378> getset key1 qf
(nil)
127.0.0.1:6378> get key1
"qf"
# APPEND: Append命令用于为指定的 key追加值,如果key已经存在并且是一个字符串,APPEND命令将value值追加到key原来的值的末尾,如果key不存在,APPEND就简单地将给定key设为value,就像执行SET key value一样
127.0.0.1:6378> APPEND key1 java
(integer) 6
127.0.0.1:6378> get key1
"qfjava"
127.0.0.1:6378> APPEND key2 php
(integer) 3
127.0.0.1:6378> get key2
"php"
127.0.0.1:6378> flushdb 清空当前库中数据
OK
127.0.0.1:6378> keys *
(empty array)
# MSET:批量添加多个String类型的键值对
127.0.0.1:6378> MSET k1 a1 k2 a2 k3 a3 k4 a4
OK
127.0.0.1:6378> mset user:1:name mask user:1:age 18 # 存储对象数据
OK
# MGET : 根据多个key获取多个String类型的value
127.0.0.1:6378> mget k1 k2 k3 k4
1) "a1"
2) "a2"
3) "a3"
4) "a4"
127.0.0.1:6378> keys *
1) "k2"
2) "k3"
3) "k1"
4) "k4"
127.0.0.1:6378> mget user:1:name user:1:age
1) "mask"
2) "18"
# MSETNX: 命令用于所有给定key都不存在时,同时设置一个或多个key-value对。(原子性操作)
127.0.0.1:6378> msetnx key1 k1 key2 k2
(integer) 1
127.0.0.1:6378> mget key1 key2
1) "k1"
2) "k2"
127.0.0.1:6378> keys *
1) "k2"
2) "user:1:name"
3) "k1"
4) "k3"
5) "key1"
6) "user:1:age"
7) "key2"
8) "k4"
127.0.0.1:6378> MSETNX key1 aaa key3 bbb # 有一个key不存在,整体就都不生效
(integer) 0 # 原子性操作,要么全部成功,要么全部失败
127.0.0.1:6378> keys *
1) "k2"
2) "user:1:name"
3) "k1"
4) "k3"
5) "key1"
6) "user:1:age"
7) "key2"
8) "k4"
127.0.0.1:6378>
# INCR: 命令将key中存储的数字值增一。如果key不存在,那么key的值会先被初始化为0,然后再执行INCR操作。如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。本操作的值限制在64位(bit)有符号数字表示至内。一般使用场景做计算使用
127.0.0.1:6378> set num 1
OK
127.0.0.1:6378> get num
"1"
127.0.0.1:6378> incr num
(integer) 2
127.0.0.1:6378> get num
"2"
127.0.0.1:6378> incr num
(integer) 3
127.0.0.1:6378> get num
"3"
127.0.0.1:6378> incr num1
(integer) 1
127.0.0.1:6378> get num1
"1"
127.0.0.1:6378> incr num1
(integer) 2
127.0.0.1:6378> get num1
"2"
# INCRBY: 让一个整型的值自增并指定步长 (例如:num5让num值自增5,其余与INCR一致)
127.0.0.1:6378> incrby num 3 # 指定增长步长为3
(integer) 6
127.0.0.1:6378> get num
"6"
127.0.0.1:6378> incrby num 3
(integer) 9
127.0.0.1:6378> get num
"9"
# DECR: 命令将key中存储的数字值减一(与INCR命令相反,其余一致)
127.0.0.1:6378> decr num # 递减1
(integer) 8
127.0.0.1:6378> decr num
(integer) 7
127.0.0.1:6378> decr num
(integer) 6
# DECRBY: 让一个整型的值自增并指定步长(与INCRBY相反,其余一致)。
127.0.0.1:6378> decrby num 2 # 指定递减步长
(integer) 4
127.0.0.1:6378> decrby num 2
(integer) 2
127.0.0.1:6378> get num
"2"
127.0.0.1:6378> decrby num 2
(integer) 0
127.0.0.1:6378> get num
"0"
# SETNX: 添加一个String类型的键值对,前提是这个key不存在,否则不执行(与MSETNX区别在于,此命令只能设置一组key-value)也是原子性操作,每次只能设置一组
127.0.0.1:6378> keys *
1) "num1"
2) "num"
3) "user:1:name"
4) "k2"
5) "k3"
6) "k1"
7) "key1"
8) "k4"
9) "key2"
10) "num2"
11) "user:1:age"
127.0.0.1:6378> SETNX k1 111
(integer) 0
127.0.0.1:6378> get k1
"a1"
127.0.0.1:6378> SETNX k5 wwww
(integer) 1
127.0.0.1:6378> get k5
"wwww"
# SETEX: 命令为指定的key设置值及其过期时间。如果key已经存在,SETEX命令将会替换旧的值 语法:SETEX KEY SECONDS VALUE # 设置过期后的值
127.0.0.1:6378> set k6 a6
OK
127.0.0.1:6378> get k6
"a6"
127.0.0.1:6378> setex k6 20 redis # 设置20秒后的值为redis
OK
127.0.0.1:6378> get k6
"redis"
127.0.0.1:6378> setex k5 60 java
OK
127.0.0.1:6378> ttl k5
(integer) 53
127.0.0.1:6378> ttl k5
(integer) 46
127.0.0.1:6378> ttl k5
(integer) 38
127.0.0.1:6378> ttl k5
(integer) 24
127.0.0.1:6378> ttl k5
(integer) 13
127.0.0.1:6378> ttl k5
(integer) -2
127.0.0.1:6378> get k5
(nil)
127.0.0.1:6378> setex k9 10 php
OK
127.0.0.1:6378> get k9 # 没有超过10秒内key的值为php
"php"
127.0.0.1:6378> get k9 # 超过10秒key的值为nil
(nil)
除了以上这些 String 还有一些类似于Java字符串操作的命令,比如截取字符串等,具体可以参照官网
其实String的使用场景很多,比如
计数器
统计多单位数量
粉丝数
对象缓存储存
Redis 数据类型 List
List 类型是一种有序集合,也是Redis是集成数据结构之一。List类型内部实现为一个双向链表,即每个节点都有两个指针,一个指向前一个节点,一个指向后一个节点。
List 功能非常强大,我们即可以把它当成栈(先进后出),队列(先进先出),并且可以存放重复的值。
List 甚至可以使用负数下标,以-1 表示列表的最后一个元素,-2表示列表的倒数第二个元素,以此类推。
常用命令
LPUSH key value1 value2 将一个或多个值插入到列表头部(左侧)
LRANGE key start stop 获取列表指定范围内的元素,根据下标
RPUSH key value1 value2 在列表中(右侧)添加一个或多个值
LPOP key 移除并获取列表的第一个元素
RPOP key 移除并获取列表最后一个元素
LINDEX key index 通过索引获取列表中的元素
LLEN key 获取列表长度
LREM key count value 移除列表元素(可以移除多个重复的值)
LTRIM key start stop 对一个列表进行修剪(trim),就是说,通过下标让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
RPOPLPUSH source destination 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
EXISTS也可以判断列表中是否有值(exists list)
LSET key index value 通过索引设置列表元素的值(需要保证现有列表和下标存在,一般作为更新操作)
LINSERT key BEFORE|AFTER pivot value 在列表的元素前或后插入元素
BLPOP key1 key2 timeout 移出并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
命令实践
# LPUSH key value1 value2 将一个或多个值插入到列表头部(左侧)
# 语法:LPUSH key element[element...] 列表就是key,[element...]表示可以插入多
# 个元素,L代表 LEFT,LPUSH表示从最左边开始插入 实例如下:
127.0.0.1:6378> LPUSH list one two three
(integer) 3
127.0.0.1:6378> lpush list 1
(integer) 4
127.0.0.1:6378> lpush list 2
(integer) 5
127.0.0.1:6378> LRANGE list 0 -1
1) "2"
2) "1"
3) "three"
4) "two"
5) "one"
# LRANGE key start stop 获取列表指定范围内的元素,根据下标
# '0'代表start即插入的第一个元素,'-1'代表stop即最后一个查如的元素
# 语法:LRANGE key start stop
127.0.0.1:6378> LRANGE list 0 -1
1) "2"
2) "1"
3) "three"
4) "two"
5) "one"
6) "four"
# RPUSH key value1 value2 在列表中(右侧)添加一个或多个值
# RPUSH key element [element...] 从最后一个元素开始插入
127.0.0.1:6378> RPUSH list four
(integer) 6
127.0.0.1:6378> RPUSH list five
(integer) 7
127.0.0.1:6378> RPUSH list six
(integer) 8
127.0.0.1:6378> LRANGE list 0 -1
1) "2"
2) "1"
3) "three"
4) "two"
5) "one"
6) "four"
7) "five"
8) "six"
127.0.0.1:6378> RPUSH list seven eight nine
(integer) 11
127.0.0.1:6378> LRANGE list 0 -1
1) "2"
2) "1"
3) "three"
4) "two"
5) "one"
6) "four"
7) "five"
8) "six"
9) "seven"
10) "eight"
11) "nine"
# LPOP key 移除并获取列表的第一个元素
# 语法:LPOP key [count]
127.0.0.1:6378> LPOP list 1
1) "2"
# RPOP key 移除并获取列表最后一个元素
# 语法:RPOP key [count]
127.0.0.1:6378>RPOP list 1
"four"
# LINDEX key index 通过索引获取列表中的元素
# 语法:LINDEX key index 通过'index'索引下标可以找出列表中的元素
127.0.0.1:6378> LPUSH list one two three four # 从左侧插入4个元素
(integer) 4
127.0.0.1:6378> LRANGE list 0 -1 # 查看列表中所有元素
1) "four"
2) "three"
3) "two"
4) "one"
127.0.0.1:6378> LINDEX list 1 # 查找索引下标为1的元素
"three"
# LLEN key 获取列表长度
127.0.0.1:6378> LLEN list # 获取列表长度
(integer) 4
# LREM key count value 移除列表元素(可以移除多个重复的值)
# 语法: LREM key count element
127.0.0.1:6378> LPUSH list two # 往列表中添加一个元素
(integer) 5
127.0.0.1:6378> lrange list 0 -1 # 再次查看列表中所有元素
1) "two"
2) "four"
3) "three"
4) "two"
5) "one"
127.0.0.1:6378> LREM list 1 two # 删除一个 two 元素
(integer) 1
127.0.0.1:6378> lrange list 0 -1
1) "four"
2) "three"
3) "two"
4) "one"
127.0.0.1:6378>
# LTRIM key start stop 对一个列表进行修剪(trim),就是说,通过下标让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
127.0.0.1:6378> lrange list 0 -1
1) "four"
2) "three"
3) "two"
4) "one"
127.0.0.1:6378> LTRIM list 1 3
OK
127.0.0.1:6378> lrange list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6378>
# RPOPLPUSH source destination 移除列表的最后一个元素,并将该元素添加到另一个列表并返回,这个重点掌握,现实工作中有很多用处,比如把购物车中商品移动到支付列表中等
127.0.0.1:6378> RPUSH qlist 1 2 3 4
(integer) 4
127.0.0.1:6378> lrange qlist 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
# 从右边开始移除 'qlist'中的数据,然后再把移动的元素添加到 'flist' 列表中
127.0.0.1:6378> RPOPLPUSH qlist flist
"4"
127.0.0.1:6378> lrange flist 0 -1
1) "4"
127.0.0.1:6378> lrange qlist 0 -1
1) "1"
2) "2"
3) "3"
# EXISTS也可以判断列表中是否有值(exists list)
127.0.0.1:6378> exists flist
(integer) 1 # 返回 1 表示有数据
127.0.0.1:6378> exists qlist
(integer) 1
127.0.0.1:6378> lpop flist 1
1) "4"
127.0.0.1:6378> lrange flist 0 -1
(empty array)
127.0.0.1:6378> exists flist # 返回 0 表示没有数据
(integer) 0
127.0.0.1:6378> flushdb # 清空当前数据库中的数据
OK
# LSET key index value 通过索引设置列表元素的值(需要保证现有列表和下标存在,一般作为更新操作)
# 语法:LSET key index element
# 列表和下标都不存在,无法做更新操作,所以报错
127.0.0.1:6378> LSET mylist 0 one
(error) ERR no such key
127.0.0.1:6378> rpush mylist one two three # 在列表中添加数据
(integer) 3
127.0.0.1:6378> lrange mylist 0 -1
1) "one"
2) "two"
3) "three"
# 因为列表中有数据,所以再次执行 'lset mylist 0 one' 就不报错了
127.0.0.1:6378> lset mylist 0 one
OK
127.0.0.1:6378> lrange mylist 0 -1
1) "one"
2) "two"
3) "three"
127.0.0.1:6378> lset mylist 2 hello # 更新元素操作
OK
127.0.0.1:6378> lrange mylist 0 -1
1) "one"
2) "two"
3) "hello"
# LINSERT key BEFORE|AFTER pivot value 在列表的元素前或后插入元素
# 语法: LINSERT key BEFORE | AFTER PIVOT(核心,支撑点) element
127.0.0.1:6378> LINSERT mylist before hello af # 在 hello 之前插入 af
(integer) 4
127.0.0.1:6378> lrange mylist 0 -1 #查看列表信息
1) "one"
2) "two"
3) "af"
4) "hello"
127.0.0.1:6378> LINSERT mylist after two jack # 在two之后插入 'jack'
(integer) 5
127.0.0.1:6378> lrange mylist 0 -1 查看列表信息
1) "one"
2) "two"
3) "jack"
4) "af"
5) "hello"
# BLPOP key1 key2 timeout 移出并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
# 语法:BLPOP key [key...] timeout
127.0.0.1:6378> LRANGE list 0 -1
(empty array)
127.0.0.1:6378> BLPOP list 10
(nil) # 没有元素发生了阻塞,超过10秒拿到一个 nil 空值
(10.06s)
127.0.0.1:6378> BRPOP list 10
(nil)
(10.02s)
127.0.0.1:6378> lpop list 1
(nil) # 直接取出元素,这就是不阻塞的效果
127.0.0.1:6378>
List小结
1. 我们可以把list看成一个链表,前后中间都可以插入数据
2. 如果key不存在。则创建新的 list (链表)
3. 如果 key存在,新增或者修改内容
4. 如果某一个list中没有任何数据,表示不存在(空链表)
5. 既然类似于链表,两边数据的插入和改动效率高,中间效率稍低
6. 常用功能:消息队列,消息排队(lpush rpop)栈(lpush lpop)
Redis数据类型-set
Redis的set是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据(无序不重复)
常见命令
SADD key member1[member2] 向集合添加一个或多个成员
SMEMBERS key 返回集合中的所有成员
SISMEMBER key member 判断 member 元素是否是集合 key 的成员
SCARD key 获取集合的成员数
SREM key member1[member2] 移除集合中一个或多个成员
SRANDMEMBER key [count] 返回集合中一个或多个随机数
spop key 移除并返回集合中的一个随机元素(原子操作,多个客户端并发访问时,每个返回的元素都是唯一的)
SMOVE source destination member 将 member 元素从 source 集合移动到 destination 集合
SDIFF key1 key2返回给定所有集合的差集(两个set中不同的值)
SINTER key1 key2返回给定所有集合的交集(两个set中相同的值)
SUNION key1 key2返回所有给定集合的并集(两个set中所有的值,重复的只有一个)
SDIFF,SINTER,SUNION这些命令就可以完成 共同好友,共同爱好等类似的功能,比如将用户的关注的人关注放入到 set中,即可完成"共同关注"功能
SDIFFSTORE destination key1 key2返回给定所有集合的差集并存储在 destination中
SINTERSTORE destination key1 key2返回给定所有集合的交集并存储在 destination 中
SUNIONSTORE destination key1 key2所有给定集合的并集存储在destination中
由于Set类型的特性,他经常被用来实现标签系统,好友关系,粉丝关系等功能。
常见命令使用
# SADD key member1[member2] 向集合添加一个或多个成员
127.0.0.1:6378> flushall 清空数据
OK
127.0.0.1:6378> SADD myset aaa bbb ccc # 添加元素
(integer) 3
# SMEMBERS key 返回集合中的所有成员
127.0.0.1:6378> smembers myset # 查看添加的元素
1) "ccc"
2) "aaa"
3) "bbb"
# SISMEMBER key member 判断 member 元素是否是集合 key 的成员
127.0.0.1:6378> sismember myset ccc
(integer) 1 # 返回'1'代表存在该元素
127.0.0.1:6378> sismember myset ddd
(integer) 0 # 返回 '0'代表不存在该元素
# SCARD key 获取集合的成员数
127.0.0.1:6378> SCARD myset
(integer) 3 # 返回 '3' 表示集合中有3个成员
# SREM key member1[member2] 移除集合中一个或多个成员
# 语法:SREM key member [member...]
127.0.0.1:6378> SREM myset aaa bbb
(integer) 2 # 删除两个元素
127.0.0.1:6378> SMEMBERS myset # 查看当前集合的元素
1) "ccc"
127.0.0.1:6378> flushall # 清空所有数据库中的数据
OK
127.0.0.1:6378> SMEMBERS myset # 查看当前集合的元素
(empty array)
# SRANDMEMBER key [count] 返回集合中一个或多个随机数
127.0.0.1:6378> SADD myset aaa bbb ccc ddd eee # 添加元素,准备实验数据
(integer) 5
127.0.0.1:6378> SRANDMEMBER myset 2
1) "ccc"
2) "ddd"
127.0.0.1:6378> SRANDMEMBER myset 3
1) "ccc"
2) "eee"
3) "bbb"
127.0.0.1:6378> SRANDMEMBER myset 3
1) "eee"
2) "bbb"
3) "aaa"
# spop key 移除并返回集合中的一个随机元素(原子操作,多个客户端并发访问时,每个返回的元素都是唯一的)使用场景 抽奖
127.0.0.1:6378> spop myset 1 # 移除并返回集合中的一个随机元素
1) "bbb"
127.0.0.1:6378> SMEMBERS myset # 查看当前集合的元素
1) "ccc"
2) "ddd"
3) "eee"
4) "aaa"
127.0.0.1:6378> SPOP myset 1
1) "ccc"
127.0.0.1:6378> smembers myset
1) "ddd"
2) "eee"
3) "aaa"
# SMOVE source destination member 将 member 元素从 source 集合移动到 destination 集合
# 语法:SMOVE source destination member
# 'source'为源 'myset','destination'为目标 's1','member'为源myset中任意成员
127.0.0.1:6378> SMOVE myset s1 aaa
(integer) 1
127.0.0.1:6378> SMEMBERS s1 # 查看 s1 当前集合的元素
1) "aaa"
127.0.0.1:6378> SMEMBERS myset # 查看 myset 当前集合的元素
1) "ddd"
2) "eee"
127.0.0.1:6378> flushall # 清空所有数据
OK
# SDIFF key1 key2返回给定所有集合的差集(两个set中不同的值)
# 语法:SDIFF key [key...]
127.0.0.1:6378> flushall # 清空所有数据
OK
127.0.0.1:6378> SADD s1 aaa bbb ccc # 准备数据
(integer) 3
127.0.0.1:6378> SADD s2 ccc ddd eee # 准备数据
(integer) 3
# 这里是以 s1 作为参照物 (即 s1与s2,s1中不同是元素)
127.0.0.1:6378> SDIFF s1 s2
1) "aaa"
2) "bbb"
# 这里是以 s2 作为参照物 (即 s1与s2,s2中不同是元素)
127.0.0.1:6378> SDIFF s2 s1 # 这里是以 s2 作为参照物
1) "ddd"
2) "eee"
# SINTER key1 key2返回给定所有集合的交集(两个set中相同的值)
# 语法:SINTER key [key...]
127.0.0.1:6378> SINTER s1 s2
1) "ccc"
# SUNION key1 key2返回所有给定集合的并集(两个set中所有的值,重复的只有一个)
# 语法:SUNION key [key...]
127.0.0.1:6378> SUNION s1 s2
1) "bbb"
2) "ccc"
3) "ddd"
4) "eee"
5) "aaa"
# SDIFF,SINTER,SUNION这些命令就可以完成 共同好友,共同爱好等类似的功能,比如将用户的关注的人关注放入到 set中,即可完成"共同关注"功能
# SDIFFSTORE destination key1 key2返回给定所有集合的差集并存储在destination中
# 语法:SDIFFSTORE destination key [key...]
# 命令描述:这里是以 s1 作为参照物 (即 s1与s2,s1中不同是元素存储到目标集合key1)
127.0.0.1:6378> SDIFFSTORE key1 s1 s2
(integer) 2 # 表示存储了2条数据到key1目标集合
127.0.0.1:6378> SMEMBERS key1 # 查看目标集合key1中存储的元素
1) "aaa"
2) "bbb"
# SINTERSTORE destination key1 key2返回给定所有集合的交集并存储在destinatio中
# 语法:SINTERSTORE destination key [key...]
127.0.0.1:6378> SINTERSTORE key2 s1 s2
(integer) 1
127.0.0.1:6378> SMEMBERS key2
1) "ccc"
# SUNIONSTORE destination key1 key2所有给定集合的并集存储在destination中
# 语法: SUNIONSTORE destination key [key...]
127.0.0.1:6378> SUNIONSTORE key3 s1 s2
(integer) 5
127.0.0.1:6378> smembers key3
1) "bbb"
2) "ccc"
3) "ddd"
4) "eee"
5) "aaa"
127.0.0.1:6378>
Hash 哈希类型详解
Redis hash 是一个 String 类型的 field和value的映射表,hash特别适合用于存储对象。
我们可以把它想象成Map集合key:<key-value>
Redis的Hash数据类型是用来表示键值对映射的一种数据类型,通常用于表示对象,如用户信息,商品信息等。哈希可以存储大量的字段-值对,并且设计得十分节省空间,使其成为表示数据对象的理想选择。你可以用哈希来表示基本对象,也可以用来存储一组计数器等多种数据。
Redis的Hash数据类型使用场景: 做数据存储和数据频繁更改
常见命令
HSET key field1 value1 field2 value2 同时将多个 field-value(域-值)对设置到哈希表 key 中
注意:Redis 4.0.0版本以后,HMSET被视为已弃用。请在新代码中使用HSET
HGET key field 获取存储在哈希表中指定字段的值
HMGET key field1 field2 获取所有给定字段的值
HGETALL key 获取在哈希表中指定 key 的所有字段和值
HDEL key field1 field2删除一个或多个哈希表字段
HLEN key 获取哈希表中字段的数量
HKEYS keys 获取所有哈希表中的字段
HVALS key 获取哈希表中所有值
HEXISTS key field 查看哈希表 key 中,指定的字段是否存在。
HINCRBY key field increment 为哈希表 key 中的指定字段的整数值加上增量 increment (如果是负数,就是减量)。
HSETNX key field value 只有在字段 field 不存在时,设置哈希表字段的值(原子性操作)。
hash常见命令使用
# HSET key field1 value1 field2 value2 同时将多个 field-value(域-值)对设置到哈希表 key 中
# 语法: HSET key field value [field value ...]
127.0.0.1:6378> flushall
OK
# 设置哈希表hash1中的域-值对
127.0.0.1:6378> HSET hash1 key1 a1 key2 a2 key3 a3
(integer) 3
127.0.0.1:6378>
# 注意:Redis 4.0.0版本以后,HMSET被视为已弃用。请在新代码中使用HSET
# HGET key field 获取存储在哈希表中指定字段的值
# 语法:HGET key field 该命令每次只能获取一个域与值对
127.0.0.1:6378> HGET hash1 key1
"a1"
127.0.0.1:6378> HGET hash1 key2
"a2"
127.0.0.1:6378> hget hash1 key3
"a3"
# HMGET key field1 field2 获取所有给定字段的值
# 语法:HMGET key field [field ...]
127.0.0.1:6378> HMGET hash1 key1 key2 key3
1) "a1"
2) "a2"
3) "a3"
# HGETALL key 获取在哈希表中指定 key 的所有字段和值
# 语法 HGETALL key
127.0.0.1:6378> HGETALL hash1
1) "key1"
2) "a1"
3) "key2"
4) "a2"
5) "key3"
6) "a3"
127.0.0.1:6378> HSET hash1 key1 aaa key2 bbb # 覆盖的效果
(integer) 0
127.0.0.1:6378> HGETALL hash1
1) "key1"
2) "aaa"
3) "key2"
4) "bbb"
5) "key3"
6) "a3"
# HDEL key field1 field2删除一个或多个哈希表字段
# 语法: HDEL key field [field ...]
127.0.0.1:6378> HDEL hash1 key1 key2
(integer) 2
127.0.0.1:6378> HGETALL hash1 # 获取在哈希表中指定 key 的所有字段和值
1) "key3"
2) "a3"
# HLEN key 获取哈希表中字段的数量
# 语法:HLEN key
127.0.0.1:6378> FLUSHALL # 清空数据
OK
127.0.0.1:6378> HSET qf k1 v1 k2 v2 k3 v3 # 准备数据
(integer) 3
127.0.0.1:6378> HGETALL qf # 获取在哈希表qf中指定 key 的所有字段和值
1) "k1"
2) "v1"
3) "k2"
4) "v2"
5) "k3"
6) "v3"
127.0.0.1:6378> HLEN qf # 获取哈希表中字段的数量
(integer) 3
# HKEYS key 获取所有哈希表中的字段
# 语法:HKEYS key
127.0.0.1:6378> HKEYS qf # 获取所有哈希表qf中的字段
1) "k1"
2) "k2"
3) "k3"
# HVALS key 获取哈希表中所有值
# 语法: HVALS key
127.0.0.1:6378> HVALS qf # 获取哈希表中所有值
1) "v1"
2) "v2"
3) "v3"
# HEXISTS key field 查看哈希表 key 中,指定的字段是否存在。
# 语法: HEXISTS key field
127.0.0.1:6378> HEXISTS qf k2
(integer) 1 # 返回 '1' 表示当前哈希表 qf 中包含字段 k2
127.0.0.1:6378> HEXISTS qf k4
(integer) 0 # 返回 '0' 表示当前哈希表 qf 中不包含字段 k4
# HINCRBY key field increment 为哈希表 key 中的指定字段的整数值加上增量 increment (如果是负数,就是减量)。
# 语法:HINCRBY key field increment
127.0.0.1:6378> HSET hash1 k1 1 k2 2 k3 3 # 准备数据
(integer) 3
127.0.0.1:6378> HGETALL hash1
1) "k1"
2) "1"
3) "k2"
4) "2"
5) "k3"
6) "3"
# 为哈希表 hash1 中的指定字段 k1 的整数值加上增量 2
127.0.0.1:6378> HINCRBY hash1 k1 2
(integer) 3
127.0.0.1:6378> HGET hash1 k1 # 获取存储在哈希表 hash1 中指定字段k1的值
"3"
为哈希表 hash1 中的指定字段 k3 的整数值加上减量 -1
127.0.0.1:6378> HINCRBY hash1 k3 -1
(integer) 2
127.0.0.1:6378> HGET hash1 k3 # 获取存储在哈希表 hash1 中指定字段k3的值
"2"
# HSETNX key field value 只有在字段 field 不存在时,设置哈希表字段的值(原子性操作)。
# HSETNX key field value
# 原子性操作,不作覆盖操作(存在,执行失败)
127.0.0.1:6378> HSETNX hash1 k1 30
(integer) 0
127.0.0.1:6378> HGET hash1 k1
"3"
# 原子性操作,不作覆盖操作(不存在,执行成功)
127.0.0.1:6378> HSETNX hash1 k4 30
(integer) 1
127.0.0.1:6378> HGET hash1 k4
"30"
127.0.0.1:6378> HGETALL hash1 # 获取在哈希表中指定 hash1 的所有字段和值
1) "k1"
2) "3"
3) "k2"
4) "2"
5) "k3"
6) "2"
7) "k4"
8) "30"
# 使用场景
127.0.0.1:6378> HSET user:1 name zhangsan age 18
(integer) 2
127.0.0.1:6378> HGETALL user:1
1) "name"
2) "zhangsan"
3) "age"
4) "18"
127.0.0.1:6378> HMGET user:1 name age
1) "zhangsan"
2) "18"
Redid数据类型-Zset(Sorted Set)
在Redis中,ZSET(有序集合)是一种复合类型的数据结构,它将Set和Hash两种数据结构进行了结合,类似与 JAVA 的 TreeMap(实际上是SkipList实现)。
在ZSET中,每个元素都是唯一的(就像Set),但是每个元素关联了一个socre(就像Hash的Value).
这个 socre(分数) 用于对元素进行从小到大的排序。
可以简单理解为在 set 的基础上,增加了一个值,
例如:Zset k1 score v1
特点: 可排序,元素不重复,查询速度快
由于这个特点所以 Zset 经常被用于排行榜类型的功能
注意:所有的排序默认都是升序排序,如果需要降序需要在Z后面加上REV
常用命令
ZADD key score member [score member ...] 向有序集合添加一个或多个成员,或者更新已存在成员的分数。
ZRANGE key start stop [WITHSCORES] 通过索引区间返回有序集合指定区间内的成员。成员按分数值递增(从小到大)来排序。
ZRANGEBYSCORE key min max WITHSCORES 通过分数返回有序集合指定区间内的成员(分数可以采用正负无穷大 -inf +inf).
ZREM key member 从有序集合中删除一个成员
ZCARD key 返回有序集合的成员数量
ZCOUNT key min max 返回有序集合中分数在给定范围内的成员数量
ZSCORE key member 返回有序集合中指定成员的分数。
常用命令的使用
# ZADD key score member [score member ...] 向有序集合添加一个或多个成员,或者更新已存在成员的分数。
# 语法:ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...]
127.0.0.1:6378> ZADD myset 1 one 2 two # 向有序集合添加一个或多个成员
(integer) 2
127.0.0.1:6378> ZADD myset 3 three 4 four
(integer) 2
# ZRANGE key start stop [WITHSCORES] 通过索引区间返回有序集合指定区间内的成员。成员按分数值递增(从小到大)来排序。
# 语法:ZRANGE key start stop [BYSCORE|BYLEX] [REV] [LIMIT offset count] [WITHSCORES]
127.0.0.1:6378> ZRANGE myset 0 -1 # 通过索引区间返回有序集合指定区间内的成员
1) "one"
2) "two"
127.0.0.1:6378> ZRANGE myset 0 -1 withscores # 添加参数查看
1) "one"
2) "1"
3) "two"
4) "2"
127.0.0.1:6378> ZADD myset 3 three 4 four
(integer) 2
127.0.0.1:6378> ZRANGE myset 0 -1 # 升序排序
1) "one"
2) "two"
3) "three"
4) "four"
# 在Z后面加上REV 降序排列
127.0.0.1:6378> ZREVRANGE myset 0 -1
1) "four"
2) "three"
3) "two"
4) "one"
127.0.0.1:6378> ZREVRANGE myset 0 -1 withscores
1) "four"
2) "4"
3) "three"
4) "3"
5) "two"
6) "2"
7) "one"
8) "1"
# ZRANGEBYSCORE key min max [WITHSCORES][LIMIT offset count] 通过分数返回有序集合指定区间内的成员(分数可以采用正负无穷大 -inf +inf).
# 语法:ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
# 一般用于统计某个范围内的值
127.0.0.1:6378> ZRANGEBYSCORE myset -inf +inf
1) "one"
2) "two"
3) "three"
4) "four"
127.0.0.1:6378> ZADD myscore 10 aaa 20 bbb 30 ccc 50 ddd 100 eee
(integer) 5
127.0.0.1:6378> ZRANGE myscore 0 -1
1) "aaa"
2) "bbb"
3) "ccc"
4) "ddd"
5) "eee"
# 取某个范围内的数据,排行榜也可以通过它来实现
127.0.0.1:6378> ZRANGEBYSCORE myscore 20 100
1) "bbb"
2) "ccc"
3) "ddd"
4) "eee"
127.0.0.1:6378> ZRANGEBYSCORE myset -inf +inf withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "four"
8) "4"
# 语法:ZRANGEBYSCORE key min max [withscores] [limit offset count]
# 跳过前面2个存储后面3个
127.0.0.1:6378> ZRANGEBYSCORE myset -inf +inf withscores limit 2 3
1) "three"
2) "3"
3) "four"
4) "4"
127.0.0.1:6378> ZRANGEBYSCORE myset -inf +inf withscores limit 1 3
1) "two"
2) "2"
3) "three"
4) "3"
5) "four"
6) "4"
127.0.0.1:6378> ZADD myset 5 five
(integer) 1
127.0.0.1:6378> zrange myset 0 -1
1) "one"
2) "two"
3) "three"
4) "four"
5) "five"
127.0.0.1:6378> ZRANGEBYSCORE myset -inf +inf withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "four"
8) "4"
9) "five"
10) "5"
# 'limit 2 3' limit表示跳过2条数据,返回后面3条数据
127.0.0.1:6378> ZRANGEBYSCORE myset -inf +inf withscores limit 2 3
1) "three"
2) "3"
3) "four"
4) "4"
5) "five"
6) "5"
# ZREM key member 从有序集合中删除一个成员
# 语法:ZREM key member [member ...]
127.0.0.1:6378> ZREM myset five one # 删除
(integer) 2
127.0.0.1:6378> ZRANGE myset 0 -1 # 查看
1) "two"
2) "three"
3) "four"
# ZCARD key 返回有序集合的成员数量
# 语法: ZCARD key
127.0.0.1:6378> ZCARD myset # 查看成员数量
(integer) 3
# ZCOUNT key min max 返回有序集合中分数在给定范围内的成员数量
# 语法:ZCOUNT key min max
127.0.0.1:6378> ZRANGE myscore 0 -1
1) "aaa"
2) "bbb"
3) "ccc"
4) "ddd"
5) "eee"
127.0.0.1:6378> ZRANGE myscore 0 -1 withscores
1) "aaa"
2) "10"
3) "bbb"
4) "20"
5) "ccc"
6) "30"
7) "ddd"
8) "50"
9) "eee"
10) "100"
# 返回20-50的人员数量
127.0.0.1:6378> ZCOUNT myscore 20 50
(integer) 3
# ZSCORE key member 返回有序集合中指定成员的分数。给一个具体的成员,返回他的分数
# 语法:ZSCORE key member
127.0.0.1:6378> ZSCORE myscore ccc
"30"
127.0.0.1:6378> ZSCORE myscore eee
"100"
127.0.0.1:6378> ZSCORE myscore ggg # 成员不存在就返回空(nil)
(nil)
Redis中文网站
可以上这个网站查看redis的命令
https://redis.net.cn/
Redis 特殊数据类型-Geospatial 地理位置
Redis的地理空间 (Geospatial) 数据结构是从3.2版本开始加入的,主要用于需要地理位置的应用场景。这种数据结构允许用户将指定的地理空间位置(经度,纬度,名称)添加到指定的 key 中,这些数据将会存储到 sorted set 中,这样设计的目的是为了方便使用GEORADIUS或者GEORADIUSBYMEMBER命令对数据进行半径查询等操作。
此命令能实现类似地理位置推算,两地之间的距离,附件的人等功能
实现原理
1,将某个地理位置的经度分别转换成二进制
2,再将两个二进制交错合并成一个即可,经度占偶数位,纬度占奇数位,得到最终的二进制
3,将合并的二进制做base32编码,得到最终结果
4,将最终结果通过 geohash处理后成功的将一个二维信息转换成了一维信息,节省存储空间,便于前缀检索
相关命令
GEOADD添加一个或多个地理位置元素到key中 语法:geoAdd key lng lat member lng1 lat1 member1
要求:满足经度在-180和180之间,纬度在-85.05112878和85.05112878之间。
GEODIST 返回一个 key 中指定两个位置之间的距离 语法:GeoDist key member1 member2
m表示单位为米
km表示单位为千米
mi表示单位为英里
ft表示单位为英尺
GEOPOS 返回一个或多个位置的经纬度信息 语法: GEOPOS key member1 member2
GEOSEARCH 命令允许你从一个给定的地理位置开始,查询在一个给定半径内的元素。此外,你可以指定搜索区域的形状为圆形(BYRADIUS)或矩形(BYBOX).
语法:
GEOSEARCH key [FROMMEMBER member] [FROMLONLAT longitude latitude] [BYRADIUS radius m|km|ft|mi] [BYBOX width height m|km|ft|mi] [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE key] [STOREDIST key]
GEOSEARCH key [FROMMEMBER member] [FROMLONLAT longitude latitude] [BYRADIUS radius m|km|ft|mi] [BYBOX width height m|km|ft|mi] [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE key] [STOREDIST key
GEOSEARCH key [FROMMEMBER member] [FROMLONLAT longitude latitude] [BYRADIUS radius m|km|ft|mi] [BYBOX width height m|km|ft|mi] [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE key] [STOREDIST key]