redis数据类型及操作,redis哨兵模式和redis集群模式的小记

一. 简介

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。

    下载地址:https://github.com/microsoftarchive/redis/releases

二. Redis的优势

:Redis非常快,每秒可执行大约110000次的设置(SET)操作,每秒大约可执行81000次的读取/获取(GET)操作。

支持丰富的数据类型:Redis支持开发人员常用的大多数数据类型,例如列表,集合,排序集和散列等等。这使得Redis很容易被用来解决各种问题,因为我们知道哪些问题可以更好使用地哪些数据类型来处理解决。

操作的原子性:所有Redis操作都是原子操作,这确保如果两个客户端并发访问,Redis服务器能接收更新的值。

很多使用工具:Redis是一个多实用工具,可用于多种用例,如:缓存,消息队列(Redis本地支持发布/订阅),应用程序中的任何短期数据,例如,web应用程序中的会话,网页命中计数等。

三. 数据类型

A. 字符串类型 (字符串的值,最大长度为512M)

B. 散列类型(Hash)  (map)

C. 列表类型(List) (列表的最大长度为2^32 -1个元素,大概40亿)

D. 集合类型(Set) 

E. 有序集合类型(zset)

四. 常用数据类型的操作

keys * : 获取数据库的所有的键。

exists key: 判断某个键是否存在,返回表示存在,0表示部存在。

type key: 获取键的类型(string,hash,list,set,zset)

4.1 字符串的常用操作

    set key value: 设置或者覆盖值。            ****

    incr key : 将对应的键的值,递增1.

    decr key : 将对应的键的值,递减1.

    get key:  根据键取值。                      ****

    del key [key1, key2,,]: 删除某个键。         ****

    expire key 时间(秒):设置key的存活时间,单位为秒。  ****

    ttl code: 查看存活时间。 (TTL  Time To Live)  

    setnx key value: 如果不存在就设置。(redis设置分布式锁)

4.2 列表的操作

    lpush key value: 往左侧中设置值。

    rpush key value: 往右侧插入值。

    lrange start end: 取集合中索引在[start, end]之间的值。

            例:lrange aa 0 2   lrange aa 0 -1

    llen key: 获取集合的长度。

    lpop key: 移除并返回首元素。

    rpop key: 移除并返回尾元素。

    lrem key count value: 移除列表中count个值为value的数据。当count为0,移除所有。(了解)

    ltrim key start end: 保留指定区域的元素,其他全部删除。  (了解)

    lset key index value: 设置索引为index的值为value.

    lindex key index: 获取索引为index的元素。

4.3 集合的操作

    sadd key member [memerb..]: 往集合中添加元素,返回添加成功的个数。

    smembers key: 返回集合中所有的元素。

    srem key member: 删除元素。

    sismember key member: 判断member是否存在, 存在返回1,不存在返回0。

    scard key: 返回集合中的个数。

    srandmember key: 从集合中随机返回一个值。(了解)

    spop key: 移除并返回一个随机的member. (了解)

    smove src destination member: 将一个元素移动到另外一个集合中。(了解)

    sinter key key: 对集合求交集。 (了解)

    sunion key key: 对两个集合求并集。(了解)

    sdiffstore destination key1 key2:  差集运算并存储到集合中。(了解)

    sinterstore destination key1 key2: 交集存储到集合中。(了解)

    sunionstore destionation key1 key2: 并集存储到集合中。(了解)

4.4 Hash操作

    hset key field value: 设置值, 如果存在相同的Key,对应的值会覆盖之前的。

    hmset key field value filed value: 设置多个值。

    hget key field: 取值。

    hexists key field: 是否存在。

    hgetall key: 获取集合中所有的元素。

    hdel key field: 删除字段。

    hkeys key: 获取所有的key。

    hvals key: 获取所有的字段值。

    hlen key: 获取字段的数量。

    hsetnx key field value : 不存在的时候设置值。

4.5 有序集合

    zadd key score value [score1 value1]: 添加。

    zscore key value: 获取分数。

    zrange key start end: 获取索引从start开始,到end结束的所有的元素。

    zrange key start end withscores: 查询索引从start开始,到end结束的所有元素名和分数。

    zcard key: 获取元素的个数。

    zcount key min max: 获取在指定分数范围内的元素的个数。闭区间[min, max]

    zrem key value1 [value2]: 删除元素。

    zrank key value: 返回value在key中的下标。

    zrangebyscore key begin end: 查询分数在[begin,end]区间的所有值,根据分数排序。

    zrangebyscore key min max limit index length; 分页,min是最低分,max最高分,index是索引,length是长度。

    zrevrange key 2 3: 倒序排列,然后去取下标在[2, 3]区间的元素。(了解)

    zremrangebyscore key min max:  移除分数在[min,max]之间的数据,返回移除的个数。(了解)

    zremrangebyrank key begin end: 移除索引在[begin,end]之间的数据。(了解)

