Redis2 GEO, redis持久化(rdb,aof), redis主从, redis哨兵

GEO

存储经纬度,计算两个点之间的距离,统计某个点周围多少距离的其他点

北京:116.28,39.55

天津:117.12,39.08

可以计算天津到北京的距离,天津周围50km的城市,外卖等

5个城市纬度

城市经度纬度简称
北京 116.28 39.55 beijing
天津 117.12 39.08 tianjin
石家庄 114.29 38.02 shijiazhuang
唐山 118.01 39.38 tangshan
保定 115.29 38.51 baoding
geoadd key longitude latitude member
举例:
geoadd cities:locations 116.28 39.55 beijing 
  
--你实际的项目,地理位置信息从哪里来的?前端传过来的
    -app,移动端,申请权限,用户允许了,直接调用手机提供的接口,得到经纬度---》调后台接口传给你--》拿到经纬度,放到redis中即可
  (网页也是,问是否允许访问你的位置,选是返回后端)
# 我现在是张三,我跟李四是朋友---》李四所在的位置,李四距离我多远,我方圆5公里内,我的好友有谁 取出某个位置的坐标 (把经纬度通过接口给前端, 前端自己处理。或者用post模块调网上现成接口[很多]显示是哪里,再给前端) geopos cities:locations beijing 计算两个人之间的距离(算的是直线距离) geodist cities:locations beijing tianjin km 计算方圆多少公里内有谁(可以算房源,商铺,好友) georadiusbymember cities:locations beijing 150 km type cities:locations # 查看geo是什么类型,返回zset,是有序集合类型

相关命令

geoadd key longitude latitude member #增加地理位置信息
geoadd cities:locations 116.28 39.55 beijing #把北京地理信息天津到cities:locations中
geoadd cities:locations 117.12 39.08 tianjin
geoadd cities:locations 114.29 38.02 shijiazhuang
geoadd cities:locations 118.01 39.38 tangshan
geoadd cities:locations 115.29 38.51 baoding
    
geopos key member #获取地理位置信息
geopos cities:locations beijing #获取北京地理信息

geodist key member1 member2 [unit]#获取两个地理位置的距离 unit:m(米) km(千米) mi(英里) ft(尺)
geodist cities:locations beijing tianjin km #北京到天津的距离,89公里

georadius key logitude latitude radiusm|km|ft|mi [withcoord] [withdist] [withhash] [COUNT count] [asc|desc] [store key][storedist key]

georadiusbymember key member radiusm|km|ft|mi [withcoord] [withdist] [withhash] [COUNT count] [asc|desc] [store key][storedist key]
#获取指定位置范围内的地理位置信息集合
'''
withcoord:返回结果中包含经纬度
withdist:返回结果中包含距离中心节点位置
withhash:返回解雇中包含geohash
COUNT count:指定返回结果的数量
asc|desc:返回结果按照距离中心店的距离做升序/降序排列
store key:将返回结果的地理位置信息保存到指定键
storedist key:将返回结果距离中心点的距离保存到指定键
'''
georadiusbymember cities:locations beijing 150 km
'''
1) "beijing"
2) "tianjin"
3) "tangshan"
4) "baoding"
'''

总结

3.2以后版本才有

geo本质时zset类型

可以使用zset的删除,删除指定member:zrem cities:locations beijing

redis持久化

#1 持久化:把内存中的数据,保存到硬盘上
#2 两种方案:
    -快照:rdb  (类似mysql中的Dump,把内存中所有数据存到硬盘中)
    -日志:aof     (每加,修改一条记录,记一条日志。用来恢复数据,从头走一遍即可恢复)

RDB

# 3 rdb持久化:三种方式,两种手动,一种配置文件(配置文件)
    # 第一种:在redis-cli客户端敲save---》通过rdb方案持久化到硬盘上,同步操作,会造成redis的阻塞
    #    (文件策略:如果老的RDB存在,会替换老的)
      # 第二种:在redis-cli客户端敲bgsave---》通过rdb方案持久化到硬盘上,异步操作
    #    (文件策略:跟save相同,如果老的RDB存在,会替换老的)
    # 第三种:配置文件
    save   900        1
    save   300        10
    save   60         10000
    解释:
    如果60s中改变了1w条数据,自动生成rdb,自动调用一下bgsave
    如果300s中改变了10条数据,自动生成rdb,自动调用一下bgsave
    如果900s中改变了1条数据,自动生成rdb,自动调用一下bgsave
    
    # 配置文件中加入:
    save 900 1 #配置一条
    save 300 10 #配置一条
    save 60 10000 #配置一条
    dbfilename dump.rdb  # 设置启动载入的rdb文件名字,这句不写默认为dump.rdb  
    dir ./ #rdb文件存在当前目录
