Redis学习记录-002

Redis中文链接:http://www.redis.cn/commands/geodist.html

Geospatial地理位置

GEOADD

将指定的地理空间位置(纬度、经度、名称)添加到指定的key中。这些数据将会存储到sorted set这样的目的是为了方便使用GEORADIUS或者GEORADIUSBYMEMBER命令对数据进行半径查询等操作。

该命令以采用标准格式的参数x,y,所以经度必须在纬度之前。这些坐标的限制是可以被编入索引的,区域面积可以很接近极点但是不能索引。具体的限制,由EPSG:900913 / EPSG:3785 / OSGEO:41001 规定如下:

  • 有效的经度从-180度到180度。
  • 有效的纬度从-85.05112878度到85.05112878度。

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

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEODIST Sicily Palermo Catania
"166274.15156960039"
redis> GEORADIUS Sicily 15 37 100 km
1) "Catania"
redis> GEORADIUS Sicily 15 37 200 km
1) "Palermo"
2) "Catania"
redis> 

GEODISK

返回两个给定位置之间的距离。
如果两个位置之间的其中一个不存在, 那么命令返回空值。
指定单位的参数 unit 必须是以下单位的其中一个:
m 表示单位为米。 km 表示单位为千米。 mi 表示单位为英里。 ft 表示单位为英尺。 如果用户没有显式地指定单位参数, 那么 GEODIST 默认使用米作为单位。 GEODIST 命令在计算距离时会假设地球为完美的球形, 在极限情况下, 这一假设最大会造成
0.5% 的误差。
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEODIST Sicily Palermo Catania
"166274.15156960039"
redis> GEODIST Sicily Palermo Catania km
"166.27415156960038"
redis> GEODIST Sicily Palermo Catania mi
"103.31822459492736"
redis> GEODIST Sicily Foo Bar
(nil)
redis> 

GEOHASH

返回一个或多个位置元素的 Geohash 表示。
通常使用表示位置的元素使用不同的技术,使用Geohash位置52点整数编码。由于编码和解码过程中所使用的初始最小和最大坐标不同,编码的编码也不同于标准。此命令返回一个标准的Geohash,在维基百科和geohash.org网站都有相关描述
Geohash字符串属性
该命令将返回11个字符的Geohash字符串,所以没有精度Geohash,损失相比,使用内部52位表示。返回的geohashes具有以下特性:
他们可以缩短从右边的字符。它将失去精度,但仍将指向同一地区。
它可以在 geohash.org 网站使用,网址 http://geohash.org/<geohash-string>。查询例子:http://geohash.org/sqdtr74hyu0.
与类似的前缀字符串是附近,但相反的是不正确的,这是可能的,用不同的前缀字符串附近。
返回值
integer-reply, 具体的:
一个数组, 数组的每个项都是一个 geohash 。 命令返回的 geohash 的位置与用户给定的位置元素的位置一一对应。
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEOHASH Sicily Palermo Catania
1) "sqc8b49rny0"
2) "sqdtr74hyu0"
redis> 

GEOPOS:

从key里返回所有给定位置元素的位置(经度和纬度)。
给定一个sorted set表示的空间索引,密集使用 geoadd 命令,它以获得指定成员的坐标往往是有益的。当空间索引填充通过 geoadd 的坐标转换成一个52位Geohash,所以返回的坐标可能不完全以添加元素的,但小的错误可能会出台。
因为 GEOPOS 命令接受可变数量的位置元素作为输入, 所以即使用户只给定了一个位置元素, 命令也会返回数组回复。
返回值
array-reply, 具体的:
GEOPOS 命令返回一个数组, 数组中的每个项都由两个元素组成: 第一个元素为给定位置元素的经度, 而第二个元素则为给定位置元素的纬度。
当给定的位置元素不存在时, 对应的数组项为空值。
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEOPOS Sicily Palermo Catania NonExisting
1) 1) "13.361389338970184"
   2) "38.115556395496299"
2) 1) "15.087267458438873"
   2) "37.50266842333162"
3) (nil)
redis> 

GEORADIUS:附近的人(使用经纬度坐标查找)

