Redis 补充 | 青训营

77 阅读8分钟

Redis 补充

基于《狂神说Java》Redis--学习笔记_狂神说redis笔记md_毫无感情的dj的博客-CSDN博客 内容均来自这里

性能测试

使用自带的 redis-benchmark 工具测试即可

格式: redis-benchmark [option] [option value]

性能测试工具可选参数:

  • -h 指定服务器主机名 127.0.0.1
  • -p 指定服务器端口 6379
  • -s 指定服务器 socket
  • -c 指定并发连接数 50
  • -n 指定请求数 10000
  • -d 以字节的形式指定 SET/GET 值的数据大小 3
  • -k 1=keep alive 0=reconnect 1
  • -r SET/GET/INCR 使用随机 key, SADD 使用随机值
  • -P 通过管道传输 \<numreq> 请求 1
  • -q 强制退出 redis。仅显示 query/sec
  • -csv 以 CSV 格式输出
  • -l 生成循环,永久执行测试
  • -t 仅运行以逗号分隔的测试命令列表。
  • -I Idle 模式。仅打开 Nidle 连接并等待。

测试例子 (100个并发连接 100000请求):

redis-benchmark -c 100 -n 100000

一些操作和知识

数据库

Redis 有16个数据库(0~15),默认使用第0个

  • select 2 切换到第二个数据库

  • dbsize 查看数据库大小

  • key * 查看当前库所有的key

  • flushdb 清空当前数据库

  • flushall 清空所有数据库

  • exists key 判断 key 是否存在

  • move key 1 把当前 key 对应信息移动到数据库 1

  • del key1 key2 删除当前数据库中的 key1 和 key2

  • expire key 2 设置当前 key 的过期时间为 2 秒

  • ttl key 查看当前 key 的剩余存活时间

  • type key 查看当前 key 的类型

  • append key GGbond 给 key 对应的 value 字符串追加 "GGbond"

  • strlen key 获取当前字符串的长度

  • getrange key startIndex endIndex 获取 key 对应字符串,endIndex = -1 时,表示从 startIndex 到最后

  • setrange key 1 hel  给 key 对应的 calue 字符串从下标 1 开始长度为 len (hel)的替换成 hel

  • incr key 给 key 对应的 value+1

  • decr key 给 key 对应的 value-1

  • incr key 100 给 key 对应的 value+100

  • decr key 100 给 key 对应的 value-100

  • setnx key redis 如果当前 key 不存在就设置 key 对应 value 为 redis

批量设置,批量获取(原子性操作):

  • mset k1 v1 k2 v2 ...

  • mget k1 k2 ...

  • getset k v 先 get 返回 k 的值(不存在则返回 nil),然后设置 k 为v

  • rename k newname 重命名

  • randomKey 返回一个随机 key

使用场景

String(字符串):

  • 计数器
  • 统计多单位的数量
  • 粉丝数
  • 对象缓存存储

List(列表):

  • 栈(lpush, lpop)
  • 队列(lpush, rpop)
    • 消息队列
  • 阻塞队列

Set(集合):

Hash (哈希):

  • key-Map, value 是一个 Map
  • 用户信息保存,经常变动的信息
  • 适合对象的存储

Zset(有序集合):

  • 在 Set 基础上增加了一个值(用于排序)
  • 普通消息=1,重要消息=2,带权重进行判断
  • 排行榜实现

三种特殊数据类型

