redis最详细笔记

Redis官网:http://www.redis.cn/ Redis线程:Redis 属于单线程还是多线程?不同的版本有什么区别?_redis is single threaded-优快云博客

Redis下载:https://github.com/redis/redis/tags | Index of /releases/

Tendis官网:Tendis存储版

??#### 什么是Redis

redis是一个nosql(not only sql不仅仅只有sql)数据库,翻译成中文叫做非关系型型数据库。 关系型数据库:以二维表形式存储数据 非关系型数据库:以键值对形式存储数据(key, value形式) 是一家意大利的创业公司出的,后来这家公司被VMware赞助。redis底层用C语句编写。

redis是将数据存放到内存中,由于内容存取速度快所以redis被广泛应用在互联网项目中, redis优点:存取速度快,官方称读取会达到30万次每秒,写在10万次每秒,具体限制于硬件。 缺点:对持久化支持不够良好, 所以redis一般不作为数据的主数据库存储,一般配合传统的关系型数据库使用。

redis应用领域

分布式缓存 分布式session 论坛、评论首页或前几页 秒杀,抢购 总之是用在数据访问量大,并发量高的情况下

怎么用

redis主要就是使用命令来进行操作,java端在代码中可以使用Jedis来操作redis服务器 redis数据类型 字符串String 列表list redis中使用的是双向循环链表来实现的list,在redis中更像栈 散列Hash 一般应用于将redis作为分布式缓存,存储数据库中的数据对象 集合set set中数据是无序的并且不允许重复 有序集合zset redis会根据分数自动排序,这里可以使用在学生成绩排序,或者是手机应用商店流行软件排名等需求中

redis持久化方案:

rdb:可以设置间隔多长时间保存一次(Redis不用任何配置默认的持久化方案)(dump.rdb) 优点:让redis的数据存取速度变快 缺点:服务器断电时会丢失部分数据(数据的完整性得不到保证) aof:可以设置实时保存(修改配置文件将appendonly改为yes)(appendonly.aof) 优点:持久化良好,能保证数据的完整性 缺点:大大降低了redis系统的存取速度

Redis 4.0 混合持久化

重启 Redis 时,我们很少使用 rdb 来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志的性能相对 rdb 来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。

Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。如图 1-3 所示,将 rdb 文件的内容和增量的 AOF 日志文件存在一起。这里的 AOF 日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量 AOF 日志,通常这部分 AOF 日志很小

img

于是在 Redis 重启的时候,可以先加载 rdb 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,重启效率因此得到大幅提升。

Redis和Memcached的区别:

1、存储方式上:memcache会把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。redis有部分数据存在硬盘上,这样能保证数据的持久性。

2、数据支持类型上:memcache对数据类型的支持简单,只支持简单的key-value,,而redis支持六种数据类型。

3、使用底层模型不同:它们之间底层实现方式以及与客户端之间通信的应用协议不一样。redis直接自己构建了VM机制,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

4、value的大小:redis可以达到1GB,而memcache只有1MB

启动

windows版本可以去gitee搜索redis-windows下载,解压可用

打开一个cmd窗口,使用cd命令切换到解压目录(D:\app\redis | D:\Program Files\Redis) 运行 redis-server.exe redis.conf 或者 双击redis-server.exe

重新打开一个cmd窗口,使用cd命令切换到指定目录 运行 redis-cli.exe -h 192.168.174.133 -p 6379 -a 123456 其中192.168.174.133是ip,6379是redis服务端的端口,密码默认空,不输入ip和端口默认本机6379

Redis常用命令集

Redis 命令参考 — Redis 命令参考

1)连接操作命令
ping:检查连接
quit:关闭连接(connection)
auth:简单密码认证
help cmd: 查看cmd帮助,例如:help quit
2)持久化
save:    将数据同步保存到磁盘
bgsave:  将数据异步保存到磁盘
lastsave:返回上次成功将数据保存到磁盘的Unix时戳
shutdown:将数据同步保存到磁盘,然后关闭服务
flushdb: 清除当前数据库的所有keys
flushall:清除所有数据库的所有keys
3)远程服务控制
info:   提供服务器的信息和统计
monitor:实时转储收到的请求
slaveof:改变复制策略设置
config: 在运行时配置Redis服务器
4)对value操作的命令
  keys *      // 查看所有keys
  keys prefix_*     // 查看前缀为"prefix_"的所有keys
  exists(key):确认一个key是否存在
  del(key):删除一个key
  type(key):返回值的类型
  keys(pattern):返回满足给定pattern的所有key
  randomkey:随机返回key空间的一个
  rename(oldname, newname):重命名key
  dbsize:返回当前数据库中key的数目
  expire:设定一个key的活动时间(s)
  ttl:获得一个key的活动时间
  select(index):按索引查询
  move(key, dbindex):移动当前数据库中的key到dbindex数据库
  flushdb:删除当前选择数据库中的所有key
  flushall:删除所有数据库中的所有key