以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
范围可以使用以下其中一个单位:
m 表示单位为米。
km 表示单位为千米。
mi 表示单位为英里。
ft 表示单位为英尺。
在给定以下可选项时, 命令会返回额外的信息:
WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。
WITHCOORD: 将位置元素的经度和维度也一并返回。
WITHHASH: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。
命令默认返回未排序的位置元素。 通过以下两个参数, 用户可以指定被返回位置元素的排序方式:
ASC: 根据中心的位置, 按照从近到远的方式返回位置元素。
DESC: 根据中心的位置, 按照从远到近的方式返回位置元素。
在默认情况下, GEORADIUS 命令会返回所有匹配的位置元素。 虽然用户可以使用 COUNT <count> 选项去获取前 N 个匹配元素, 但是因为命令在内部可能会需要对所有被匹配的元素进行处理, 所以在对一个非常大的区域进行搜索时, 即使只使用 COUNT 选项去获取少量元素, 
命令的执行速度也可能会非常慢。 但是从另一方面来说, 使用 COUNT 选项去减少需要返回的元素数量, 对于减少带宽来说仍然是非常有用的。 返回值 bulk-string-reply, 具体的: 在没有给定任何 WITH 选项的情况下, 命令只会返回一个像 [“New York”,”Milan”,”Paris”] 这样的线性(linear)列表。 在指定了 WITHCOORD 、 WITHDIST 、 WITHHASH 等选项的情况下, 命令返回一个二层嵌套数组, 内层的每个子数组就表示一个元素。 在返回嵌套数组时, 子数组的第一个元素总是位置元素的名字。 至于额外的信息, 则会作为子数组的后续元素, 按照以下顺序被返回: 以浮点数格式返回的中心与位置元素之间的距离, 单位与用户指定范围时的单位一致。 geohash 整数。 由两个元素组成的坐标,分别为经度和纬度。
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEORADIUS Sicily 15 37 200 km WITHDIST
1) 1) "Palermo"
   2) "190.4424"
2) 1) "Catania"
   2) "56.4413"
redis> GEORADIUS Sicily 15 37 200 km WITHCOORD
1) 1) "Palermo"
   2) 1) "13.361389338970184"
      2) "38.115556395496299"
2) 1) "Catania"
   2) 1) "15.087267458438873"
      2) "37.50266842333162"
redis> GEORADIUS Sicily 15 37 200 km WITHDIST WITHCOORD
1) 1) "Palermo"
   2) "190.4424"
   3) 1) "13.361389338970184"
      2) "38.115556395496299"
2) 1) "Catania"
   2) "56.4413"
   3) 1) "15.087267458438873"
      2) "37.50266842333162"
redis> 

GEORADIUSBYMEMBER:附近的人(使用已经添加的位置)

这个命令和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 GEORADIUSBYMEMBER 的中心点是由给定的位置元素决定的, 而不是像 GEORADIUS 那样, 使用输入的经度和纬度来决定中心点
指定成员的位置被用作查询的中心。
redis> GEOADD Sicily 13.583333 37.316667 "Agrigento"
(integer) 1
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEORADIUSBYMEMBER Sicily Agrigento 100 km
1) "Agrigento"
2) "Palermo"
redis>

Hyperloglog基数统计

Bitmap位图场景

Redis基本的事务操作

事务:本质一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行
一次性 顺序性 排他性
redis单条命令是保证原子性的,redis事务是不保证原子性的 redis事务没有隔离级别的概念 所有的命令在事务中,并没有被执行 只有发起执行命令的时候 才会执行exec
事务分为3个阶段
1.开启事务(multi)
2.命令入队(....)
3.执行事务(exec)
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

放弃事务:DISCARD
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 k4 v4 QUEUED 127.0.0.1:6379(TX)> DISCARD OK 127.0.0.1:6379> get k4 #事务中的命令都不会被执行 (nil)

Redis实现乐观锁

监控
悲观锁:认为什么时候都会出问题,无论做什么都加锁
乐观锁:认为什么时候都不会出问题,不会加锁 更新数据时候取判断一下 再次期间是否有人修改过数据,version,获取version,更新的时候比较version

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  //银行卡取出少了20元
QUEUED
127.0.0.1:6379(TX)> INCRBY out 20    //手中余额多了20元
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 80
2) (integer) 20
测试多线程修改值 使用watch 可以当作redis 乐观锁操作

