基本功能

安装

  • 源码编译安装
  • brew/apt/yum安装
  • docker启动

    • docker pull redis
    • docker run -itd —name redis-test -p 6379:6379 redis
    • docker image inspect redis|grep -i version
    • docker exec -it redis-test bash
    • redis-cli info

      基础

  • 默认有(0-15)16个库,默认使用的是0库

  • select n; 切换到n库
  • dbsize; 返回此库有多少个key

    性能测试

    1. root@8b1beccfab8c:/etc# redis-benchmark -n 100000 -c 32 -t SET,GET,INCR,HSET,LPUSH,MSET -q
    2. root@8b1beccfab8c:/etc# redis-benchmark -n 100000 -c 32

    5种常用数据结构

    string

  • 在redis中是二进制安全的,意味着该类型可以接受任何格式的数据(int、str、byte[]、json字符串、jpg数据等)

  • 字符串类型的value最多可容纳的数据长度是512M
  • 字符串append操作
    • 默认append是多次的,所以第一次append会预留内存,减少实时分配内存的消耗
    • 如果需要少量的更改操作可以直接使用 set key newValue 替换旧值
  • 整数共享
    • 为了节省内存,redis会对整数共享起来,如果有多个key的值都是同一个整数,系统内部是共享的
    • 如果能使用整数表示就尽量使用整数
    • 如果限制了redis内存和LRU缓存淘汰策略,会关闭整数共享特性
  • 整数精度问题
    • 通常能保证16位的精度
    • 超过的可能丢失精度 ```bash set get getset #获取旧值并设置新值 del exists append

incr decr incrby decrby

  1. <a name="CfdTg"></a>
  2. ### hash
  3. - 具有String key 和 String value的 Map容器
  4. - 适合于存储对象的信息
  5. ```bash
  6. hset
  7. hget
  8. hmset
  9. hmget
  10. hgetall
  11. hdel
  12. hincrby
  13. hexists
  14. hlen
  15. hkeys
  16. hvals

list

  • 按插入顺序排序的字符串链表
  • 如果键不存在则创建一个新的链表,如果所有元素均被移除则该键也被删除 ```bash lpush lpop

rpush rpop

lrange

<a name="KtxOD"></a>
### set

- 不重复的list
- 没有排序
```bash
sadd
srem
smembers
sismember

sdiff
sinter
sunion

sortedSet

  • 字符串的集合
  • 不允许重复
  • 每一个成员都有一个分数score与之关联,通过分数为成员从小到大排序,分数可以重复 ```bash zadd key score member score2 member2 … zscore key member : 返回member的分数 zcard key: 返回成员数量 zrem key member1 … zrange key start end [withScores]: 获取集合中脚注为start-end的成员,withScores表明返回的成员包含其分数 zrevrange key start stop [withScores]: 按分数从大到小的顺序返回索引start到end之间的所有元素 zremrangebyrank key start stop: 按照排名范围删除元素
<a name="uz4wK"></a>
## 3种高级数据结构
<a name="wmHUC"></a>
### bitmaps

- 不是一个真实的数据结构
- 是string类型上的一组面向bit操作的集合的封装
- 因为string是二进制安全的blob,最大长度是512M,所以bitmaps能最大设置2^32个不同的bit
```bash
setbit
getbit
bitop
bitcount
bitpos