5)String
set(key, value):给数据库中名称为key的string赋予值value
get(key):返回数据库中名称为key的string的value
getset(key, value):给名称为key的string赋予上一次的value
mget(key1, key2,…, key N):返回库中多个string的value
setnx(key, value):添加string,名称为key,值为value
setex(key, time, value):向库中添加string,设定过期时间time
mset(key N, value N):批量设置多个string的值
msetnx(key N, value N):如果所有名称为key的string都不存在
incr(key):名称为key的string增1操作
incrby(key, integer):名称为key的string增加integer
decr(key):名称为key的string减1操作
decrby(key, integer):名称为key的string减少integer
append(key, value):名称为key的string的值附加value
substr(key, start, end):返回名称为key的string的value的子串

NX是Not eXists的缩写,如SETNX命令就应该理解为:SET if not exists。

6)List:存集合,可重复
rpush(key, value):在名称为key的list尾添加一个值为value的元素
lpush(key, value):在名称为key的list头添加一个值为value的 元素
llen(key):返回名称为key的list的长度
lrange(key, start, end):返回名称为key的list中start至end之间的元素
ltrim(key, start, end):截取名称为key的list
lindex(key, index):返回名称为key的list中index位置的元素
lset(key, index, value):给名称为key的list中index位置的元素赋值(修改)
lrem(key, count, value):删除count个key的list中值为value的元素
lpop(key):返回并删除名称为key的list中的首元素
rpop(key):返回并删除名称为key的list中的尾元素
blpop(key1, key2,… key N, timeout):lpop命令的block版本。
brpop(key1, key2,… key N, timeout):rpop的block版本。
rpoplpush(srckey, dstkey):返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部
7)Set:存集合,不可重复

对象是所有属性值相同认为重复,重写hashcode和equals只对程序有效,所以数据可以在取出来之后去重的

sadd(key, member):向名称为key的set中添加元素member
srem(key, member) :删除名称为key的set中的元素member
spop(key) :随机返回并删除名称为key的set中一个元素
smove(srckey, dstkey, member) :移到集合元素
scard(key) :返回名称为key的set的基数
sismember(key, member) :member是否是名称为key的set的元素
sinter(key1  key2 …key N) :求交集
sinterstore(dstkey  (keys)) :求交集并将交集保存到dstkey的集合
sunion(key1  (keys)) :求并集
sunionstore(dstkey  (keys)) :求并集并将并集保存到dstkey的集合
sdiff(key1  (keys)) :求差集
sdiffstore(dstkey  (keys)) :求差集并将差集保存到dstkey的集合
smembers(key) :返回名称为key的set的所有元素
srandmember(key) :随机返回名称为key的set的一个元素
8)ZSet:有序集合,不可重复
zadd(key score member):添加元素(score用来指定排序规则,数字越小代表值越小)
zrange(key start stop [WITHSCORES]) :获取索引区间内的元素,WITHSCORES显示score值
ZRANGE zset 0 -1 WITHSCORES:显示整个有序集成员
ZRANGE zset 1 2 WITHSCORES:显示有序集下标区间 1 至 2 的成员
zrangebyscore :获取分数区间内的元素
    zrangebyscore zset -inf +inf :显示整个有序集成员(zrangebyscore zset 8 8显示score值为8的元素)
