redis基础2

Redis基础2

三种特殊的类型

geospatial地理位置

  1. 推算两地之间的距离
  2. geo的底层原理就是Zset
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#添加地理位置geoadd
#两级无法直接添加
#经度、纬度、名称
127.0.0.1:6379> geoadd china:city 116.40 39.9 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 120.16 30.24 hangzhou
(integer) 1
127.0.0.1:6379> geoadd china:city 106.5 29.53 chongqing
(integer) 1
127.0.0.1:6379> geoadd china:city 108.96 34.26 xian
(integer) 1

#获取指定位置的经纬度geopos
127.0.0.1:6379> geopos china:city beijing
1) "116.39999896287918091"
2) "39.90000009167092543"

#两地之间的距离geodist
127.0.0.1:6379> geodist china:city beijing shanghai
"1067378.7564"
127.0.0.1:6379> geodist china:city beijing shanghai km
"1067.3788"

#给定的经纬度为中心,指定半径为距离georadius
127.0.0.1:6379> georadius china:city 100 30 1000 km
1) "chongqing"
2) "xian"
127.0.0.1:6379> georadius china:city 100 30 1000 km withcoord
1) 1) "chongqing"
2) 1) "106.49999767541885376"
2) "29.52999957900659211"
2) 1) "xian"
2) 1) "108.96000176668167114"
2) "34.25999964418929977"
127.0.0.1:6379> georadius china:city 100 30 1000 km withdist
1) 1) "chongqing"
2) "629.6756"
2) 1) "xian"
2) "967.2846"
127.0.0.1:6379>

#找出位于指定元素周围的其他元素georadiusbymember
127.0.0.1:6379> georadiusbymember china:city beijing 2000 km
1) "chongqing"
2) "xian"
3) "hangzhou"
4) "shanghai"
5) "beijing"

#返回11个字符,代表当前城市经纬度的字符串,两个字符串越接近代表两个地方越接近 geohash
127.0.0.1:6379> geohash china:city beijing chongqing
1) "wx4fbxxfke0"
2) "wm5xzrybty0"

#geo的底层原理就是Zset,通过底层原理删除一个元素
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqing"
2) "xian"
3) "hangzhou"
4) "shanghai"
5) "beijing"
127.0.0.1:6379> zrem china:city shanghai
(integer) 1

Hyperloglog数据结构

  1. 基数:不重复的元素
  2. Redis Hyperloglog基数统计的算法,网页UV:一个网页同一个人访问多次算作是一个人,不会重复统计
  3. 传统方式,set保存用户ID,set中不允许重复,可以使用set中元素的数量作为标准
  4. 目的是为了计数,不是为了保护用户ID,需要login呢?
  5. Redis Hyperloglog基数统计的算法占用12KB内存,如果从内存角度来比较,是首选,错误率0.81%,统计UV任务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
127.0.0.1:6379> pfadd mykey a b c hc o j k k k k hy ii o p p g f u #添加
(integer) 1
127.0.0.1:6379> pfcount mykey #计数
(integer) 13
127.0.0.1:6379> pfadd mykey a b c ie k d j k l g t u a
(integer) 1
127.0.0.1:6379> pfcount mykey
(integer) 16
127.0.0.1:6379> pfadd mykey2 a h n g b g b k s
(integer) 1
127.0.0.1:6379> pfmerge mykey3 mykey mykey2 #合并
OK
127.0.0.1:6379> pfcount mykey3
(integer) 19

Bitmaps位图

  1. 位存储,只有0和1的两种状态
  2. 用户活跃/不活跃 登录/未登录 打卡/未打卡都可以使用Bitmaps
  3. 只要46个字节就可以存储用户一年内的状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 1 1
(integer) 0
127.0.0.1:6379> setbit sign 2 0
(integer) 0
127.0.0.1:6379> setbit sign 3 0
(integer) 0
127.0.0.1:6379> setbit sign 4 0
(integer) 0
127.0.0.1:6379> setbit sign 5 1
(integer) 0
127.0.0.1:6379> setbit sign 6 1
(integer) 0
127.0.0.1:6379> bitcount sign #统计打卡记录
(integer) 4

