Redis学习——入门篇①
- 1、2:Redis入门概述
- 3:Redis安装配置
- 10 安装
- Redis-cli命令
- 4:Redis——十大数据类型
- 11 redis数据类型
- 12 命令查阅
- 13 key常用命令介绍
- 14 类型大小写和帮助命令
- 15 String 命令(上)
- 16 String 命令(下)
- 17 List
- 面试题:Redis list 可以存放的最大长度是多少?
- 18 hash
- 19 set
- 20 zset(sorted set)
- 21 bitmap
- 22 hyperloglog
- 23 geo 地理坐标
- 24 25 26 stream
- 27 bitfield——了解即可
1、2:Redis入门概述
常用网站汇总
Redis中文文档 https://www.redis.com.cn/documentation.html |
作者 Git Hub https://github.com/antirez |
Redis GitHub 源码 https://github.com/redis/redis |
Github releases 新特性https://github.com/redis/redis/releases |
Redis 在线测试 https://try.redis.io/ |
Redis 命令参考 https://redis.io/commands/ |
Redis是什么?what?
-
Redis(Remote Dictionary Server ),即远程字典服务 !
-
是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
免费和开源!是当下最热门的 NoSQL 技术之一!也被人们称之为结构化数据库!
基于内存的KV键值对内存数据库
Redis能干嘛?
- 内存存储、持久化,内存中是断电即失、所以说持久化很重要(rdb、aof)
- 效率高,可以用于高速缓存
- 发布订阅系统
- 地图信息分析
- 计时器、计数器(浏览量!)
- …
MySQL怎么了?
与传统数据库关系(mysq|)
- Redis是key-value数据库(NoSQL一种), mysql是关系数据库
- Redis数据操作主要在内存,而mysql主要存储在磁盘
- Redis在某一些场景使用中要明显优于mysql,比如计数器、排行榜等方面
- Redis通常用于一些特定场景,需要与Mysql一起配合使用
- 两者并不是相互替换和竞争关系,而是共用和配合使用
优势
- 性能极高——Redis能读的速度是
110000次/秒
,写的速度是81000次/秒
- Redis数据类型丰富,不仅仅支持简单的key-value类型的数据,
- 同时还提供
list
,set
,zset
,hash
等 数据结构的存储 - Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,
- 重启的时候可以再次加载进行使用
- Redis支持数据的备份,即master-slave模式的数据备份
3:Redis安装配置
https://redis.io/download/
- Redis在线测试——https://try.redis.io
- Redis命令参考——http://doc.redisfans.com
10 安装
第一步:查询 Linux系统位数
[root@localhost redis-one]# getconf LONG_BIT
64
第二步:准备系统环境
gcc -v
yum -y install gcc-c++
[root@localhost redis-one]# gcc -v
......省略部分代码
gcc 版本 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
[root@localhost redis-one]#
第三步:上传并解压 Redis压缩包
tar -zxvf redis-7.0.8.tar.gz
第四步:在Redis目录安装 Redis
cd redis-7.0.8
make && make install
安装后效果
[root@localhost redis-7.0.8]# cd /usr/local/bin/
[root@localhost bin]# ll
总用量 21524
-rwxr-xr-x. 1 root root 5197776 2月 22 16:32 redis-benchmark
lrwxrwxrwx. 1 root root 12 2月 22 16:32 redis-check-aof -> redis-server
lrwxrwxrwx. 1 root root 12 2月 22 16:32 redis-check-rdb -> redis-server
-rwxr-xr-x. 1 root root 5411112 2月 22 16:32 redis-cli
lrwxrwxrwx. 1 root root 12 2月 22 16:32 redis-sentinel -> redis-server
-rwxr-xr-x. 1 root root 11426784 2月 22 16:32 redis-server
[root@localhost bin]#
第五步:备份配置文件 redis.conf
cp redis.conf redis-bf.conf
第六步:打开配置文件并修改redis-bf.conf,对照修改配置
daemonize yes
protected-mode no
#bind 127.0.0.1 -::1
requirepass 123456
第七步:启动 redis-server
redis-server redis-bf.conf
ps -ef|grep redis 或者
ps -ef|grep redis|grep -v grep
[root@localhost bin]# ps -ef|grep redis
root 2129 1 0 14:43 ? 00:00:11 redis-server 0.0.0.0:6379
root 3461 1947 0 16:24 pts/0 00:00:00 grep --color=auto redis
[root@localhost bin]# ^C
[root@localhost bin]# ps -ef|grep redis|grep -v grep
root 2129 1 0 14:43 ? 00:00:11 redis-server 0.0.0.0:6379
[root@localhost bin]#
第八步:连接服务
redis-cli -a 123456 -p 6379
[root@localhost bin]# redis-cli -a 123456 -p 6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379>
第九步:测试 ping 命令
127.0.0.1:6379> ping
PONG
Redis-cli命令
quit:退出客户端连接
[root@localhost bin]# redis-cli -a 123456 -p 6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> quit
[root@localhost bin]#
shutdown:关闭 Redis 服务。
[root@localhost bin]# redis-cli -a 123456 -p 6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> shutdown
not connected>
删除 redis
rm -rf /usr/local/bin/redis-*
4:Redis——十大数据类型
https://redis.io/docs/data-types/
常见:String
、List
、Hash
、set
、Zset
高级:Geo
(经纬度)、HyperLogLog
(基数统计)、bitmap
(位图)、bitfield
(位域)、Stream
(流)
11 redis数据类型
12 命令查阅
Redis中文文档 中文命令 https://www.redis.com.cn/commands.html | 官网命令 https://redis.io/commands/ |
13 key常用命令介绍
https://redis.io/commands/?group=generic
这里说的数据类型是value的数据类型,key的类型都是字符串
拷贝key
copy
删除key
del key...
序列化key
dump key
存在key
EXISTS key...
给key一个过期时间
EXPIRE key seconds [NX | XX | GT | LT]
给key一个unix时间
EXPIREAT key unix-time-seconds [NX | XX | GT | LT]
以秒为单位返回unix时间戳
EXPIRETIME key
返回所有匹配的key,*name*,a??,*
KEYS pattern
迁移key,从一个redis实例迁移到另一个redis实例
MIGRATE
将一个key移动到其他的库
MOVE key db
返回key的internal encoding(内部编码)
OBJECT ENCODING key
返回 the logarithmic access frequency counter (对数访问频率计数器)
OBJECT FREQ key
返回上次访问到现在的时间
OBJECT IDLETIME key
返回 reference count (引用计数)
OBJECT REFCOUNT key
删除过期时间变为永久key
PERSIST key
同EXPIRE毫秒为单位
PEXPIRE key milliseconds [NX | XX | GT | LT]
keys * //查询全部
EXISTS key // 是否存在
type key //类型
del key //删除指定的key数据
unlike key //非阻塞删除,仅仅将keys从keyspace元数据中删除,真正的删除会在后续异步中操作
ttl key // 查看还有多少秒过期,-1表示永不过期,-2表示已过期
expire key //秒钟 为给定的key设置过期时间
move key 0-15 //将当前数据库的key移动到给定的数据库db当中select 0-15 //切换数据库[0-15],默认为0
dbsize //查看当前数据库key的数量
flushdb //清空当前库
flushall //通杀全部库
14 类型大小写和帮助命令
Tips:命令不区分大小写,key 区分大小写。
help @类型
,查看内部手册,截图待补充。
15 String 命令(上)
https://redis.io/docs/data-types/strings/
https://redis.io/commands/?group=string
set k1 v1 nx
set k1 v1 xx //覆盖
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> set k1 vnx nx
(nil)
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> set k1 vxx xx
OK
127.0.0.1:6379> get k1
"vxx"
127.0.0.1:6379>
set k1 v1 get //返回旧的
127.0.0.1:6379> set k1 v1 get
"vxx"
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379>
set k1 v1 ex 10
set k1 v1 px 8000
set k1 v1 exat + unix时间戳
set k1 v1 pxat + unix时间戳
//续接上一次过期时间,默认会覆盖,keepttl只替换值。
set k1 v1 keepttl
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> set k1 v1 ex 30
OK
127.0.0.1:6379> ttl k1
(integer) 27
127.0.0.1:6379> set k1 v1keepttl keepttl
OK
127.0.0.1:6379> ttl k1
(integer) 8
127.0.0.1:6379> ttl k1
(integer) 2
127.0.0.1:6379> ttl k1
(integer) -2
127.0.0.1:6379> ttl k1
(integer) -2
127.0.0.1:6379>
16 String 命令(下)
同时设置多个 kv
mset k1 v1 k2 v2 ...
msetnx k1 v1 k4 v4 //类似于事务全部成功或者失败
获取指定范围值
getrange k1 0 3
setrange k1 1 xxyy
127.0.0.1:6379> set k1 abcdefg
OK
127.0.0.1:6379> get k1
"abcdefg"
127.0.0.1:6379> getrange k1 0 3
"abcd"
127.0.0.1:6379> getrange k1 0 -3
"abcde"
127.0.0.1:6379> setrange k1 1 xzy
(integer) 7
127.0.0.1:6379> get k1
"axzyefg"
127.0.0.1:6379>
数值增减
incr k1
incrby k1 3
decr k1
decrby k1 3
127.0.0.1:6379> get k1
"axzyefg"
127.0.0.1:6379> set k1 100
OK
127.0.0.1:6379> get k1
"100"
127.0.0.1:6379> incr k1
(integer) 101
127.0.0.1:6379> set k1 a
OK
127.0.0.1:6379> incr k1
(error) ERR value is not an integer or out of range
获取字符串长度和内容追加
strlen k1
append k1 xxx
127.0.0.1:6379> set k1 a
OK
127.0.0.1:6379> strlen k1
(integer) 1
127.0.0.1:6379> append k1 xxx
(integer) 4
127.0.0.1:6379> get k1
"axxx"
分布式锁
setex k1 10 v1 //原子设置
127.0.0.1:6379> setex k1 10 v1
OK
127.0.0.1:6379> ttl k1
(integer) 4
127.0.0.1:6379>
获取并设置
下面2个一样!!!
getset k1 v1 //相当于
set k1 v1 get //返回旧的
17 List
https://redis.io/docs/data-types/lists/
https://redis.io/commands/?group=list
面试题:Redis list 可以存放的最大长度是多少?
Tips:The max length of a Redis list is 2^32 - 1 (4,294,967,295) elements.
数据结构:双向链表
l = left 左 , r = right 右
队列:Treat a list like a queue (first in, first out): 左边进,右边出,先进先出。
127.0.0.1:6379> lpush list1 1 2 3 4 5
(integer) 5
127.0.0.1:6379> rpush list2 11 22 33 44 55
(integer) 5
127.0.0.1:6379> type list1
list
127.0.0.1:6379> lrange list1 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> lrange list2 0 -1
1) "11"
2) "22"
3) "33"
4) "44"
5) "55"
//从左边进入一个元素101
> LPUSH work:queue:ids 101
(integer) 1
//从左边进入一个元素237
> LPUSH work:queue:ids 237
(integer) 2
//从右边删除元素101
> RPOP work:queue:ids
"101"
//从右边删除第二个元素237
> RPOP work:queue:ids
"237"
栈:Treat a list like a stack (first in, last out): 左边进,左边出,先进后出。
//左边进101
> LPUSH work:queue:ids 101
(integer) 1
//左边进237
> LPUSH work:queue:ids 237
(integer) 2
//左边出237
> LPOP work:queue:ids
"237"
//左边出237
> LPOP work:queue:ids
"101"
Check the length of a list 检查列表的长度
LLEN work:queue:ids
127.0.0.1:6379> lrem list1 1 3
(integer) 1
127.0.0.1:6379> lrange list1 0 -1
1) "5"
2) "4"
3) "2"
4) "1"
127.0.0.1:6379> ltrim list1 1 3
OK
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "2"
3) "1"
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "2"
3) "1"
127.0.0.1:6379> lset list1 1 redis
OK
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "redis"
3) "1"
127.0.0.1:6379>
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "redis"
3) "1"
127.0.0.1:6379> linsert list1 before redis java
(integer) 4
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "java"
3) "redis"
4) "1"
127.0.0.1:6379>
18 hash
https://redis.io/docs/data-types/hashes/
https://redis.io/commands/?group=hash
HSET、HGET、HGETALL
127.0.0.1:6379> HSET user:123 username martina firstName Martina lastName Elisa country GB
(integer) 4
127.0.0.1:6379> HGET user:123 username
"martina"
127.0.0.1:6379> HGETALL user:123
1) "username"
2) "martina"
3) "firstName"
4) "Martina"
5) "lastName"
6) "Elisa"
7) "country"
8) "GB"
带m的是指一次性多个批处理
127.0.0.1:6379> hlen user:123
(integer) 4
127.0.0.1:6379> hlen user:123
(integer) 4
127.0.0.1:6379> HEXISTS user:123 name
(integer) 0
127.0.0.1:6379> HEXISTS user:123 lastname
(integer) 0
127.0.0.1:6379> HEXISTS user:123 lastName
(integer) 1
127.0.0.1:6379> HKEYS user:123
1) "username"
2) "firstName"
3) "lastName"
4) "country"
127.0.0.1:6379> HVals user:123
1) "martina"
2) "Martina"
3) "Elisa"
4) "GB"
127.0.0.1:6379> hset user:123 age 11
(integer) 1
127.0.0.1:6379> HKEYS user:123
1) "username"
2) "firstName"
3) "lastName"
4) "country"
5) "age"
127.0.0.1:6379> Hincrby user:123 age 5
(integer) 16
127.0.0.1:6379> hset user:123 score 91.1
(integer) 1
127.0.0.1:6379> hgetall user:123
1) "username"
2) "martina"
3) "firstName"
4) "Martina"
5) "lastName"
6) "Elisa"
7) "country"
8) "GB"
9) "age"
10) "16"
11) "score"
12) "91.1"
127.0.0.1:6379> hincrbyfloat user:123 score 3.5
"94.6"
hsetnx 不存在赋值
127.0.0.1:6379> hsetnx hash3 k1 44
(integer) 1
127.0.0.1:6379> hsetnx hash3 k1 55
(integer) 0
127.0.0.1:6379> hget hash3 k1
"44"
19 set
https://redis.io/docs/data-types/sets/
https://redis.io/commands/?group=set
127.0.0.1:6379> keys *
1) "list"
2) "user:123"
3) "list2"
4) "list1"
5) "k2"
6) "hash3"
7) "user:001"
8) "k3"
127.0.0.1:6379> sadd set1 111 222 3 4 5 6
(integer) 6
127.0.0.1:6379> sadd set1 3 4 5 6
(integer) 0
127.0.0.1:6379> sismember set1 x
(integer) 0
127.0.0.1:6379> sismember set1 111
(integer) 1
127.0.0.1:6379> srem set1 y
(integer) 0
127.0.0.1:6379> srem set1 111
(integer) 1
127.0.0.1:6379> smembers set1
1) "3"
2) "4"
3) "5"
4) "6"
5) "222"
127.0.0.1:6379> scard set1
(integer) 5
127.0.0.1:6379> srandmember set1 2
1) "5"
2) "6"
127.0.0.1:6379> srandmember set1 2
1) "4"
2) "222"
127.0.0.1:6379> smembers set1
1) "3"
2) "4"
3) "5"
4) "6"
5) "222"
127.0.0.1:6379> spop set1 2
1) "4"
2) "5"
127.0.0.1:6379> smembers set1
1) "3"
2) "6"
3) "222"
127.0.0.1:6379> sadd set2 a b c
(integer) 3
127.0.0.1:6379> smove set1 set2 222
(integer) 1
127.0.0.1:6379> smembers set1
1) "3"
2) "6"
127.0.0.1:6379> smembers set2
1) "a"
2) "b"
3) "c"
4) "222"
127.0.0.1:6379> del set1
(integer) 1
127.0.0.1:6379> del set2
(integer) 1
127.0.0.1:6379> sadd set1 a b c 1 2
(integer) 5
127.0.0.1:6379> sadd set2 1 2 3 a x
(integer) 5
127.0.0.1:6379> sdiff set1 set2
1) "b"
2) "c"
127.0.0.1:6379> sdiff set2 set1
1) "3"
2) "x"
127.0.0.1:6379> sunion set1 set2
1) "a"
2) "b"
3) "c"
4) "1"
5) "2"
6) "3"
7) "x"
127.0.0.1:6379> sinter set1 set2
1) "a"
2) "1"
3) "2"
它不返回结果集,而只返回结果的基数。返回由所有给定集合的交集产生的集合的基数
127.0.0.1:6379> sintercard 2 set1 set2
(integer) 3
-
微信抽奖小程序园
-
微信朋友圈点赞查看同赞朋友
-
内推可能认识的人
20 zset(sorted set)
https://redis.io/docs/data-types/#sorted-sets
https://redis.io/commands/?group=sorted-set
set和zset的关系——无序和有序
相当于业务补充和业务扩展
在set基础上,每个val值前加一个score分 数值。
之前set是k1 v1 v2 v3,现在zset是k1 score1 v1 score2 v2
127.0.0.1:6379> keys *
1) "list1"
127.0.0.1:6379> zadd zset1 60 v1 70 v2 80 v3 90 v4 100 v5
(integer) 5
127.0.0.1:6379> zrange zset1 0 -1
1) "v1"
2) "v2"
3) "v3"
4) "v4"
5) "v5"
127.0.0.1:6379> zrange zset1 0 -1 withscores
1) "v1"
2) "60"
3) "v2"
4) "70"
5) "v3"
6) "80"
7) "v4"
8) "90"
9) "v5"
10) "100"
127.0.0.1:6379> zrevrange zset1 0 -1
1) "v5"
2) "v4"
3) "v3"
4) "v2"
5) "v1"
127.0.0.1:6379> zrevrange zset1 0 -1 withscores
1) "v5"
2) "100"
3) "v4"
4) "90"
5) "v3"
6) "80"
7) "v2"
8) "70"
9) "v1"
10) "60"
127.0.0.1:6379> zrangebyscore zset1 60 90
1) "v1"
2) "v2"
3) "v3"
4) "v4"
127.0.0.1:6379> zrangebyscore zset1 60 90 withscores
1) "v1"
2) "60"
3) "v2"
4) "70"
5) "v3"
6) "80"
7) "v4"
8) "90"
127.0.0.1:6379> zrem zset1 v5
(integer) 1
127.0.0.1:6379> zrem zset1 v5
(integer) 0
127.0.0.1:6379> zrange zset1 0 -1
1) "v1"
2) "v2"
3) "v3"
4) "v4"
127.0.0.1:6379> zcount zset1 60 100
(integer) 4
127.0.0.1:6379> zcount zset1 62 70
(integer) 1
127.0.0.1:6379> zmpop 1 zset1 min count 1
1) "zset1"
2) 1) 1) "v1"
2) "60"
127.0.0.1:6379> zrange zset1 0 -1
1) "v2"
2) "v3"
3) "v4"
127.0.0.1:6379> zmpop 1 zset1 max count 1
1) "zset1"
2) 1) 1) "v4"
2) "90"
127.0.0.1:6379> zrange zset1 0 -1
1) "v2"
2) "v3"
127.0.0.1:6379> zrank zset1 v2
(integer) 0
127.0.0.1:6379> zrevrank zset1 v2
(integer) 1
21 bitmap
由0和1状态表现的二进制位的bit数组
https://redis.io/docs/data-types/bitmaps/
https://redis.io/commands/?group=bitmap
Redis bitmaps are an extension of the string data type that lets you treat a string like a bit vector.
bitmaps 是 string 数据类型的扩展,使你像对待 bit 向量一样对待字符串。
You can also perform bitwise operations on one or more strings.
你可以对一个或者多个字符串执行按位操作。
是什么:每一位记录0或者1的bit数组(位数组)。
有什么用:记录是与否的需求,例如:统计用户的考勤或者签到的需求。
- 用户是否登陆过Y、N,比如京东每日签到送京豆
- 电影、广告是否被点击播放过
- 钉钉打卡上下班,签到统计
说明:用String 类型作为底层数据结构实现的一种统计二值状态的数据类型
位图本质是数组,它是基于String数据类型的按位的操作。该数组由多个二进制位组成,每个二进制位都对应一 个偏移量(我们称之为一个索引)。
Bitmap支持的最大位数是 2 32 2^{32} 232 位,它可以极大的节约存储空间,使用512M内存就可以存储多达42.9亿的字节信息( 2 32 = 4294967296 2^{32}= 4294967296 232=4294967296 )
包含命令:
27.0.0.1:6379> setbit bitk1 0 1
(integer) 0
127.0.0.1:6379> getbit bitk1 0
(integer) 1
127.0.0.1:6379> strlen bitk1
(integer) 1
127.0.0.1:6379> setbit bitk1 7 1
(integer) 0
127.0.0.1:6379> strlen bitk1
(integer) 1
127.0.0.1:6379> setbit bitk1 8 0
(integer) 0
127.0.0.1:6379> strlen bitk1
(integer) 2
127.0.0.1:6379> setbit bitk1 80 0
(integer) 0
127.0.0.1:6379> strlen bitk1
(integer) 11
127.0.0.1:6379> bitcount bitk1
(integer) 2
BITCOUNT :Starting with Redis version 7.0.0: Added the BYTE|BIT option.
22 hyperloglog
https://redis.io/docs/data-types/hyperloglogs/
https://redis.io/commands/?group=hyperloglog
统计某个网站的UV、统计某个文章的UV
什么是UV?
- Unique Visitor,独立访客,一般理解为客户端IP
- 需要去重考虑
用户搜索网站关键词的数量
统计用户每天搜索不同词条个数
用精确度换空间的思想
最大使用12KB的内存可以统计 2 64 2^{64} 264 次个基数(不重复的数)误差率 0.81 % 0.81\% 0.81%。
适用场景:统计 uv,去重后的真实个数。
特点:非精确数据结构,
PFADD
redis> PFADD hll a b c d e f g
(integer) 1
redis> PFCOUNT hll
(integer) 7
redis>
PFCOUNT
PFCOUNT key [key ...]
redis> PFADD hll foo bar zap
(integer) 1
redis> PFADD hll zap zap zap
(integer) 0
redis> PFADD hll foo bar
(integer) 0
redis> PFCOUNT hll
(integer) 3
redis> PFADD some-other-hll 1 2 3
(integer) 1
redis> PFCOUNT hll some-other-hll
(integer) 6
redis>
PFMERGE
PFMERGE destkey [sourcekey [sourcekey ...]]
redis> PFADD hll1 foo bar zap a
(integer) 1
redis> PFADD hll2 a b c foo
(integer) 1
redis> PFMERGE hll3 hll1 hll2
"OK"
redis> PFCOUNT hll3
(integer) 6
23 geo 地理坐标
https://redis.io/docs/data-types/geospatial/
https://redis.io/commands/?group=geo
移动互联网时代LBS应用越来越多,交友软件中附近的小姐姐、外卖软件中附近的美食店铺、高德地图附近的核酸检查点等等,那这种附近各种形形色色的XXX地址位置选择是如何实现的?
地球上的地理位置是使用二维的经纬度表示,经度范围 ( − 180 , 180 ] (-180, 180] (−180,180],纬度范围 ( − 90 , 90 ] (-90, 90] (−90,90],只要我们确定一个点的经纬度就可以名取得他在地球的位置。
例如滴滴打车,最直观的操作就是实时记录更新各个车的位置,然后当我们要找车时,在数据库中查找距离我们坐标 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)附近r公里范围内部的车辆
使用如下SQL即可:
但是这样会有什么问题呢?
- 查询性能问题,如果并发高,数据量大这种查询是要搞垮数据库的
- 这个查询的是一个矩形访问,而不是以我为中心r公里为半径的圆形访问。
- 精准度的问题,我们知道地球不是平面坐标系,而是一个圆球,这种矩形计算在长距离计算时会有很大误差
24 25 26 stream
https://redis.io/commands/?group=stream
https://redis.io/docs/data-types/streams/
redis 版本的 MQ
Redis 消息队列的方案:
- List:点对点,不支持一对多。
- Pub / Sub:无法持久化
List实现消息队列
按照插入顺序排序,你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
所以常用来做异步队列使用,将需要延后处理的任务结构体序列化成字符串塞进Redis的列表,另一个线程从这个列表中轮询数据进行处理。
Pub / Sub:无法持久化
Redis发布订阅(pub/sub)有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。而且也没有Ack机制来保证数据的可靠性,假设一个消费者都没有,那消息就直接被丢弃了。
Redis5.0版本新增了一个更强大的数据结构-----Stream
Stream——Redis版的MQ消息中间件+阻塞队列
实现消息队列,它支持消息的持久化、支持自动生成全局唯一ID、 支持ack确认消息的模式、支持消费组模式等,让消息队列更加的稳定和可靠
底层原理和结构:
指令名称 | 指令作用 |
---|---|
XADD | 添加消息到队列末尾 |
XTRIM | 限制Stream的长度,如果已经超长会进行截取 |
XDEL | 删除消息 |
XLEN | 获取Stream中的消息长度 |
XRANGE | 获取消息列表(可以指定范围),忽略删除的消息 |
XREVRANGE | 和XRANGE相比区别在于反向获取,ID从大到小 |
XREAD | 获取消息(阻塞/非阻塞),返回大于指定ID的消息 |
四个特殊符号
127.0.0.1:6379> xadd mystream * id 11 cname z3
"1705993155303-0"
127.0.0.1:6379> xadd mystream * id 12 cname l4
"1705993164804-0"
127.0.0.1:6379> xadd mystream * id 13 cname w5
"1705993175046-0"
127.0.0.1:6379> xadd mystream * k1 v1 k2 v2
"1705993188853-0"
127.0.0.1:6379> type mystream
stream
127.0.0.1:6379> xrange mystram - +
(empty array)
127.0.0.1:6379> xrange mystream - +
1) 1) "1705993155303-0"
2) 1) "id"
2) "11"
3) "cname"
4) "z3"
2) 1) "1705993164804-0"
2) 1) "id"
2) "12"
3) "cname"
4) "l4"
3) 1) "1705993175046-0"
2) 1) "id"
2) "13"
3) "cname"
4) "w5"
4) 1) "1705993188853-0"
2) 1) "k1"
2) "v1"
3) "k2"
4) "v2"
127.0.0.1:6379> xrange mystream - + count 1
1) 1) "1705993155303-0"
2) 1) "id"
2) "11"
3) "cname"
4) "z3"
127.0.0.1:6379> xrevrange mystream + -
1) 1) "1705993188853-0"
2) 1) "k1"
2) "v1"
3) "k2"
4) "v2"
2) 1) "1705993175046-0"
2) 1) "id"
2) "13"
3) "cname"
4) "w5"
3) 1) "1705993164804-0"
2) 1) "id"
2) "12"
3) "cname"
4) "l4"
4) 1) "1705993155303-0"
2) 1) "id"
2) "11"
3) "cname"
4) "z3"
127.0.0.1:6379> xdel mystream 1705993155303-0
(integer) 1
127.0.0.1:6379> xrange mystream - +
1) 1) "1705993164804-0"
2) 1) "id"
2) "12"
3) "cname"
4) "l4"
2) 1) "1705993175046-0"
2) 1) "id"
2) "13"
3) "cname"
4) "w5"
3) 1) "1705993188853-0"
2) 1) "k1"
2) "v1"
3) "k2"
4) "v2"
127.0.0.1:6379> xlen mystream
(integer) 3
127.0.0.1:6379> xtrim mystream maxlen 2
(integer) 1
127.0.0.1:6379> xrange mystream - +
1) 1) "1705993175046-0"
2) 1) "id"
2) "13"
3) "cname"
4) "w5"
2) 1) "1705993188853-0"
2) 1) "k1"
2) "v1"
3) "k2"
4) "v2"
127.0.0.1:6379> xtrim mystream minid 1705993175046-0
(integer) 0
127.0.0.1:6379> xtrim mystream minid 1705993175047-0
(integer) 1
127.0.0.1:6379> xrange mystream - +
1) 1) "1705993188853-0"
2) 1) "k1"
2) "v1"
3) "k2"
4) "v2"
127.0.0.1:6379>
27 bitfield——了解即可
https://redis.io/docs/data-types/bitfields/
ascii 字节码对照表:https://ascii.org.cn/
溢出控制
BITFIELD命令可以将一个Redis字符串看作是一个由二进制位组成的数组,并对这个数组中任意偏移进行访问。可以使用该命令对一个有符号的5位整型数的第1234位设置指定值,也可以对一个31位无符号整型数的第4567位进行取值。类似地,本命令可以对指定的整数进行自增和自减操作,可配置的上溢和下溢处理操作。
BITFIELD命令可以在一次调用中同时对多个位范围进行操作:它接受一系列待执行的操作作为参数,并返回一个数组,数组中的每个元素就是对应操作的执行结果。
例如,对位于5位有符号整数的偏移量100执行自增操作,并获取位于偏移量0上的4位长无符号整数:
BITFIELD命令的作用在于它能够将很多小的整数储存到一个长度较大的位图中,又或者将一个非常庞大的键分割为多个较小的键来进行储存,从而非常高效地使用内存,使得Redis能够得到更多不同的应用一特别是在实时分析领域:
BITFIELD能够以指定的方式对计算溢出进行控制的能力,使得它可以被应用于这一领域。
hello 等价于 0110100001100101011011000110110001101111
- 位域修改
- 溢出控制
下面是已支持的命令列表:
●GET <type> <offset> -返回指定的位域
●SET <type> <offset> <va1ue> -设置指定位域的值并返回它的原值
●INCRBY <type> <offset> <increment> -自增或自减(如果increment为负数)指定位域的值并返回它的新值
当需要一个整型时, 有符号整型需在位数前加i
,无符号在位数前加u
。例如,u8
是一个8
位的无符号整型, i16
是一个16
位的有符号整型。
BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]
127.0.0.1:6379> set fieldkey hello
OK
127.0.0.1:6379> get fieldkey
"hello"
127.0.0.1:6379> bitfield fieldkey get i8 0
1) (integer) 104
127.0.0.1:6379> bitfield fieldkey get i8 8
1) (integer) 101
127.0.0.1:6379> bitfield fieldkey get i8 8
1) (integer) 101
127.0.0.1:6379> bitfield fieldkey set i8 8 120
1) (integer) 101
127.0.0.1:6379> bitfield fieldkey get i8 8
1) (integer) 120
127.0.0.1:6379> get fieldkey
"hxllo"
溢出控制OVERFLOW [WRAP|SAT|FAIL]
- WRAP:使用回绕(yrap around)方法处理有符号整数和无符号整数的溢出情况(默认)
- SAT:使用饱和计算(saturation arithmetic)方法处理溢出,下溢计算的结果为最小的整数值,而上溢计算的结果为最大的整数值
- FAIL:命令将拒绝执行那些会导致上溢或者下溢情况出现的计算,并向用户返回空值表示计算未被执行
127.0.0.1:6379> bitfield fieldkey incrby u4 2 1
1) (integer) 11
127.0.0.1:6379> bitfield fieldkey incrby u4 2 1
1) (integer) 12
127.0.0.1:6379> bitfield fieldkey incrby u4 2 1
1) (integer) 13
127.0.0.1:6379> bitfield fieldkey incrby u4 2 1
1) (integer) 14
127.0.0.1:6379> bitfield fieldkey incrby u4 2 1
1) (integer) 15
127.0.0.1:6379> bitfield fieldkey incrby u4 2 1
1) (integer) 0
127.0.0.1:6379> bitfield fieldkey incrby u4 2 1
1) (integer) 1
127.0.0.1:6379> bitfield fieldkey incrby u4 2 1
1) (integer) 2
127.0.0.1:6379> get fieldkey
"Hxllo"
127.0.0.1:6379> bitfield fieldkey incrby u4 2 1
1) (integer) 3
127.0.0.1:6379> bitfield fieldkey incrby u4 2 1
1) (integer) 4
127.0.0.1:6379> get fieldkey
"Pxllo"
127.0.0.1:6379>