zrem :删除元素
zcard :获取集合中元素个数
zincrby :增减元素的score
zcount : 获取分数区间内元素个数
zrank : 获取项在zset中的索引
zscore :获取元素的分数
zrevrange :获取索引区间内的元素
zrevrangebyscore:获取分数区间内的元素
zremrangebyrank:删除索引区间内的元素
zremrangebyscore:删除分数区间内的元素
zinterstore:交集
zunionstore:并集
9)Hash:存对象 hset user id 1 | hset user name admin
hset(key, field, value):向名称为key的hash中添加元素field
hget(key, field):返回名称为key的hash中field对应的value
hmget(key, (fields)):返回名称为key的hash中field i对应的value
hmset(key, (fields)):向名称为key的hash中添加元素field 
hincrby(key, field, integer):将名称为key的hash中field的value增加integer
hexists(key, field):名称为key的hash中是否存在键为field的域
hdel(key, field):删除名称为key的hash中键为field的域
hlen(key):返回名称为key的hash中元素个数
hkeys(key):返回名称为key的hash中所有键
hvals(key):返回名称为key的hash中所有键对应的value
hgetall(key):返回名称为key的hash中所有的键(field)及其对应的value
10)Stream:(Redis 5.0 新增)

主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。

我们后面有专业的消息队列ActiveMQ、RabbitMQ、RocketMQ等。

 消息队列相关命令:
    XADD - 添加消息到末尾
    XTRIM - 对流进行修剪,限制长度
    XDEL - 删除消息
    XLEN - 获取流包含的元素数量,即消息长度
    XRANGE - 获取消息列表,会自动过滤已经删除的消息
    XREVRANGE - 反向获取消息列表,ID 从大到小
    XREAD - 以阻塞或非阻塞方式获取消息列表

消费者组相关命令:
    XGROUP CREATE - 创建消费者组
    XREADGROUP GROUP - 读取消费者组中的消息
    XACK - 将消息标记为"已处理"
    XGROUP SETID - 为消费者组设置新的最后递送消息ID
    XGROUP DELCONSUMER - 删除消费者
    XGROUP DESTROY - 删除消费者组
    XPENDING - 显示待处理消息的相关信息
    XCLAIM - 转移消息的归属权
    XINFO - 查看流和消费者组的相关信息;
    XINFO GROUPS - 打印消费者组的信息;
    XINFO STREAM - 打印流信息

Redis高级应用

1、安全性 设置客户端连接后进行任何操作指定前需要密码,一个外部用户可以再一秒钟进行150W次访问,具体操作密码修改设置redis.conf里面的requirepass属性给予密码

2、主从复制 做这个操作的时候准备多个不同的配置启动多台服务器 通过主从复制可以允许多个slave server拥有和master server相同的数据库副本

如果没有主从同步那么就检查一下是不是防火墙的问题

3、事务处理 redis对事务的支持还比较简单,redis只能保证一个client发起的事务中的命令可以连续执行,而中间不会插入其他client的命令。当一个client在一个连接中发出multi命令时,这个连接会进入一个事务的上下文,连接后续命令不会立即执行,而是先放到一个队列中,当执行exec命令时,redis会顺序的执行队列中的所有命令。 比如我下面的一个例子 set age 100 multi set age 10 set age 20 exec get age --这个内容就应该是20 multi set age 20 set age 10 exec get age --这个时候的内容就成了10,充分体现了一下按照队列顺序执行的方式 discard 取消所有事务,也就是事务回滚 不过在redis事务执行有个别错误的时候,事务不会回滚,会把不错误的内容执行,错误的内容直接放弃

4、持久化机制 redis是一个支持持久化的内存数据库 snapshotting快照方式,默认的存储方式,默认写入dump.rdb的二进制文件中,可以配置redis在n秒内如果超过m个key被修改过就自动做快照 save 900 1 #900秒内有至少1个键被更改则进行快照 save 300 10 #300秒内有至少10个键被更改则进行快照 save 60 10000 #60秒内有至少10000个键被更改则进行快照

append-only file aof方式,使用aof时候redis会将每一次的修改都追加到文件中

Redis-cli参数

Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]] -h <hostname> Server hostname (default: 127.0.0.1) -p <port> Server port (default: 6379) -s <socket> Server socket (overrides hostname and port) -a <password> Password to use when connecting to the server -r <repeat> Execute specified command N times -i <interval> When -r is used, waits <interval> seconds per command. It is possible to specify sub-second times like -i 0.1 -n <db> Database number -x Read last argument from STDIN -d <delimiter> Multi-bulk delimiter in for raw formatting (default: \n) -c Enable cluster mode (follow -ASK and -MOVED redirections) --raw Use raw formatting for replies (default when STDOUT is not a tty) --latency Enter a special mode continuously sampling latency --slave Simulate a slave showing commands received from the master --pipe Transfer raw Redis protocol from stdin to server --bigkeys Sample Redis keys looking for big keys --eval <file> Send an EVAL command using the Lua script at <file> --help Output this help and exit --version Output version and exit