事务

  1. Redis事务的本质,一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行过程中会按照顺序执行。
  • 一次性
  • 顺序性
  • 排他性
  1. 所有命令在事务中并没有直接被执行,只有发起执行命令才会被执行
  2. Redis单条命令保存原子性,但是是事务不保证原子性
  3. Redis没有隔离级别的概念
  4. Redis事务,批量执行命令
  • 开启事务 mutli
  • 命令入队
  • 执行事务 exec
    1
    2
    3
    4
    5
    6
    7
    8
    9
    127.0.0.1:6379> multi
    OK
    127.0.0.1:6379> set k4 v4
    QUEUED
    127.0.0.1:6379> set k5 v5
    QUEUED
    127.0.0.1:6379> exec
    1) OK
    2) OK
  1. 放弃事务 discard
  2. 编译型错误,代码有问题,事务中的所有命令都不会背执行
  3. 运行时异常,队列中存在语法错误,执行命令时,错误命令抛出异常,其他命令正常执行,(验证了Redis不存在事务原子性)

悲观锁和乐观锁

悲观锁

  1. 无论做什么都要加锁

乐观锁

  1. 监视watch即为乐观锁,如果监视的值在执行时未发生变化,则执行成功,否则整个队列执行失败

配置文件redis.conf

  1. bind 127.0.0.1绑定ip
  2. protected-mode yes保护模式
  3. port 6379 端口设置
  4. daemonize yes默认no,yes时以守护进行的方式运行
  5. 持久化:在规定时间内执行了多少次操作,会持续化到文件.rdb .aof
  • save 900 1900秒内,至少有一个key进行了修改,即进行持久化操作
  • save 300 10300秒内至少有10个key进行了修改
  • stop-writes-on-bgsave-error yes持久化如果出错是否继续工作
  • rbdcompression yes是否压缩rdb文件,需要消耗一些CPU资源
  • rdbchecksum yes保存rbd文件时,检查校验错误
  • dir ./rdb保存的目录
  1. security安全配置,默认没有密码
  • config get requirepass获取密码
  • config set requirepass "111"设置密码
  • auth 111获取权限
  1. 限制client
  • maxclier 10000设置能连接上redis的最大服务器数量
  • maxmemory <byte>Redis配置最大的内存容量
  • maxmemory-policy noeviction内存到达上限后的处理策略
    • noeviction:当内存使用达到阈值的时候,所有引起申请内存的命令会报错
    • allkeys-lru:在所有键中采用lru算法删除键,直到腾出足够内存为止
    • volatile-lru:在设置了过期时间的键中采用lru算法删除键,直到腾出足够内存为止
    • allkeys-random:在所有键中采用随机删除键,直到腾出足够内存为止
    • volatile-random:在设置了过期时间的键中随机删除键,直到腾出足够内存为止
    • volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除
  • appendonly no默认不开启aof模式,默认使用rbd方式持久化
  • appendfsync always/everysec/no每次次该都会同步/每秒执行一次sync/不执行sync

Redis持久化

  1. 单独创建一个子进程来进行持久化,将数据写入到一个临时文件中,持久化过程结束后将这个文件替换上次持久化后的文件,整个过程主进程不进行任何IO操作。
  2. 默认使用rdb实现持久化,保存的文件尾dump.rdb,在snapshot中配置
  3. save命令,flushall,关闭Redis都会生成rdb
  4. 恢复rdb,dump.rdb在redis-server同级目录下,开启Redis会自动恢复数据
  5. 适合大规模的数据恢复
  6. AOF将所有命令保存在一个文件中,恢复的时候就把这些操作全部重新执行一遍,数据量较大时效率较低
  7. appendonly yes修改配置文件,开启aof
  8. 如果aof文件被破坏,Redis连接失败,redis-check-aof --fix appendonly.aof文件恢复aof文件
  9. 每一次修改都同步,保障文件完整性
  10. aof修复速度远大于rdb,运行效率也较低
  11. aof文件默认最大64M,超过这个大小时候fork一个新的进程来重新aof
  12. 如果redis做缓存,不需要持久化
  13. 同时开启两种方式,优先使用aof来恢复,aof更加完整
  14. rdb更适用于备份数据库

Redis发布和订阅

  1. 用C中的pubsub.c文件,通过publish/subscribe/psubscribe实现订阅和发布的功能
  2. 订阅频道后,在redis-server中维护一个字典表,字典表标识频道,字典的值是链表,链表中保存所有订阅这个频道的客户端
  3. subscribe命令将客户端添加到给定的channel的订阅链表中
  4. publish命令遍历链表,将消息发送给所有订阅者