127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 10
QUEUED
127.0.0.1:6379(TX)> INCRBY out 10
QUEUED
127.0.0.1:6379(TX)> exec  #执行之前另外一个线程修改了值 这个时候导致事务执行失败
(nil)

如果发现事务执行失败 先解锁unwatch 再次监视watch 

Redis订阅发布

Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。

Redis 客户端可以订阅任意数量的频道。

下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:

当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:

redis 127.0.0.1:6379> SUBSCRIBE runoobChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1
redis 127.0.0.1:6379> PUBLISH runoobChat "Redis PUBLISH test"
(integer) 1
redis 127.0.0.1:6379> PUBLISH runoobChat "Learn redis by runoob.com"
(integer) 1
# 订阅者的客户端会显示如下消息
 1) "message"
2) "runoobChat"
3) "Redis PUBLISH test"
 1) "message"
2) "runoobChat"
3) "Learn redis by runoob.com"
PSUBSCRIBE:订阅一个或多个符合给定模式的频道。
PUBSUB:查看订阅与发布系统状态
PUBLISH:将信息发送到指定的频道
PUNSUBSCRIBE:退订所有给定模式的频道
SUBSCRIBE:订阅给定的一个或多个频道的信息
UNSEBSCRIBE:退订给定的频道

Redis配置文件

1、配置文件单位大小写不敏感
2、可以引入其他配置文件
3、配置网络
4、pidfile 守护进程的pid设置
5、默认16个数据库
6、快照设置 默认的配置 save 900 1 save 300 10   save 60 10000 #解释 900秒有一个键发生改变,300秒内有10个键发生改变,60秒内有10000个键发生改变 则进行备份
7、持久化出错,是否继续工作 默认开启,继续工作
8、压缩rdb文件,默认开启
9、安全设置,默认没有密码
10、默认10000个客户端
11、内存满了,处理策略进行配置
默认RDB持久化,生成dump.rdb文件,rdb文件在配置文件夹中即可,每次重启则读取rdb的文件进行还原。
AOF(Append Only Aof)默认不开启,当aof备份文件存在语法错误时,可以使用redis-check-aof.exe 进行修复。
在aof文件中保存的内容有自己的固定格式,当文件中存在不符合格式的内容,在启动Redis并且开始还原aof文件时,则无法启动。这时候只需要运行redis-check-aof 就可以进行修复。
redis-check-aof --fix aof文件

Redis集群环境搭建

  测试实验在单机进行,只需要修改配置文件即可,需要注意的是需要修改的有四项

1、port 6379  端口 
2、pid(后台运行守护进程的id)
3、logfile  log文件名称
4、dbfilename dump.rdb  dump.rdb文件名(rdb备份文件)

  Redis在配置之前都是主机,想要搭建集群,就需要进行配置,将Redis配置成从机,临时配置可以使用以下命令

slaveof 主机IP 端口

  可以通过以上命令临时配置多个从机,想要永久生效就需要在配置文件(redis.windows.conf)中进行设置,我这个是在window上进行配置的

        #主机ip    #主机端口
slaveof <masterip> <masterport>
#如果需要密码则进行配置 主机密码
masterauth <master-password>
# 使得Redis服务器可以跨网络访问
bind 0.0.0.0
# 设置密码
requirepass "123456"
# 指定主服务器,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
slaveof 192.168.11.128 6379
# 主服务器密码,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
masterauth 123456

  查看主从及信息命令

127.0.0.1:6379> info replication
# Replication
role:master      #主机
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6379>

  接下来就是主从机发生故障的情况,前提是主机已经设置完毕。举例:A为主机,B、C为从机

主机写,从机读,从机主要用来备份
从机强行进行写操作,就会报错提示
主机A故障发生宕机,B、C从机的主机依然是A
主机A恢复后,从机B、C的数据进行恢复,并且A仍然为主机。有两个从机B、C,就是说我是主机,暂时宕机了,恢复了我依然是主机,该是我的就是我的
主机A已经设置完毕,从机也已经绑定完毕,已经存在数据,添加一个新的从机D,从机D会发送一个Sync同步命令,从而进行全量复制(将绑定前主机A的数据全量进行复制)。绑定完成后,主机A进行写操作时,就会进行增量复制,同步进行备份。

  宕机后手动配置主机,以下命令可以使自己变为主机

