redis

准备

# 安装
yum -y install redis
# 启动(加&是后台启动)(第二个参数是选择配置文件)
redis-server /etc/redis.conf &
#客户端连接
redis-cli -p 6379
#断开客户端
shutdown
#退出
exit

基础

# 数据库切换 默认16个
select 0
# 查看大小
datasize
# 查看数据库所有的key
keys *
# 清空当前库(所有库)
flushdb(flushall)
### 判断key是否存在
查看key类型
type name

String

  • 追加
    apppend name 追加内容(如果key不存在,那么等同于set)
  • 获取字符串长度
    strlen name
  • 增加减少
    incr num
    decr num
  • 截取字符串
    getrange name strat stop
  • 替换字符串
    setrange name [offset]
  • 设置值并且设置过期时间(s)
    setex key seconds value
  • 如果key不存在会设置,存在则不会覆盖
    setnx key vlaue
  • 批量设置(原子性,只要有一个失败,其他都会失败)
    mset msetnx mget
  • 对象

List [L]

所有的list命令都是l开头的,下面的基本数据结构都一样

  • 获取长度
    llen

  • lpop
    lpush
  • 队列
    rpush
  • 获取对应值
    lrange key start stop
  • 截取
    ltrim key start stop
  • 更新下标值
    lset key index value
  • 插入
127.0.0.1:6379> lrange l 0 3
1) "1"
2) "2"
3) "3"
4) "4"
127.0.0.1:6379> linsert list before 2 0 

Set(无序不重复) [S]

  • 添加
    sadd
  • 查看所有值
    smembers key
  • 是否包含
    sismember key member
  • 个数
    scard key
  • 删除
    srem key member [member …]
  • 两个set交集
    sinter key [key …]
  • 两个set并集
    sunion key [key …]

Hash(Key-Map) [H]

hset key field value
hget key field
hget
hgetall
hlen

  • 删除
    hdel key field
  • 包含
    hexists key field
  • 获得所有field
    hkeys key
  • 获得所有value
    hvalues key
  • 如果不存在可以创建
    hsetnx key field value

Zset(有序集合) [Z]

在set的基础上增加了一个值score(根据值排序)
zadd
zrem

  • 正序输出
    zrangebyscore key-inf +inf(正序)
  • 倒序输出
    zrevrangebyscore zset max min [WITHSCORES] [LIMIT offset count]
  • 数目
    zcard
  • 获取指定区间的数量

geo(地点)

  • geoadd key longitude latitude member [longitude latitude member …]
  • 获取地点经纬
  • geopos
  • 获取两个地点的距离(km)
  • grodist
  • 查询地点周围的位置(这些地点都在key中)
  • georadius key longitude latitude radius m|km|ft|mi

事务

不保证原子性

一个事务按照入队顺序执行
一个队列中命令错误对其他命令的影响

  • 编译型错误:其他命令都不会执行
  • 运行型错误:不影响其他命令的执行

开启事务(multi)
命令入队
执行事务(exec)
放弃事务(discard)

监控
  • 悲观锁(效率低)
    无论做什么都会加锁
  • 乐观锁
    无论做什么都不会加锁,更新数据的时候判断这个数据是否被修改
    线程1 开启事务,加锁(watch money)
    在这里插入图片描述
    线程2 在线程1命令入队时修改数据
    在这里插入图片描述
    最后会发现线程1的事务执行失败
  • 基本原理:在加锁后,每次开启事务都会检查key中类似version,每次key修改后version都会发生变动,如果事务开启时和提交时的version不同,则这次事务提交失败

Springboot整合

  1. entity 类要实现Serializable接口
  2. springboot配置文件
spring.redis.host=服务器公网ip
  1. conf(死代码)
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    /**
     * 自定义 RedisTemplate 怒ban
     *
     * @param factory
     * @return
     */
    @Bean(name="myRedisTemplate")
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        // 为开发方便,一般直接使用 <String, Object>
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);

        // Json序列化配置
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        // String 的序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

}
  1. 一般自写redisUtil,直接使用即可(原生代码是使用RedisTemplate(需要@Qualifier来辨别自定义的))

注意 如果连接远程服务器需要更改服务器上的配置文件,然后重启redis(我就忘记了这点),不然会连接失败.

主从复制

主机:负责写文件
从机:负责读文件(无法写入)
一个主机对应多个主机

集群环境配置

复制2个redis.conf 文件,作为从机的配置文件
修改以下属性
前四个避免重复,最后一个代表这个主机为从机

  • port
  • dbfilename
  • logfile
  • pidfile
  • slaveof (只在一个机器上开,masterip设置为127.0.0.1)
复制原理
  • 全量复制:从机加载主机的所有数据
  • 增量复制:从机加载主机修改的数据

从机在连接时至少会进行一次全量复制

哨兵

哨兵进程监视这redis实例,但主机挂掉之后,通过让从机投票选举出新的主机
如果挂掉的主机回来,会变成从机

  • 新建哨兵配置文件(写主机ip和port)
    sentinel monitor 127.0.0.1 6379 1
    后面的数字1代表主机挂了,slave投票看让谁成为主机,票数最多的变成主机
  • 运行哨兵进程
    redis-sentinel /etc/sentinel.conf

缺点:配置复杂,集群扩容困难

缓存穿透和雪崩(简介)

穿透:大量请求,但缓存都未命中,那么会给持久层数据库很大压力
击穿:一个key非常热点,大量用户并发集中对这一个点访问,当这个key过期瞬间,这些并发会访问数据库,给数据带来很大压力
雪崩:key集中过期或者redis接收数据量过大导致宕机


版权声明:本文为qq_51682771原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。