五. Redis配置

redis的核心配置文件为redis的解压目录下名为redis.windows.conf的模板文件,拷贝一份重命名为redis.conf文件。

5.1 安全登录




5.2 数据的持久化


5.3 主从备份(灾备)(Master-Slave)


六. Redis 持久化之RDB和AOF

Redis 有两种持久化方案,RDB(Redis DataBase)和 AOF (Append Only File).

6.1 RDB存储

RDB 是 Redis 默认的持久化方案。在指定的时间间隔内,执行指定次数的写操作,则会将内存中的数据写入到磁盘中。即在指定目录下生成一个dump.rdb文件。Redis 重启会通过加载dump.rdb文件恢复数据。在5.2小结已经涉及到该存储的方式。

6.2 AOF存储

Redis 默认不开启。它的出现是为了弥补RDB的不足(数据的不一致性),所以它采用日志的形式来记录每个写操作,并追加到文件中。Redis 重启的会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。


6.3 总结

1.Redis 默认开启RDB持久化方式,在指定的时间间隔内,执行指定次数的写操作,则将内存中的数据写入到磁盘中。

2.RDB 持久化适合大规模的数据恢复,但它的数据一致性和完整性较差。

3.Redis 需要手动开启AOF持久化方式,默认是每秒将写操作日志追加到AOF文件中。

4.AOF 的数据完整性比RDB高,但记录内容多了,会影响数据恢复的效率。

5.Redis 针对 AOF文件大的问题,提供重写的瘦身机制。

6.若只打算用Redis 做缓存,可以关闭持久化。

7.若打算使用Redis 的持久化。建议RDB和AOF都开启。其实RDB更适合做数据的备份,留一后手。RDB出问题了,还有AOF。

七. Linux中Redis的安装

Linux版Redis的下载地址为:https://redis.io/download

将Redis放入到Linux操作系统中,然后解压,进入到redis-5.0.5目录下:


进入到redis-5.0.5目录

执行 make 命令

make

执行 make 命令

如果在使用make命令的时候出现如上的错误,参考如下网址:

https://blog.csdn.net/realize_dream/article/details/106483499

安装所需的编译

    yum install cpp

    yum install binutils

    yum install glibc

    yum install glibc-kernheaders

    yum install glibc-common

    yum install glibc-devel

    yum installgcc

    yum installmake

升级GCC

    yum -y install centos-release-scl

    yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils

    scl enable devtoolset-9 bash

安装redis

    make MALLOC=libc

启动Redis, 进入到src目录下,执行如下命令:

    ./redis-server

八. redis哨兵模式(sentinel)

获取redis的配置文件

    wget http://download.redis.io/redis-stable/redis.conf

主的配置

    # bind 127.0.0.1    #将该行代码注释掉

    masterauth  admin    #主节点的认证,因为主节点可能掉线,当其重新加入集群后,需要认证。

    requirepass admin    #设置密码

从的配置

    # bind 127.0.0.1        #将该行代码注释掉

    requirepass admin        #和主保持一致,因为从节点可能提升为主节点

    replicaof master 6379    #master是docker-compose.yml文件中主的服务名

    masterauth admin        #主节点的密码

获取哨兵的配置文件

    wget http://download.redis.io/redis-stable/sentinel.conf

哨兵的配置文件:

    # sentinel monitor 固定

    # cluster-master该名字是在哨兵中随意定义的,在哨兵主的名字,该名字如果重新定义了,全文中都需要修改

    # master 是主的ip地址,也可以写成docker-compose.yml文件中主的服务名

    # 6379是主节点的端口号

    sentinel monitor cluster-master master 6379 2

# 主机的密码

    sentinel auth-pass cluster-master admin

docker-compose文件的编写

version: '3.7'