Redis多个数据库

注意:Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,并且基于单机才有,如果是集群就没有数据库的概念

Redis是一个字典结构的存储服务器,而实际上一个Redis实例提供了多个用来存储数据的字典,客户端可以指定将数据存储在哪个字典中。这与我们熟知的在一个关系数据库实例中可以创建多个数据库类似,所以可以将其中的每个字典都理解成一个独立的数据库。

每个数据库对外都是一个从0开始的递增数字命名,Redis默认支持16个数据库(可以通过配置文件支持更多,无上限),可以通过配置databases来修改这一数字。客户端与Redis建立连接后会自动选择0号数据库,不过可以随时使用SELECT命令更换数据库,如要选择1号数据库:

redis> SELECT 1 OK redis [1] > GET foo (nil)

然而这些以数字命名的数据库又与我们理解的数据库有所区别。首先Redis不支持自定义数据库的名字,每个数据库都以编号命名,开发者必须自己记录哪些数据库存储了哪些数据。另外Redis也不支持为每个数据库设置不同的访问密码,所以一个客户端要么可以访问全部数据库,要么连一个数据库也没有权限访问。最重要的一点是多个数据库之间并不是完全隔离的,比如FLUSHALL命令可以清空一个Redis实例中所有数据库中的数据。综上所述,这些数据库更像是一种命名空间,而不适宜存储不同应用程序的数据。比如可以使用0号数据库存储某个应用生产环境中的数据,使用1号数据库存储测试环境中的数据,但不适宜使用0号数据库存储A应用的数据而使用1号数据库B应用的数据,不同的应用应该使用不同的Redis实例存储数据。由于Redis非常轻量级,一个空Redis实例占用的内在只有1M左右,所以不用担心多个Redis实例会额外占用很多内存。

Redis桌面管理工具:

redis-desktop-manager (开源自己编译免费,或者去百度下载)

官网(收费):https://redisdesktop.com/download

码云:redisdesktop 标签 - Gitee.com(源码)

AnotherRedisDesktopManager(免费开源):https://github.com/qishibo/AnotherRedisDesktopManager/releases

程序操作Redis:

注意pojo实体类必须实现序列化

纯Java连接Redis:

Jedis:https://www.cnblogs.com/c-xiaohai/p/8376364.html

SpringBoot+Redis:

SpringBoot1.x:

<!--  redis -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
spring:
  redis:
    database: 0
    host: localhost
    port: 6379
    password: 123456
    timeout: 60   
    pool:
      max-active: 10
      max-wait: -1
      max-idle: 5
      min-idle: 3

SpringBoot2.x:

<!--  redis -->
<dependency>
	<groupId>org.springframework.boot</groupId>
    <!-- spring-boot-starter-data-redis-reactive也可以 -->
	<artifactId>spring-boot-starter-data-redis</artifactId>     
</dependency>
spring:
  redis:
    host: 192.168.174.131
    port: 6379
    username: admin			#6.x新增acl
    password: 123456 
    database: 0
    timeout: 10s  # 数据库连接超时时间,2.x中该参数的类型为Duration,在配置的时候需要指明单位

    # 连接池配置,2.x中直接使用jedis或者lettuce配置连接池
    jedis: 	  # 也可以使用[lettuce]
      pool:        
        max-idle: 50		# 最大空闲连接数        
        min-idle: 10		# 最小空闲连接数        
        max-wait:  -1s		# 等待可用连接的最大时间,负数为不限制        
        max-active: -1		# 最大活跃连接数,负数为不限制

	#哨兵(注释上面host、port,注意缩进,错了不报错默认连接localhost:6379)
    sentinel: 
      master: mymaster 
      #只配哨兵不需要配主从服务器地址(三个哨兵集群地址)
      nodes: 192.168.174.130:26379,192.168.174.131:26379,192.168.174.132:26379   

	#纯集群(注释上面host、port、sentinel)
    cluster: 
      nodes:       
      - 192.168.174.131:6001 
      - 192.168.174.131:6002
      - 192.168.174.131:6003 
      - 192.168.174.131:6004 
      - 192.168.174.131:6005
      - 192.168.174.131:6006 