hyperloglogs

  • 根据概率估计度量

    pfadd
    pfcount
    pfmerge
    

    geo

  • 存储经纬度信息并进行相关计算

    geoadd
    geohash
    geopos
    geodist
    georadius
    georadiusbymember
    

    线程模型

  • 作为一个redis服务,需要多个线程配合完成工作

    • 备份线程
    • IO线程
      • redis6之前是单线程
      • redis6之后是多线程,采用NIO模型
    • 内存处理线程
      • 一直是单线程
    • 。。。

      六大场景

      业务数据缓存

  • 通用数据缓存(string、int、list、map等)

  • 实时热数据(最热500条等)
  • 会话缓存,token缓存等

    业务数据处理

  • 非严格一致性要求的数据(评论、点击等)

  • 业务数据去重(订单处理的幂等校验)
  • 业务数据排序(排名、排行榜等)

    全局一致计数

  • 全局流控计数

  • 秒杀的库存计算
  • 抢红包
  • 全局ID生成

    高效统计计数

  • id去重,记录访问ip等

  • UV、PV等访问量

    发布订阅与Stream

  • PUB/SUB模拟队列

  • redis Stream是5.0版本新增加的数据结构,主要用于MQ

    分布式锁

  • 分布式锁特点

    • 原子性
    • 互斥
    • 超时 ```bash

      获取锁,NX表示不存在,PX表示超时,一条语句保证原子性

      SET [KEY] [VALUE] NX PX 30000

      老版本中不支持上面的原子性语句,也通过lua脚本实现,

      lua脚本中执行下面2条语句

      setnx [KEY] [VALUE] expire [KEY] [TIME]

释放锁-lua脚本(也保证redis的原子性,因为redis执行lua脚本时也单线程执行)

if redis.call(“get”, KEYS[1]) == ARGV[1] then return redis.call(“del”,KEYS[1]) else return 0 end

<a name="kkvsG"></a>
# Redis的Java客户端
<a name="EzlWY"></a>
## Jedis

- 官方客户端,类似于JDBC,对redis命令的封装
- 基于BIO,线程不安全,需要配置连接池管理连接
- 不推荐使用
<a name="CmphE"></a>
## Lettuce

- 主流推荐的驱动,基于NettyNIO,API线程安全,推荐使用
<a name="0yo4R"></a>
## Redission

- 基于NettyNIO,API线程安全
- 丰富的分布式功能特性(分布式版本、分布式基本数据类型、锁等)
<a name="lTuJA"></a>
# 与Spring整合
<a name="ZmRPO"></a>
## SpringDataRedis

- 核心是RedisTemplate(可配置基于Jedis、Lettuce、Redission)
- 使用方式类似于MongoDBTemplate,JDBCTemplate或JPA
- 封装了基本的Redis操作
<a name="VWDsQ"></a>
## SpringBoot集成

- 引入spring-boot-starter-data-redis
- 配置spring redis
<a name="eRkts"></a>
## SpringCache集成

- 默认使用全局CacheManager自动集成
- 使用ConcurrentHashMap或ehcache时,不需要考虑序列化问题
- redis默认使用java的对象序列化,对象需要实现Serializable,也可自定义配置,修改为其他序列化方式
<a name="4jmX3"></a>
# Redis高级功能
<a name="TNLmr"></a>
## Lua

- redis内置了lua的JIT引擎,可以直接执行lua脚本
- 也可以预编译lua脚本,运行时直接执行其签名即可
```bash
# eval script numkeys key [key ...] arg [arg ...]
eval "return 'hello world'" 0
eval "redis.call('set',KEYS[1],ARGV[1])" 1 lua-key lua-value

# SCRIPT LOAD 代码片段 返回其SHA1 shastring
# evalsha sha1 numkeys key [key ...] arg [arg ...]

数据备份和恢复

RDB

save
bgsave

# 默认保存数据到数据目录的dump.rdb文件
# 服务启动时也会默认加载此文件来初始化数据
# 查看数据目录可执行如下命令
config get dir

AOF

appendfilename "append.aof"
# appendfsync always
# appendfsync everysec
# appendfsync no

事务

# 事务命令

## 开启事务
multi

## 执行事务
exec

## 撤销事务
discard


# 乐观锁
watch 实现乐观锁,watch一个key,发生变化则事务失败