slaveof no noe   #通俗解释 部署于任何一个主机 那么我就是主机了

哨兵模式

  哨兵认识

在哨兵模式出来之前,以上主从机设置都是手动的,之后都是自动的,感觉像是手动挡向自动挡的进化。
跟一主多从一样,防止单个哨兵故障宕机,于是哨兵模式也就是多哨兵模式,再加上redis集群,所以哨兵模式加一主多从,起步就是6个进程。
故障切换(failover),加入主服务器宕机,哨兵1先检测,系统不会马上进行failover过程,仅仅哨兵1主观的认为主服务器不可用,这个现象就是主观下线。当后面其他哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵就会进行一次投票,投票的结果由一个哨兵发起,
进行failover操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换,这个过程称为客观下线

我自己总结的图

 

 

 

 

 

 

 

  

  配置哨兵模式

1、修改配置文件(sentinel.conf)  最简单的核心配置
  sentinel  monitor  myredis  IP  端口  1  #1代表主机挂了进行投票选举
2、启动哨兵
  redis-sentinel  kconfig/sentinel.conf
配置哨兵模式之后,当主机宕机,确认进行客观下线后,进行选举,选举新的主机,A主机发生宕机,所有的哨兵都已经检测确认,然后将A主机进行客观下线,选举B作为主机,当A主机恢复后,此时就不再是主机了,也会以B作为主机,从而变成从机,这是跟之前手动设置的不同
# 禁止保护模式
protected-mode no
# 配置监听的主服务器,这里sentinel monitor代表监控,mymaster代表服务器的名称,可以自定义,192.168.11.128代表监控的主服务器,6379代表端口,2代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作。
sentinel monitor mymaster 192.168.11.128 6379 2
# sentinel author-pass定义服务的密码,mymaster是服务名称,123456是Redis服务器密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster 123456

java中使用哨兵模式

/**
 * 测试Redis哨兵模式
 * @author liu
 */
public class TestSentinels {
    @SuppressWarnings("resource")
    @Test
    public void testSentinel() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(10);
        jedisPoolConfig.setMaxIdle(5);
        jedisPoolConfig.setMinIdle(5);
        // 哨兵信息
        Set<String> sentinels = new HashSet<>(Arrays.asList("192.168.11.128:26379",
                "192.168.11.129:26379","192.168.11.130:26379"));
        // 创建连接池
        JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels,jedisPoolConfig,"123456");
        // 获取客户端
        Jedis jedis = pool.getResource();
        // 执行两个命令
        jedis.set("mykey", "myvalue");
        String value = jedis.get("mykey");
        System.out.println(value);
    }
}

哨兵模式的其他配置

缓存穿透、击穿、雪崩

缓存穿透:很多请求请求一个缓存中不存在的数据,大量请求直达数据库,造成崩溃。
缓存击穿:很多请求同时访问同一个热点数据,当这个数据失效时,所有请求涌入数据库,造成奔溃。
缓存雪崩:热点数据同时失效,从而导致所有请求涌入数据库,造成崩溃。

开发中使用redis,进行集成,自己定义一个template,并且进行各种类型的系列化,将底层的方法进行封装,封装成RedisUtil,使调用更加方便。

跟SpringBoot集成是不再直接使用Jedis,而是使用lettue。

jedis和lettue的区别

jedis客户端连接方式是基于tcp的阻塞式连接方式。 支持全面的Redis操作特性,使用阻塞的I/O,且方法调用都是同步的,程序流需要等到socket处理完I/O才能执行,不支持异步,不是线程安全的,需要通过连接池使用Jedis
lettuce客户端连接方式是基于netty的多路复用异步非阻塞的连接方案。  可扩展的线程安全的Redis客户端,支持异步模式,底层基于Netty,支持高级的Redis特性,比如哨兵、集群、管道、自动重新连接
Redisson,额外提供了分布式服务,使用者对Redis进行关注分离,可以类比Spring框架,提供了很多分布式相关操作服务,比如,分布式锁、分布式集合、可通过Redis支持延迟队列,对字符串的操作支持比较差