services:

  master:

    image: redis

    ports:

      - 6379:6379

    volumes:

      - /redis-sentinel-mode/master/redis.conf:/var/local/redis/redis.conf

      # 容器中默认将数据就是放在 /datas目录下

      - /redis-sentinel-mode/master/datas:/datas

    command: ['redis-server', '/var/local/redis/redis.conf']

  slave1:

    image: redis

    ports:

      - 6380:6379

    volumes:

      - /redis-sentinel-mode/slave1/redis.conf:/var/local/redis/redis.conf

      # 容器中默认将数据就是放在 /datas目录下

      - /redis-sentinel-mode/slave1/datas:/datas

    command: ['redis-server', '/var/local/redis/redis.conf']

  slave2:

    image: redis

    ports:

      - 6381:6379

    volumes:

      - /redis-sentinel-mode/slave2/redis.conf:/var/local/redis/redis.conf

      # 容器中默认将数据就是放在 /datas目录下

  - /redis-sentinel-mode/slave2/datas:/datas

    command: ['redis-server', '/var/local/redis/redis.conf']

  sentinel1:

    image: redis

    ports:

      - 26391:26379

    volumes:

      - /redis-sentinel-mode/sentinel1/sentinel.conf:/var/local/redis/sentinel.conf

      # 容器中默认将数据就是放在 /datas目录下

    command: ['redis-sentinel', '/var/local/redis/sentinel.conf']

  sentinel2:

    image: redis

    ports:

      - 26392:26379

    volumes:

      - /redis-sentinel-mode/sentinel2/sentinel.conf:/var/local/redis/sentinel.conf

      # 容器中默认将数据就是放在 /datas目录下

    command: ['redis-sentinel', '/var/local/redis/sentinel.conf']

  sentinel3:

    image: redis

    ports:

      - 26393:26379

    volumes:

      - /redis-sentinel-mode/sentinel3/sentinel.conf:/var/local/redis/sentinel.conf

      # 容器中默认将数据就是放在 /datas目录下

    command: ['redis-sentinel', '/var/local/redis/sentinel.conf']

九. redis集群模式

9.1 使用docker来创建集群

集群模式的配置全部一样

    # bind 127.0.0.1      #注释掉

    requirepass  admin    #加上密码

    masterauth admin      #认证

    cluster-enabled yes    #将注释放开

docker-compose.yml文件的编写:

version: '3.7'

services:

  master1:

    image: redis

    volumes:

      - /redis-cluster-mode/master1/redis.conf:/var/local/redis/redis.conf

    ports:

      - 6381:6379

    command: ['redis-server', '/var/local/redis/redis.conf']

  master2:

    image: redis

    volumes:

      - /redis-cluster-mode/master2/redis.conf:/var/local/redis/redis.conf

    ports:

      - 6382:6379

    command: ['redis-server', '/var/local/redis/redis.conf']

  master3:

    image: redis

    volumes:

      - /redis-cluster-mode/master3/redis.conf:/var/local/redis/redis.conf

    ports:

      - 6383:6379

    command: ['redis-server', '/var/local/redis/redis.conf']

  slave1:

    image: redis

    volumes:

      - /redis-cluster-mode/slave1/redis.conf:/var/local/redis/redis.conf

    ports:

      - 6384:6379

    command: ['redis-server', '/var/local/redis/redis.conf']

  slave2:

    image: redis

    volumes:

      - /redis-cluster-mode/slave2/redis.conf:/var/local/redis/redis.conf

    ports:

      - 6385:6379

command: ['redis-server', '/var/local/redis/redis.conf']

  slave3:

    image: redis

    volumes:

      - /redis-cluster-mode/slave3/redis.conf:/var/local/redis/redis.conf

    ports:

      - 6386:6379

    command: ['redis-server', '/var/local/redis/redis.conf']


进入到任何一个容器中,执行如下代码,创建集群:

    redis-cli --cluster create 172.21.0.7:6379 172.21.0.4:6379 172.21.0.2:6379 172.21.0.5:6379 172.21.0.3:6379 172.21.0.6:6379 -a admin --cluster-replicas 1

进入到redis中,执行如下命令,验证集群是否成功:cluster nodes

验证集群是否成功

9.2 集群的扩容

        重新创建两个redis的节点,目的是为了让其成为主从。

查看上一次集群的网络,使用docker network ls命令:

查看上一次集群的网络

docker-compose.yml文件的内容

version: '3.7'

services:

  master4:

    image: redis

    volumes:

      - /redis-external-cluster-node/master4/redis.conf:/var/local/redis/redis.conf

    ports:

      - 6391:6379

    networks:

      - redis-cluster-mode_default

    command: ['redis-server', '/var/local/redis/redis.conf']

  slave4:

    image: redis

    volumes:

      - /redis-external-cluster-node/slave4/redis.conf:/var/local/redis/redis.conf

    ports:

      - 6392:6379

    networks:

      - redis-cluster-mode_default

    command: ['redis-server', '/var/local/redis/redis.conf']