管道pipline

  • 因为redis操作大多是小命令且频繁的,CS交互的消耗可能远大于命令真正执行的消耗
  • 所以需要合并操作批量处理,且不阻塞前序命令的技术

    (echo -en "PING\r\nSET pkey redis\r\nGET pkey\r\nINCR visitor\r\nINCR visitor\r\nINCR visitor\r\n";sleep 1) | nc localhost 6379
    

    实践经验

    CPU

  • 不要阻塞

  • 谨慎使用范围操作
  • SLOWLOG GET 10 # 默认只保留最后的128条
  • 监控100%,优化高延迟的操作

    内存

  • 推荐最大内存10G-20G

  • 配置hash-max-ziplist-value 64
  • 配置zset-max-ziplist-value 64
  • 官方内存优化链接 👉 https://redis.io/topics/memory-optimization

    业务

  • 尽量相互独立,不混用

  • 规范环境和key的管理
  • 做好容量规划和监控(使用量、连接数、命中率、读写比)
  • 尽量只使用默认的 0 库,因为很多功能都不支持后面的15个库的配置,如redis cluster

    集群与高可用

    主从复制:从单节点到多节点

  • 从节点执行 SLAVEOF IP PORT 可以把自己变为从库,但推荐写在配置文件中,这样服务重启时可以自动配置

  • 这时的从节点会异步复制,并且是只读状态
  • 两种拓扑
  • SLAVEOF NO ONE 断开主从关系

主从复制.png

Sentinel:走向高可用

  • sentinel 基于raft协议监控主从节点状态并自动切换
  • 两种启动方式
    • redis-sentinel sentinel.conf #其实redis-sentinel命令就是redis-server的软连接
    • redis-server sentinel.conf —sentinel
  • 不需要配置从节点,不需要配置其他sentinel信息,会自动读取
  • Sentinel服务一般配置多个,只要有符合配置的(默认半数以上)的节点能提供服务就能保证集群可用

    # sentinel.conf
    # 最后的2是最少需要多少个节点的确认才能认为节点下线
    sentinel monitor mymaster 127.0.0.1 6379 2
    sentinel down-after-milliseconds mymaster 60000
    sentinel failover-timeout mymaster 180000
    sentinel parallel-syncs mymaster 1
    

    sentinel.png

    RedisCluster:走向分片

  • 主从复制从容量角度来说还是单机

  • 分片设计原理
    • RedisCluster通过一致性hash算法,将数据分散到多个服务器节点
    • 先设计16384个hash槽,分配到多个节点
    • 当需要在集群中读取一个key时,redis客户端先对key使用crc16算法计算一个数值,然后对16384取模,这样每个key都对应一个编号在0-16383之间的hash槽
    • 然后在此槽对应的节点上进行操作
  • 配置
    • cluster-enabled yes
  • 注意

    • 节点间使用gossip通信,规模需要小于1000
    • 默认所有槽位可用,才提供服务
    • 一般会配合主从模式使用

      Redisson

  • 基于NettyNIO

  • API线程安全
  • 大量丰富的分布式功能特性
    • JUC线程安全集合
    • 工具分布式版本
    • 分布式基本数据类型和锁
  • 代码场景

    • 分布式锁
    • 进程内拿到的redis的值是实时的即RMap对象是实时的

      Hazelcast

      基础

  • Redis演化出来Redisson,Redisson演化出来Hazelcast

  • Hazelcast IMDG(InMemoryDataGrid)是一个标准的内存网格系统
  • 基本特征

    • 分布式的:数据按某种策略尽可能均匀的分布在集群所有节点上
    • 高可用:集群中的每个节点都是active模式,可以提供业务查询和数据修改事务,部分节点不可用集群可用
    • 可扩展:按需增加、减少节点
    • 面向对象:数据模型是面向对象和非关系型的,java友好
    • 低延迟:基于内存的,可以使用堆外内存

      部署模式

  • Client-Server模式

  • Embedded模式

部署模式.png

数据分区

  • 数据集默认分271个分区,可通过hazelcast.partition.count进行配置修改
  • 所有分区均匀分布在集群所有节点,同一个节点不会同时包含一个分区的多个副本,副本总是分散的保证高可用

    控制台

    控制台.png