Geospatial

  • 朋友的定位,附近的人,打车距离计算
  • 底层是 Zset(即可以使用 Zset 的命令操作 Geospatial

geoadd key 经度 纬度 名称 添加地理位置

  • 两极无法添加
  • 经度:-180 ~ 180(度)
  • 纬度:-85.05112878 ~ 85.05112878(度)

geopos key 名称 获取指定位置的地理位置 geodist key 返回两个给定位置之间的距离(直线距离) --> (m, 米;km, 千米;mi, 英里;ft, 英尺)

georadius key 经度 纬度 半径 单位 以给定值为半径,以经度和维度为中心,查找附近的人(获得所有附近的人的地址(开启定位))通过半径查询

georadiusbymember key 成员名 半径 单位 以给定值为半径,以成员(城市名)为中心,查找

geohash key 成员1 成员2 返回一个或多个位置元素的 geohash 表示(- 如果两个字符串越相似,表示两个地方越近)

Hyperloglog

  • 基数统计的算法
  • 占用内存是固定的

基数:集合中元素的个数(先去重),如{1,2,2,3} 其基数为3(集合去重后为1,2,3 有3个元素) 网页的 UV(一个人访问访问一个网站多次,但是还是算作一个人) 传统实现UV:Set保存用户的Id,然后统计set中的元素的数量作为标准判断(这种需要保存大量用户的ID) ![[Pasted image 20230827205857.png]]

Bitmaps

  • 位存储,位图(操作二进制)
  • 统计用户信息,活跃,不活跃!登录、未登录!打卡,365 打卡!(两个状态都可以使用)

1: 打卡,0:未打卡 setbit sign 0 1 周一 setbit sign 1 0 周二 setbit sign 2 1 周三 setbit sign 3 1 周四 ... getbit sign 2 查看周三打卡情况 bitcount sign 统计 key 为sign 所有打卡天数

事务

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

  • 一次性、顺序性、排他性!执行一些列的命令

Redis 的事务

  • 开启事务(multi

  • 命令入队(其他命令

  • 执行事务(exec

  • discard 取消事务 (在执行事务之前)

异常执行: 编译时(命令写错):整个命令队列都不会执行 运行时:报错语句,会抛出异常,其他语句照样运行

监控 Watch(面试)

乐观锁

乐观锁:实现秒杀,很乐观,认为什么时候都不会出现问题,所以不会加锁!(更新数据的时候去判断一下,在此期间是否有人修改过这个数据)

  • 获取version
  • 更新的时候比较 version

Redis 实现乐观锁

单线程:

多线程:

悲观锁

悲观锁:很悲观,认为什么时候都会出现问题,无论做什么都会加锁

redis 中可以使用 watch 命令会监视给定的 key,当 exec 时候如果监视的 key 从调用 watch 后发生过变化,则整个事务会失败。 也可以调用 watch 多次监视多个 key。这样就可以对指定的 key 加乐观锁了。注意 watch 的 key 是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。 当然了 exec , discard , unwatch 命令都会清除连接中的所有监视。


Redis 发布订阅补充

命令:

这些命令被广泛用于构建即时通信应用,比如网络聊天室(chatroom)和实时广播、实时提醒等。

命令描述 PSUBSCRIBE pattern [pattern..]: 订阅一个或多个符合给定模式的频道。(psubscribe) PUNSUBSCRIBE pattern [pattern..]: 退订一个或多个符合给定模式的频道。(punsubscribe) PUBSUB subcommand [argument[argument]]: 查看订阅与发布系统状态。(pubsub)

PUBLISH channel message:向指定频道发布消息。 (publish) SUBSCRIBE channel [channel..]:订阅给定的一个或多个频道。(subscribe) SUBSCRIBE channel [channel..]:退订一个或多个频道。(subscribe)

终端 1 : subscribe blog 订阅频道 blog 终端 2: publish blog "hello world !" 发送消息到频道 blog 终端 1: ... 频道 blog 接收的消息

原理:

  • Redis 是使用 C 实现的,通过分析 Redis 源码里的 pubsub. c 文件,了解发布和订阅机制的底层实现,籍此加深对 Redis 的理解。
  • 通过 SUBSCRIBE 命令订阅某频道后,redis-server 里维护了一个字典,字典的键就是一个个 channel,而字典的值则是一个链表,链表中保存了所有订阅这个 channel 的客户端。 SUBSCRIBE 命令的关键,就是将客户端添加到给定 channel 的订阅链表的尾部,退订则就是将客户端节点从链表中移除。

使用场景:

  • 实时消息系统!
  • 实时聊天!(频道当作聊天室,将信息回显给所有人)
  • 订阅,关注系统都是可以

复杂的情况,使用专业的消息中间件

主从复制

概念: 主从复制,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。前者称为主节点(Master/Leader),后者称为从节点(Slave/Follower),数据的复制是单向的!只能由主节点复制到从节点(主节点以写为主、从节点以读为主)。

作用:

  • 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余的方式。
  • 故障恢复:当主节点故障时,从节点可以暂时替代主节点提供服务,是一种服务冗余的方式
  • 负载均衡:在主从复制的基础上,配合读写分离,由主节点进行写操作,从节点进行读操作,分担服务器的负载;尤其是在多读少写的场景下,通过多个从节点分担负载,提高并发量。
  • 高可用基石:主从复制还是哨兵和集群能够实施的基础。

环境配置: 只需配置从库,无需配置主库

查看主从复制的信息: info replication

默认情况下,每一个 redis 服务器都是主节点

详情:

复制配置文件 redis. conf 到 Redis 安装目录下: cp redis.conf XXXX

再从该文件拷贝出 3 个文件: cp redis.conf redis_6379.conf (主,端口:6379) cp redis.conf redis_6380.conf (从, 端口:6380) cp redis.conf redis_6381.conf (从, 端口:6381)

修改配置文件 :

  • 端口(92行)
  • pid 进程名(244行)
  • 日志文件名(257行)
  • rdb 文件名(339行)

启动服务: 进入配置文件所在目录: .... redis-server redis_6379.conf redis-server redis_6380.conf redis-server redis_6381.conf

查看启动状态: ps -ef | grep redis

开启四个窗口,前三个用于主从复制,最后一个用于测试 redis-cli redis-cli -p 6380 redis-cli -p 6381

一主二从: 默认情况下,每一个 Redis 服务器都是主节点 一般情况下,只配置从机

在窗口 3 中: slaveof 127.0.0.1 6379:使用 slaveof 指定主节点 ip 和端口(临时配置) ![[Pasted image 20230906211908.png]] 图片来自 基于《狂神说Java》Redis--学习笔记_狂神说redis笔记md_毫无感情的dj的博客-CSDN博客

再次查看主从复制信息: info replication

有密码配置(+永久配置): ........