# 4 rdb方案有缺陷,可能会丢失数据(只是用缓存)

删除对应文件,对应aof,rdb方式无法恢复

AOF

# 5 aof持久化方案
## AOF介绍:客户端每写入一条命令,都记录一条日志,放到日志文件中,如果出现宕机,可以将数据完全恢复

## aof的三种策略
日志不是直接写到硬盘上,而是先放在缓冲区,缓冲区根据一些策略,写到硬盘上
always:redis--》写命令刷新的缓冲区---》每条命令fsync到硬盘---》AOF文件    #耗费资源,每一条命令,调flash
everysec(默认值):redis——》写命令刷新的缓冲区---》每秒把缓冲区fsync到硬盘--》AOF文件 #每秒刷一次(一般用这个)
no:redis——》写命令刷新的缓冲区---》操作系统决定,缓冲区fsync到硬盘--》AOF文件 #类似python读写文件,没调flash,由系统决定
    
# 6 aof重写
随着命令的逐步写入,并发量的变大, AOF文件会越来越大,通过AOF重写来解决该问题
本质就是把过期的,无用的,重复的,可以优化的命令,来优化
这样可以减少磁盘占用量,加速恢复速度

# 7 启用aof就是修改一下配置文件(重启即可)
  appendonly yes #将该选项设置为yes,打开
  # appendfilename "appendonly-${port}.aof" #文件保存的名字(指定aof文件名字)
  appendfilename "appendonly.aof" #文件保存的名字(指定aof文件名字)
  appendfsync everysec #采用第二种策略
  dir /bigdiskpath #存放的路径
  no-appendfsync-on-rewrite yes #在aof重写的时候,是否要做aof的append操作,因为aof重写消耗性能,磁盘消耗,正常aof写磁盘有一定的冲突,这段期间的数据,允许丢失(重写策略,是否开启)

## 公司里可以aof rdb同时使用,就是耗费性能

  自动化运维系统,自动安装redis,修改配置文件,
  给redis使用aof的持久化方案
  点按钮,切换成aof----》打开配置文件---》把那几行写入---》重启redis服务
  
  点个按钮即可

 

redis主从

# 1 为了提高性能,扩展机器(读写分离,数据副本。一主一从,一主多从)
# 2 数据流向是单向的,从master到slave
# 3 两种方式:(需要两台机器)(启动两个redis进程,分别监听两个端口)
-第一种:在客户端cli里执行命令
      -在本地起两个redis服务(进程)6380是从,6379是主
            # 6380从库基础配置修改如下
            ## port 6380    # 修改端口
            ## dir "/opt/soft/redis/data1"    # 修改数据存放目录
            ## logfile 6380.log    # 修改log文件名
            # 监测两个redis进程起来没   ps aux|grep redis-server
            ## grep --color=auto redis-server 这是监测的进程
    -登陆到从库(6380库, redis-cli -p 6380),执行 
      -slaveof 127.0.0.1 6379  # 主库增删该数据,从库跟着改(在从库写入数据会报错)
      
    -取消复制:slaveof no one
      
      
-第二种:配置文件
    -在从节点(从数据库)配置(重启即可)
          slaveof ip port #配置从节点ip和端口
        slave-read-only yes #从节点只读,因为可读可写,数据会乱
      
          slaveof 127.0.0.1 6379
        slave-read-only yes
# 4 一主多从呢?(从库只能读)
    只需要在多个从库上配置即可

redis哨兵

架构说明

可以做故障判断,故障转移,通知客户端(其实是一个进程),客户端直接连接sentinel的地址

1 多个sentinel发现并确认master有问题

2 选举触一个sentinel作为领导

3 选取一个slave作为新的master

4 通知其余slave成为新的master的slave

5 通知客户端主从变化

6 等待老的master复活成为新master的slave

# 1 哨兵是为了保证redis'服务的高可用,一个master挂掉,服务依然可以用
# 2 哨兵搭建步骤
  -1 先做一主两从
        6379是主mastre 
        6380是从slave
        6381是从slave
  -2 启用哨兵(哨兵是一个redis进程,哨兵sentinel进程可以分别放在不同的机器上)
    ## 配置解释:
sentinel monitor <master-name> <ip> <redis-port> <quorum>
告诉sentinel去监听地址为ip:port的一个master,这里的master-name可以自定义,quorum是一个数字,指明当有多少个sentinel认为一个master失效时,master才算真正失效
sentinel auth-pass <master-name> <password>
设置连接master和slave时的密码,注意的是sentinel不能分别为master和slave设置不同的密码,因此master和slave的密码应该设置相同。
sentinel down-after-milliseconds <master-name> <milliseconds> 
这个配置项指定了需要多少失效时间,一个master才会被这个sentinel主观地认为是不可用的。 单位是毫秒,默认为30秒
sentinel parallel-syncs <master-name> <numslaves> 
这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
sentinel failover-timeout <master-name> <milliseconds>
failover-timeout 可以用在以下这些方面:     
1. 同一个sentinel对同一个master两次failover之间的间隔时间。   
2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。    
3.当想要取消一个正在进行的failover所需要的时间。    
4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了。

    # vim sentinel_26379.conf #创建一个sentinel的配置文件
      #26379端口--一个哨兵
    配置文件:
    port 26379
    daemonize yes# 是否以守护进程的形式来跑
    dir data# 数据存放目录
    protected-mode no#保护模式,写不写都行,现在不需要远程连它
    bind 0.0.0.0#绑定
    logfile "redis_sentinel.log"#日志存放路径,在数据存放路径下面
    sentinel monitor mymaster 127.0.0.1 6379 2#mymaster名字随便命 主master地址端口号 2代表要有两个sntinel觉得你挂了,你才是挂了
    sentinel down-after-milliseconds mymaster 30000#指定需要多少时间,master被这个sentinel主管地认为不可用.单位是毫秒,默认为30秒
    sentinel parallel-syncs mymaster 1#设置failover主备切换时,多少slave同事对新master进行同步,数字越小,切换时间越长.注:在备份的slave不可用,设为1保证每次只有一个slave处于不能处理命令请求状态.默认为1
    sentinel failover-timeout mymaster 180000#同一个sentinel对同一个master两次failover失败之间的事件间隔,单位毫秒,用默认即可
    #26380端口--一个哨兵
       port 26380
       daemonize yes
    dir data1
    protected-mode no
    bind 0.0.0.0
    logfile "redis_sentinel.log"
    sentinel monitor mymaster 127.0.0.1 6379 2
    sentinel down-after-milliseconds mymaster 30000
    sentinel parallel-syncs mymaster 1
    sentinel failover-timeout mymaster 180000
    #26381端口--一个哨兵
    port 26381
    daemonize yes
    dir data2
    protected-mode no
    bind 0.0.0.0
    logfile "redis_sentinel.log"
    sentinel monitor mymaster 127.0.0.1 6379 2
    sentinel down-after-milliseconds mymaster 30000
    sentinel parallel-syncs mymaster 1
    sentinel failover-timeout mymaster 180000
    
    
    -redis-sentinel 配置文件来启动哨兵
    -启动哨兵:
    redis-sentinel 配置文件
    # ./src/redis-sentinel sentinel_26379.conf # 命令在src路径下
    redis-sentinel sentinel_26379.conf
    redis-sentinel sentinel_26380.conf
    redis-sentinel sentinel_26381.conf
    # ps aux |grep redis # 查看当前redis-sentinel进程
    
    -从客户端登录到一个哨兵上
    redis-cli -p 26379 # 哨兵不能写数据
    -输入info
    最后一行看到
    master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3
    # 显示主数据库地址端口,从数据库数量,几个哨兵
    -把主库手动停掉
    shutdown
    
    -连到哨兵上,输入info(主master自动变成了6381)
  master0:name=mymaster,status=ok,address=101.133.225.166:6381,slaves=4,sentinels=3#这是视频结果,有问题
  master0:name=mymaster,status=ok,address=127.0.0.1:6381,slaves=2,sentinels=3#这是我的正常结果,6381变为主。从库还是有2,实际有一个已经被关闭了
        
    -原来的主库如果启动,主库会变为从库,继续运行redis服务(哨兵不能重启redis服务,只能监控)(视频碰到了问题:数据脏了)
    
    
# python客户端连接(直接连了主库,主库挂掉,不能改代码吧)
import redis
from redis.sentinel import Sentinel

# 连接哨兵服务器(主机名也可以用域名)
# 10.0.0.101:26379
sentinel = Sentinel([('10.0.0.101', 26379),
                     ('10.0.0.101', 26378),
                     ('10.0.0.101', 26377)
             ],socket_timeout=5)
print(sentinel)
# 获取主服务器地址
master = sentinel.discover_master('mymaster')
print(master)


# 获取从服务器地址
slave = sentinel.discover_slaves('mymaster')
print(slave)


# 获取主服务器进行写入
# master = sentinel.master_for('mymaster', socket_timeout=0.5)
# w_ret = master.set('foo', 'bar')
#
#
# slave = sentinel.slave_for('mymaster', socket_timeout=0.5)
# r_ret = slave.get('foo')
# print(r_ret)
原文地址:https://www.cnblogs.com/ludingchao/p/14062785.html