redis linux 学习记录

1、redis 是  nosql 数据库,不仅仅只有sql

redis是目前使用比较广泛的缓存技术,redis数据都是在内存中存放的所以在获取过程中可以直接获取,从而减少执行时间

2:redis支持的数据类型

五大类型的数据结构

String:

字符串类型,使用最多的类型,value可以是任何数据,只要将数据转换为String即可,常用的方式是通过JSON转换

常用命令:

        获取:get  key 、添加:set key value

list:

列表,通常可用于模拟栈、队列

常用命令:

        插入数据在最左侧:lpush key value

        插入数据在最右边:rpush key value

        获取数据:lrange key start  end

hash:

hash(散列),可用于投票、关注、购物车等

常用命令:

        插入数据:hset key field value field2 value

        获取数据:hset key field

        获取所有:hgetall key

set:

集合,可用于差集、交集、并集等业务场景

常用命令:

        插入数据:sadd key value

        获取数据:smembers key

        随机获取并移除集合中的元素:spop key

        获取key1不存在key2的差集:sdiff key1 key2

        获取所有给定的并集:sunion key1 key2

        获取给定集合的交集:sinter key1 key2

        随机返回给定集合的一个元素:srandmember key

zset:

有序集合,可用于排名,排序等业务场景

常用命令:

        添加:zadd key score member

        获取所有:zcard key

命令详情可参考Redis 有序集合(sorted set) | 菜鸟教程

或者官网

3:redis geo 主要用于位置信息,并对位置信息进行操作

如:获取geodist key1 key2 可获取两个key之间的距离

        georadius 经度  纬度  range(m/km)可获取指定坐标range内的数据

 还有不常用的HyperLogLog等

4:安装redis

# 直接安装,

yum install redis 

# 启动

systemctl start redis

# 查看安装位置

whereis redis 

# 下载zip

unzip redis

# 安装环境

yum install gcc-c++

# 编译,进入redis 目录

make 

# 安装,最后出现src目录,安装成功

make install

# 进入src启动

redis-server  ../redis.conf

redis 默认不是后台运行的:

修改配置文件:redis.conf

daemonize no 为 yes   可后台运行

bind 127.0.0.1 修改ip可远程访问 

port 6379    默认端口6379

requirepass foobared     设置密码,默认是没有密码的

5:持久化 rdb 和 aof,数据恢复是自动的,只要重启redis会自动加载这些文件

rdb:默认是开启的,如果服务器意外宕机,重启服务后会默认加载这些记录文件

save 900 1             每隔900秒有一个修改命令,则保存一次

save 300 10

save 60 10000

可根据业务进行修改,触发之后会在redis下创建一个dump.rdb文件

优点:高效,redis会启动两个进程,主进程主要处理业务,子进程进行记录,

缺点:在宕机之前未触发的命令会丢失

如果对数据的完整性不敏感可使用该方式

aof:默认是关闭的

appendonly  no 修改为 yes 即开启aof持久化

会在redis文件夹下生成appendonly .aof文件,所有的写操作都会被记录

如果aof被破坏redis是启动不了的,

使用redis-check-aof 工具进行恢复即可命令:redis-check-aof  --fix  appendonly .aof

优点:数据完整性高,基本不会丢失数据,每次修改都会同步

缺点:aof文件远大于rdb,修复速度比rdb慢,运行效率也比rdb慢,aof记录是无限增加的,数据量会越来越大

6:主从配置,修改配置即可实现集群的搭建,主机可读可写,从机只能度不能写,否则报错。

如果使用命令配置主从关系,宕机重启后从机会恢复为主机,只有修改配置文件才是永久。

从机(slave)重启重新链接后会同步主机(master)中的数据,

并且是全量复制,然后加载到内存中

主从配置方式一:

这种方式如果主机宕机从机不会成为主机,会造成只能读,不能写的状态,

哨兵模式(主机宕机之后从机自动选举主机)

 在redis文件夹下创建文件(哨兵配置文件):vim sentinel.conf

输入:

sentinel monitor   mymaster  127.0.0.1 6379  1

保存退出

src 下有  redis-sentinel  ,运行  :./redis-sentinel  ../sentinel.conf   启动哨兵

每一台服务都需要配置哨兵,最后会形成哨兵集群,配置文件就会涉及到

端口、主机密码、故障转移时间等等配置,上边这个配置是主要配置

穿透:

是指用户访问的数据在缓存中不存在(没有命中),然后去查数据库,数据库中也没有,于是当前查询失败,当很多用户都去访问,缓存没有命中、都去请求数据库,给数据库造成压力,就相当于出现了缓存穿透

解决方式:增加条件过滤器、缓存空值等

击穿:

一个热key,所有人都在访问同一个数据,导致压力倍增,当key扛不住压力或者失效瞬间,持续的大并发就穿破缓存,直接请求数据库。

解决方式:

热key过期时间做延长处理、加锁(同一时间内只能有一个线程进行访问)等

雪崩:

是指在某一时间段,缓存集中过期失效,redis宕机;所有请求数据库,导致数据库访问量暴增,造成数据库宕机的情况

springboot集成redis

导入redis

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

springboot 提供了一个RedisTemplate 类,

redisTemplate.opsForValue  是操作String类型的
redisTemplate.opsForList   列表
redisTemplate.opsForHash   hash
redisTemplate.opsForSet    集合
redisTemplate.opsForZSet   有序集合

一些公用的方法直接使用:redisTemplate 调用即可

常用的开发方式是创建一个RedisService 注入RedisTemplate,来简化redisTemplate原生的复杂性,如下。然后使用的时候直接注入redisService 即可

@Service
public class RedisService implements IRedisService {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 创建key-value 添加
     *
     * @param key
     * @param value
     * @param time
     */
    public void set(String key, Object value, Long time) {
        redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
    }

    /**
     * 获取key 对应的数据
     *
     * @param key
     * @return
     */
    public Object get(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    public Object del(String key) {
        return redisTemplate.delete(key);
    }

    /**
     * list 数据结构类型的数据添加数据(添加到最右边)
     *
     * @param key
     * @param value
     */
    public void rightPush(String key, List<Object> value) {
        redisTemplate.opsForList().rightPush(key, value);
    }

    /**
     * list 数据类型的数据结构添加数据(添加到最左边)
     *
     * @param key
     * @param value
     */
    public void leftPush(String key, List<Object> value) {
        redisTemplate.opsForList().leftPush(key, value);
    }

    /**
     * list 数据类型的数据结构删除数据(删除最左边)
     *
     * @param key
     */
    public void leftPop(String key) {
        redisTemplate.opsForList().leftPop(key);
    }

    /**
     * list 数据类型的数据结构删除数据(删除最右边)
     *
     * @param key
     */
    public void rightPop(String key) {
        redisTemplate.opsForList().rightPop(key);
    }

    public void listSize(String key) {
        redisTemplate.opsForList().size(key);
    }


    public void setAdd(String key, Object value) {
        redisTemplate.opsForSet().add(key, value);
    }

    /**
     * 获取set中所有元素
     *
     * @param key
     */
    public void setMembers(String key) {
        redisTemplate.opsForSet().members(key);
    }

    /**
     * 随机删除set中的一个元素
     *
     * @param key
     */
    public void setPop(String key) {
        redisTemplate.opsForSet().pop(key);
    }

    public void setSize(String key) {
        redisTemplate.opsForSet().size(key);
    }

    /**
     * 交集----返回key1,key2中都存在的数据
     *
     * @param key1
     * @param key2
     */
    public void intersect(String key1, String key2) {
        redisTemplate.opsForSet().intersect(key1, key2);
    }

    /**
     * 并集----返回key1,key2 合并之后的数据
     *
     * @param key1
     * @param key2
     */
    public void union(String key1, String key2) {
        redisTemplate.opsForSet().union(key1, key2);
    }

    /**
     * 差集----返回key1中不存在key2中的数据
     *
     * @param key1
     * @param key2
     */
    public void difference(String key1, String key2) {
        redisTemplate.opsForSet().difference(key1, key2);
    }

    /**
     * 随机获取出set中的一个元素,或获取指定个数的元素
     *
     * @param key
     */
    public void setRandm(String key, Integer num) {
        if (num != null && num > 0) {
            redisTemplate.opsForSet().randomMembers(key, num);
        }
        redisTemplate.opsForSet().randomMember(key);
    }

    /**
     * hash 结构数据添加
     *
     * @param key
     * @param value
     */
    public void mapAdd(String key, Map value) {
        redisTemplate.opsForHash().putAll(key, value);
    }

    /**
     * hash 结构数据添加,指定hashKey添加
     *
     * @param key
     * @param value
     */
    public void mapAdd(String key, String hashKey, Object value) {
        redisTemplate.opsForHash().put(key, hashKey, value);
    }

    /**
     * 获取hash中所有的数据
     *
     * @param key
     */
    public void mapGet(String key) {
        redisTemplate.opsForHash().entries(key);
    }

    /**
     * 获取hash中指定key的数据
     *
     * @param key
     */
    public void mapGet(String key, String hashKey) {
        redisTemplate.opsForHash().get(key, hashKey);
    }

    /**
     * 删除指定key
     *
     * @param key
     * @param hashKey
     */
    public void mapDel(String key, String hashKey) {
        redisTemplate.opsForHash().delete(key, hashKey);
    }


    public void zsetAdd(String key, Set<Object> value) {
        redisTemplate.opsForZSet().add(key, value);
    }

    public Long zsetCount(String key) {
        Long aLong = redisTemplate.opsForZSet().zCard(key);
        return aLong;
    }

    public void zsetGet(String key, Integer start, Integer end) {
        if (start == null || start < 0) {
            start = 0;
        }
        if (end > 0 && end < start) {
            end = -1;
        }
        redisTemplate.opsForZSet().range(key, start, end);
    }

猜你喜欢

转载自blog.csdn.net/wdz985721191/article/details/120552328