NoSQL学习之Redis(三)

120 阅读9分钟

这是我参与「掘金日新计划 · 2 月更文挑战」的第 九 天

八、三种特殊数据类型

8.1、geospatial 地理位置

Redis的Geo可以推算地理位置的信息

只有6个命令:

  • geoadd:添加地理位置的坐标。
  • geopos:获取地理位置的坐标。
  • geodist:计算两个位置之间的距离。
  • georadius:根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。
  • georadiusbymember:根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合。
  • geohash:返回一个或多个位置对象的 geohash 值。

geoadd 用于存储指定的地理空间位置,可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中。

geoadd 语法格式如下:

GEOADD key  latitude longitude member [latitude longitude member ...]

geoadd:添加地理位置的坐标。

127.0.0.1:6379> GEOADD china:city 116.40 39.90 beijing
(integer) 1
127.0.0.1:6379> GEOADD china:city 121.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> GEOADD china:city 113.28 23.12 guangzhou
(integer) 1
127.0.0.1:6379> GEOADD china:city 113.66 34.75 henan
(integer) 1

geopos:获取地理位置的坐标。

127.0.0.1:6379> GEOPOS china:city beijing  # 获取指定城市的精度和纬度
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"
127.0.0.1:6379> GEOPOS china:city henan
1) 1) "113.65999907255172729"
   2) "34.74999926510690784"
127.0.0.1:6379>

geodist:计算两个位置之间的距离。

geodist 用于返回两个给定位置之间的距离。

geodist 语法格式如下:

GEODIST key member1 member2 [m|km|ft|mi]

member1 member2 为两个地理位置。

最后一个距离单位参数说明:

  • m :米,默认单位。
  • km :千米。
  • mi :英里。
  • ft :英尺。
127.0.0.1:6379> GEODIST china:city beijing henan km # 查看北京到河南的距离
"621.8822"
127.0.0.1:6379> GEODIST china:city beijing shanghai km # 查看北京到上海的距离
"1067.3788"
127.0.0.1:6379> 

georadius、georadiusbymember

  • georadius 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
  • georadiusbymember 和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 georadiusbymember 的中心点是由给定的位置元素决定的, 而不是使用经度和纬度来决定中心点。
  • georadius 与 georadiusbymember 语法格式如下:
  • GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
    GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
    
  • 参数说明:
    • m :米,默认单位。
    • km :千米。
    • mi :英里。
    • ft :英尺。
    • WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。
    • WITHCOORD: 将位置元素的经度和纬度也一并返回。
    • WITHHASH: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。
    • COUNT 限定返回的记录数。
    • ASC: 查找结果根据距离从近到远排序。
    • DESC: 查找结果根据从远到近排序
127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km # 以110,30这个经纬度为中心,寻找方圆1000KM你的城市
1) "guangzhou"
2) "henan"
127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km withdist # 显示到中心距离的位置
1) 1) "guangzhou"
   2) "831.7713"
2) 1) "henan"
   2) "630.2160"
127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km withcoord # 显示他人的定位信息
1) 1) "guangzhou"
   2) 1) "113.27999979257583618"
      2) "23.1199990030198208"
2) 1) "henan"
   2) 1) "113.65999907255172729"
      2) "34.74999926510690784"
127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km withdist withcoord count 1 # 筛选出指定的结果 
1) 1) "henan"
   2) "630.2160"
   3) 1) "113.65999907255172729"
      2) "34.74999926510690784" 
# 找出位于指定元素周围的其他元素
127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km 
1) "henan" 
2) "beijing"
127.0.0.1:6379> GEORADIUSBYMEMBER china:city shanghai 1000 km 
1) "shanghai"
2) "henan"

8.2、Hyperloglog

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

什么是基数?

比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。

下表列出了 redis HyperLogLog 的基本命令:

序号命令及描述
1PFADD key element [element ...] 添加指定元素到 HyperLogLog 中。
2PFCOUNT key [key ...] 返回给定 HyperLogLog 的基数估算值。
3PFMERGE destkey sourcekey [sourcekey ...] 将多个 HyperLogLog 合并为一个 HyperLogLog
127.0.0.1:6379> PFADD runoobkey "redis" "mongodb" "mysql" # 创建第一组元素
(integer) 1
127.0.0.1:6379> PFCOUNT runoobkey # 统计runoobkey 元素的基数数量
(integer) 3
127.0.0.1:6379> PFADD myset "redis" "mysql" "java" # 创建第二组 myset
(integer) 1 
127.0.0.1:6379> PFMERGE mykey myset runoobkey # 合并两组
OK
127.0.0.1:6379> PFCOUNT mykey
(integer) 4

8.3、Bitmaps

使用bitmaps来记录一周的打卡

查看某天是否打卡

127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 1 0
(integer) 0
127.0.0.1:6379> setbit sign 2 0
(integer) 0
127.0.0.1:6379> setbit sign 3 1
(integer) 0
127.0.0.1:6379> setbit sign 4 1
(integer) 0
127.0.0.1:6379> setbit sign 5 0
(integer) 0
127.0.0.1:6379> setbit sign 6 0
(integer) 0
127.0.0.1:6379> getbit sign 3
(integer) 1
127.0.0.1:6379> getbit sign 6
(integer) 0

统计操作,统计打卡的天数

127.0.0.1:6379> bitcount sign  # 统计这周打卡的天数
(integer) 3

九、事务

Redis事务本质:一组命令的集合,一个事务中的所有命令都会被序列化,在食物执行过程中,会按照顺序执行!

一次性、顺序性、排他性!

一个事务从开始到执行会经历以下三个阶段:

  • 开始事务。(MULTI)
  • 命令入队。
  • 执行事务。(EXEC)