一、Spring注解管理缓存:

@Cacheable、@CachePut、@CacheEvict,必须使用@EnableCaching开启,CacheManager可选

使用参数id作为键,方法返回值作为值,而且忽略空值存入缓存,下次调用根据键取值,如果有直接返回而不调用该方法,condition表示满足条件才执行缓存: @Cacheable放在一个类上时则表示该类所有的方法都是支持缓存的,条件不满足直接执行方法

//参数为对象 key="#user.id" (#对象名.属性名)
@Cacheable(value="user", key="#id", unless="#result==null", condition="#id%2==0")
public Users getUser(int id) {
    System.out.println("UsersService:");
    Users u = usersDao.findById(id);       

    return u;
}

注意: 1、返回对象的时候报java.lang.ClassCastException是和热部署冲突!去掉SpringBoot热部署就可以了 2、CacheManager(disableCachingNullValues()) 必须匹配 unless="#result==null"

@CachePut类似@Cacheable,不同的是它不会查看缓存是否存在,而是直接保存到缓存 @CacheEvict是用来标注在需要清除缓存元素的方法或类上的,可以指定的属性有value、key、condition、 allEntries和beforeInvocation allEntries表示是否需要清除缓存中的所有元素。默认为false,表示不需要。 beforeInvocation默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。

//CacheManager:
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
    //默认缓存管理器
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisCacheManager cacheManager = RedisCacheManager.create(factory);
        return cacheManager;
    }
    
    //缓存管理器
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        System.out.println("CacheManager......");
        //改序列化方式为json
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        serializer.setObjectMapper(om);

        //设置缓存配置
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();

        RedisCacheConfiguration config1 = config.serializeValuesWith(
                RedisSerializationContext.SerializationPair.fromSerializer(serializer))
                .entryTtl(Duration.ofSeconds(300))   //缓存时间,秒
                .disableCachingNullValues()          //不缓存空值
                .prefixKeysWith("user");         //前缀userssss+#id(userssss2)

        RedisCacheConfiguration config2 = config.serializeValuesWith(
                RedisSerializationContext.SerializationPair.fromSerializer(serializer))
                .entryTtl(Duration.ofHours(1))   //缓存时间,小时
                .disableCachingNullValues()         //不缓存空值
                .prefixKeysWith("news");            //缓存区间

        //对每个缓存空间应用不同的配置
        Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
        configMap.put("user", config1);            //user匹配@Cacheable的value属性值user
        configMap.put("news", config2);

        //初始化一个RedisCacheWriter
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);

        //初始化RedisCacheManager
        RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, config, configMap);
        return cacheManager;
    }
}

在SpringBoot中使用Spring Cache可以轻松实现缓存,是Spring框架提供的对缓存使用的抽象类,支持多种缓存,比如Redis、EhCache等,每种类型只能返回一个CacheManager,如果返回多个或者配置了多个不同Cache默认都会异常!

二、SpringBoot使用的模板类:

RedisTemplate和StringRedisTemplate的区别:

  1. 两者的关系是StringRedisTemplate继承RedisTemplate。

  2. 两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。

  3. SDR默认序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略。

StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。

RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。

  1. 修改默认序列化策略

    @Bean(name = "redisTemplate")
    public RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setConnectionFactory(factory);     
        
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.activateDefaultTyping(
            LaissezFaireSubTypeValidator.instance,
            ObjectMapper.DefaultTyping.NON_FINAL, 
            JsonTypeInfo.As.PROPERTY);
    
        Jackson2JsonRedisSerializer js = new Jackson2JsonRedisSerializer(Object.class);
        js.setObjectMapper(objectMapper);
        // key的序列化类型
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // value的序列化类型
        redisTemplate.setValueSerializer(js); 
        
        return redisTemplate;    
    }

    性能总结: JdkSerializationRedisSerializer序列化后长度最小,Jackson2JsonRedisSerializer效率最高。GenericJackson2JsonRedisSerializer序列化时间最长,序列化后的长度也最长,StringRedisSerializer直接就是字符串。

    如果综合考虑效率和可读性,牺牲部分空间,推荐key使用StringRedisSerializer,保持的key简明易读;value可以使用Jackson2JsonRedisSerializer

    如果空间比较敏感,效率要求不高,推荐key使用StringRedisSerializer,保持的key简明易读;value可以使用JdkSerializationRedisSerializer

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值