Redis主从复制

  1. 将一台Redis服务器的数据复制到其他服务器,称为主节点和从节点,数据复制是单项的,从主复制到从,主节点只能有一个。一般为一主二从
  2. 读写分离,80%的情况下都在进行读操作,减缓服务器压力
  3. 主从复制的作用:
  • 数据冗余:实现数据的热备份
  • 故障恢复:主节点出现问题时可以由从节点恢复
  • 负载均衡:主从复制配合读写分离,分担服务器负载,在写少读多的情况下,可以大大减少Redis服务器的并发量
  • 高可用(基群)基石:主从复制是哨兵和基群能够实施的基础
  1. 环境配置:
  • 默认所有节点都是主节点,因此需要配置从库
  • 复制多个redis.conf,修改配置文件,所有服务的pid、dump.rdb、端口、logfile等不能重复
  • slaveof 127.0.0.1 6379配置主节点,此节点变为从节点
  • info replication查看信息
  • 真实的主从配置,在文件中配置,则是永久的
  1. 主机中的所有信息都会被从机自动保存
  2. 主机断开连接,重新连接成功后,能立即重新读取数据。实际应该在从机中选取一个作为主机
  3. slaveof no one将自己设置为主节点,此时可以手动将其他从节点配置到当前主节点上
  4. 若是从机断开,重新启动后数据立马从主机中再次获取(永久的主从配置)
  5. 复制原理:
  • slave启动成功连接到master后发送一个sync同步命令
  • master接到命令后启动后台存盘过程,同时收集所有用于修改数据集命令,在后台进程执行完毕后,master将传送整个数据文件到slave,并完成一个完全同步
  • 全量复制:slave服务器在接收到数据库文件数据后,将其存盘并加载到内存中
  • 增量复制:master继续将新的所有收集到的修改命令一次传递给slave,完成同步
  • 只要重新连接master,一次完全同步将会被自动执行,即全量复制

哨兵模式

  1. 重新开启一个进程,作为一个独立的进程,发送命令,等待Redis服务器相应,监视多个Redis服务器
  2. 专业套娃:配置多个哨兵互相监督
  3. 检测到主节点不可用,哨兵之前投票,确定宕机后,进行failover操作。切换成功后,通过发布订阅模式,将哨兵把自己的监控转移到新的主机
  4. sentinel.conf,redis-sentinel sentinel.conf启动哨兵模式

    1
    2
    3
    4
    sentinel monitor myredis 127.0.0.1 6379 1 //被监控的名称,1代表主机挂了之后投票,1票就可以认为是宕机

    sentinel failover-timeout 18000
    //默认三分钟
  5. 原本的主机重新连接,只能归并到现在的主机下面当从机

  6. 哨兵集群,基于主从复制模式,主从切换转移故障,实现系统的高可用性
  7. 哨兵模式不好在线扩容,基群到达上线后,很难实现在线扩容,需要单独配置

Redis缓存穿透和雪崩

  1. 缓存没有命中,持久层数据库也没有,当很多用户都在请求持久层数据库,会给持久层数据库造成很大的压力,相当于就是缓存穿透
  2. 使用布隆过滤器,对所有可能查询的参数以hash形式存储,在控制层先进行过滤,避免对底层存储系统产生大的查询压力
  3. 缓存空对象,也会造成一些新的问题
  4. 缓存击穿:大并发集中对一个点进行访问,这个key在失效的瞬间,持续的大并发就击破缓存,直接请求数据库
  5. 设置热点数据不过期,加互斥锁,保证每个key同时只有一个线程去持久层数据库查询数据(限流降级)
  6. 缓存雪崩,在某个时刻,缓存集体失效
  • Redis高可用,增设Redis服务器
  • 限流降级,缓存失效后通过一定的手段来控制读写数据库写缓存的线程数量
  • 数据预热,在正式部署钱对可能的数据线访问一遍,在即将发生大并发访问钱手动触发加载缓存不同的key,设置不同的过期时间,使缓存失效的时间更均匀
WhitneyLu wechat
Contact me by scanning my public WeChat QR code
0%