Redis事务没有隔离级别的概念

Redis单条命令保证原子性,但事务不保证原子性

Redis 事务命令

下表列出了 redis 事务的相关命令:

序号命令及描述
1DISCARD 取消事务,放弃执行事务块内的所有命令。
2EXEC 执行所有事务块内的命令。
3MULTI 标记一个事务块的开始。
4UNWATCH 取消 WATCH 命令对所有 key 的监视。
5WATCH key [key ...] 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
127.0.0.1:6379> MULTI  # 开启事务
OK
# 命令入队
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> get k2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> EXEC # 执行事务
1) OK
2) OK
3) "v2"
4) OK

放弃事务

127.0.0.1:6379>  MULTI # 开启事务
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> DISCARD #放弃事务
OK
127.0.0.1:6379> get k4 # 事务中的所有命令都不会被执行
(nil)

编译型异常(代码有问题,命令有错)事务中所有的命令都不会被执行

127.0.0.1:6379> MULTI 
OK
127.0.0.1:6379(TX)> set k1 v1 
QUEUED
127.0.0.1:6379(TX)> set k2 v2 
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> getset k3
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> EXEC # 执行事务报错
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k4 # 所有命令都不会被执行
(nil)

运行时异常!如果事务队列中存在与发行错误,那么执行命令的时候,其他命令可以执行,错误命令抛出异常

127.0.0.1:6379> set k1 "hello"
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> INCR k1
QUEUED
127.0.0.1:6379(TX)> set k2 v2 
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> get k3
QUEUED
127.0.0.1:6379(TX)> EXEC
1) (error) ERR value is not an integer or out of range
2) OK
3) OK
4) "v3"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379> get k3
"v3"

监控!

# Redis监控测试
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money # 监视 money 对象
OK
127.0.0.1:6379> MULTI  # 事务正常结束,数据期间米有发生变动就正常执行成功
OK
127.0.0.1:6379(TX)> DECRBY money 20
QUEUED
127.0.0.1:6379(TX)> INCRBY out 20
QUEUED
127.0.0.1:6379(TX)> EXEC
1) (integer) 80
2) (integer) 20

十、Redis配置文件详解

网络

bind 127.0.0.1 -::1         # 绑定的IP
protected-mode yes          # 保护模式
port 6379                   # 默认端口号

通用GENERAL

daemonize yes                       # 以守护进程的方式运行,默认是no,我们需要修改为yes
pidfile /var/run/redis_6379.pid     # 如果以后台方式运行,我们就需要指定一个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
logfile "" # 日志的文件位置名
databases 16 # 数据库的数量,默认16个数据库
always-show-logo no     # 是否总显示LOGO

快照

持久化,在规定的时间内,执行了多少次操作,则会持久化到文件 .rdb .aof

redis 是内存数据库,如果没有持久化,那么数据断电即失!

# 如果3600秒内,如果至少有一个key进行了修改,我们就会进行持久化操作
save 3600 1
# 如果300秒内,如果至少有100个key进行了修改,我们就会进行持久化操作
save 300 100
# 如果60秒内,如果至少有10000个key进行了修改,我们就会进行持久化操作
save 60 10000
# 我们后续会定义自己的测试
​
stop-writes-on-bgsave-error yes     # 持久化如果出错,是否继续工作
​
rdbcompression yes                  # 是否压缩rdb文件,需要消耗一些CPU的资源
​
rdbchecksum yes                     # 保存rdb文件的时候,进行错误的检查校验dir ./                              # rdb文件保存的目录

SECURITY 安全

设置密码

127.0.0.1:6379> CONFIG GET requirepass      #获取redis的密码
1) "requirepass"
2) ""
127.0.0.1:6379> CONFIG SET requirepass "zjch1328"   # 设置redis的密码
OK
127.0.0.1:6379> CONFIG GET requirepass
1) "requirepass"
2) "zjch1328"
127.0.0.1:6379> CONFIG GET requirepass
(error) NOAUTH Authentication required.
127.0.0.1:6379> AUTH zjch1328       # 使用密码进行登录
OK

CLIENTS 客户端

maxclients 10000        # 设置能连接上redis的最大客户端的数量
maxmemory <bytes>       # redis 配置最大的内存容量
maxmemory-policy noeviction     # 内存到达上限之后的处理策略
1volatile-lru:只对设置了过期时间的key进行LRU(默认值) 
2、allkeys-lru : 删除lru算法的key   
3volatile-random:随机删除即将过期key   
4、allkeys-random:随机删除   
5volatile-ttl : 删除即将过期的   
6、noeviction : 永不过期,返回错误

APPEND ONLY aof模式

appendonly no       # 默认是不开启aof模式的
appendfilename "appendonly.aof"     # 持久化的文件的名字# appendfsync always    # 每次修改都会写入 sync
appendfsync everysec    # 美妙执行一次 sync,可能会丢失着一秒的数据
# appendfsync no        # 不执行 sync,这个时候操作系统自己同步数据,速度最快

10.2、网络相关的配置

  • bind 默认情况 bind=127.0.0.1 只能接受本机的访问请求 注释掉bind=127.0.0.1
  • 不写的情况下,无限制接受任何IP地址访问,生产环境肯定要写你的应用服务器的地址;服务器是需要远程访问的,所以要将其注释掉。
  • protected-mode 开启之后,也只能本地链接 把protected-mode no
  • tcp-backlog 设置tcp的backlog,backlog其实是一个链接队列,backlog队列=未完成三次握手的队列+王城三次握手的队列。在高并发下你需要一个高的backlog值来避免慢客户端的问题
  • timeout 设置连接无操作超时时间