networks:

  #对上一次的docker-compose的网络进行扩展,让新的docker-compose与之前的docker-compose在同一个网段

  redis-cluster-mode_default:

    external: true


查看新启动的redis节点的ip地址:

    docker inspect 7af8698a0a78 b38eb96a00ea | grep IPA

将新的redis节点添加到集群中

    cluster meet 172.21.0.8 6379

    cluster meet 172.21.0.9 6379

将新的两个节点,让其构成主从节点,首先查看主节点的 node 号

    redis-cli -h 172.21.0.9 -p 6379 -a admin cluster replicate d2c9a3628a151f532dec0e3e2328ead7c55d28af

给新增的节点分配槽位,原理是将其他节点的槽位,平均挪到新增节点中,执行如下命令:

redis-cli --cluster reshard 172.21.0.8:6379 -a admin --cluster-from 365a6640c3e66dfb0f2c7e435f7cdb2639dda028,76e10e0005b309ff2aff4c45c3c4552346ed9b7d,7d35e4be39389e24ce19fdf7960e83bc7932d7ee --cluster-to d2c9a3628a151f532dec0e3e2328ead7c55d28af --cluster-slots 4095

分配槽位之前

分配槽位之前

分配槽位之后


测试,进入到一个容器中,设置值,不同的name会hash到不同的槽位中:

测试不同的值被HASH到不同的槽位中

十. redis与spring boot整合

依赖配置:

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-data-redis</artifactId>

    </dependency>

    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->

   <dependency>

         <groupId>org.apache.commons</groupId>

          <artifactId>commons-pool2</artifactId>

          <version>2.7.0</version>

    </dependency>

代码中直接注入 RedisTemplate即可使用。

十一. Mybatis二级缓存

11.1 缓存类的实现

一级缓存,就是SqlSession级别的缓存;二级缓存就是SqlSessionFactory级别的缓存。

要想使用Mybatis的二级缓存,必须要实现Cache接口,具体的实现如下:

public class RedisCache implements Cache {

    private RedisTemplate<Object, Object> redisTemplate;

    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    private String id;

    public RedisCache(){}

    public RedisCache(String id) {

        this.id = id;

    }

    private RedisTemplate<Object, Object> getRedisTemplate() {

        if(null == this.redisTemplate) {

            this.redisTemplate = (RedisTemplate)ApplicationContextHolder.getBean("redisTemplate");

        }

        return this.redisTemplate;

    }

    @Override

    public String getId() {

        return this.id;

    }

    @Override

    public void putObject(Object key, Object value) {

        if(value != null) {

            this.getRedisTemplate().opsForValue().set(key, value);

        }

    }

    @Override

    public Object getObject(Object key) {

        if(null != key) {

            return this.getRedisTemplate().opsForValue().get(key);

        }

        return null;

    }

    @Override

    public Object removeObject(Object key) {

        if(null != key) {

            this.getRedisTemplate().delete(key);

        }

        return null;

    }

    @Override

    public void clear() {

        Set<Object> set = getRedisTemplate().keys("*:" + this.id + "*");

        if(null != set) {

            getRedisTemplate().delete(set);

        }

    }

    @Override

    public int getSize() {

        return 0;

    }

    @Override

    public ReadWriteLock getReadWriteLock() {

        return this.readWriteLock;

    }

}

11.2 获取ApplicationContext

@Component

public class ApplicationContextHolder implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

        this.applicationContext = applicationContext;

    }

    public static ApplicationContext getApplicationContext() {

        return applicationContext;

    }

    public static Object getBean(String name) {

        return getApplicationContext().getBean(name);

    }

    public static <T> T getBean(Class<T> clazz) {

        return getApplicationContext().getBean(clazz);

    }

    public static <T> T getBean(String name, Class<T> clazz) {

        return getApplicationContext().getBean(name, clazz);

    }

}

11.3 mapper.xml配置

<!--

        flushInterval: 清空缓存的时间间隔,单位为毫秒; 默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用更新语句时刷新。

        size: 可以被设置为任意正整数, 缓存的数量,默认是1024;

        evication: LRU 移除最长时间不被使用的对象。

        blocking: 默认是false;

    -->

<cache size="1024" type="com.qf.cache.RedisCache" />  RedisCache c = new RedisCache();

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335