使用建议:lettuce+Redisson
lettuce支持基础的Redis操作,Redisson提供了很多开箱即用的Redis高级功能,相互配合则比较完善。

当主从机写入配置中是,哨兵模式切换主从机时,是否会修改配置文件呢?具体怎么工作的呢???如何切换的?? 

故障切换机制

1. 启动群集后,群集程序默认会在从库的redis文件中加入连接主的配置

# Generated by CONFIG REWRITE
slaveof 192.168.137.40 6379

2.启动群集之后,群集程序默认会在主从的sentinel.conf文件中加入群集信息

主:

复制代码
port 26379
dir "/usr/local/redis-6379"
# 守护进程模式
daemonize yes
# 指明日志文件名
logfile "./sentinel.log"
sentinel monitor mymaster 192.168.137.40 6379 1
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 18000
sentinel auth-pass mymaster 123456
# Generated by CONFIG REWRITE
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 1
sentinel known-slave mymaster 192.168.137.40 6380
sentinel known-sentinel mymaster 192.168.137.40 26380 c77c5f64aaad0137a228875e531c7127ceeb5c3f
sentinel current-epoch 1
复制代码

从:

复制代码
#sentinel端口
port 26380
#工作路径
dir "/usr/local/redis-6380"
# 守护进程模式
daemonize yes
# 指明日志文件名
logfile "./sentinel.log"
#哨兵监控的master,主从配置一样,在进行主从切换时6379会变成当前的master端口,
sentinel monitor mymaster 192.168.137.40 6379 1
# master或slave多长时间(默认30秒)不能使用后标记为s_down状态。
sentinel down-after-milliseconds mymaster 5000
#若sentinel在该配置值内未能完成failover操作(即故障时master/slave自动切换),则认为本次failover失败。
sentinel failover-timeout mymaster 18000
#设置master和slaves验证密码
sentinel auth-pass mymaster 123456
#哨兵程序自动添加的部分
# Generated by CONFIG REWRITE
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 1
###指明了当前群集的从库的ip和端口,在主从切换时该值会改变
sentinel known-slave mymaster 192.168.137.40 6380
###除了当前的哨兵还有哪些监控的哨兵
sentinel known-sentinel mymaster 192.168.137.40 26379 7a88891a6147e202a53601ca16a3d438e9d55c9d
sentinel current-epoch 1
复制代码

模拟主故障

复制代码
[root@monitor redis-6380]# ps -ef|grep redis
root       4171      1  0 14:20 ?        00:00:15 /usr/local/redis-6379/src/redis-server *:6379                          
root       4175      1  0 14:20 ?        00:00:15 /usr/local/redis-6380/src/redis-server *:6380                          
root       4305      1  0 15:28 ?        00:00:05 /usr/local/redis-6379/src/redis-sentinel *:26379 [sentinel]                            
root       4306      1  0 15:28 ?        00:00:05 /usr/local/redis-6380/src/redis-sentinel *:26380 [sentinel]                            
root       4337   4144  0 15:56 pts/1    00:00:00 grep redis
[root@monitor redis-6380]# kill -9 4171
[root@monitor redis-6380]# ps -ef|grep redis
root       4175      1  0 14:20 ?        00:00:15 /usr/local/redis-6380/src/redis-server *:6380                          
root       4305      1  0 15:28 ?        00:00:05 /usr/local/redis-6379/src/redis-sentinel *:26379 [sentinel]                            
root       4306      1  0 15:28 ?        00:00:05 /usr/local/redis-6380/src/redis-sentinel *:26380 [sentinel]                            
root       4339   4144  0 15:56 pts/1    00:00:00 grep redis
[root@monitor redis-6380]# 
复制代码

从哨兵配置文件中可以看到当前的主库的已经发生了改变

 从日志文件也可以看到当前的主已经从6379转换成了6380

待续......

posted @ 2021-08-31 10:47  背着泰山找黄河  阅读(79)  评论(0编辑  收藏  举报