1、redis功能:数据库、缓存、消息队列
2、常用类型与命令:

  • String类型:
    key 是否存在:exists key key 移动到指定库:move key 1 key 移除:del key 设置过期时间(s):expire name 10 剩余过期时间(s):ttl key 查看key的类型:type key 追加字符串,key不存在set:append key str 自增:incr key 自减:decr key 步长:incrby/decrby key step 字符串截取:getrange key begin end 获取全部字符串:getrange key 0 -1 字符串替换:setrange key begin end 设置过期时间(set with expire):setex key second value 不存在再设置,分布式锁经常使用(set if not expire):setnx key value 批量创建:mset k1 v1 k2 v2 k3 v3 批量获取:mget k1 k2 k3 不存在再创建(一起成功或失败): msetnx k1 v1 k4 v4 设置对象:mset user:1:name zhangsan user:2:age 2 先get再set:getset key value
  • list类型:双头链表(栈:lpush lpop 队列:lpush rpop)
    左插入:lpush list value 右插入:rpush list value 左截取:lrange list start end 右截取:rrange list start end 从左取出前num个:lpop list num 从右取出前num个:rpop list num 获取list长度:llen list 移除list中指定的value item:lrem list 1 value 通过下标截取指定长度,list已修改,只剩下截取的:ltrim list start end 移除list最右边的元素并添加到新的list的左边:rpoplpush oldList newList 设置list指定下标的值(不存在,报错,存在更新):lset list num item 向某个指定value前或后插入值:insert list before/after oldvalue newvalue
  • set类型(无序,不能重复):
    向集合添加值:sadd set hello 查出集合内所有元素:smembers set 判断集合中是否存在某个值(1:存在0:不存在):sismember set item 获取集合中元素的个数:scard set 获取集合内的指定个数的随机元素:srandmember set num oleset中的item移动到newset:smove oleset newset item 随机删除set中的num个元素: spop set num 数字集合类-差集(set1-set2):sdiff set1 set2 数字集合类-交集:sinter set1 set2 数字集合类-并集:sunion set1 set2
  • hash类型:
    向hash设置元素:hset/hmset hash key1 value1 key2 value2 找到hash中指定key的value(hset:单个):hset/hmget hash key 获取hash中所有的数据:hgetall hash 删除hash中指定的key-value:hdel hash key 获取hsah的key-value个数:hlen hash 判断hash中指定key是否存在:hexists hash key 获取所有key:hkeys hash 获取所有value:hvals hash 自增(没有hdecrby,step可为负):hincr(by) hash key (step) 不存在key就添加(存在不能设置):hsetnx hash key value
  • Zset类型(有序集合,按key排序):
    添加元素:zadd zset key value key2 value 集合排序(倒序):zrevrange zset min(max) max(min) 集合排序(正序):zrangebyscore zset -inf(min) +inf(max) 集合排序(将序):zrevrangebyscore zset +inf(max) -inf(min) 获取集合所有元素:zrange zset 0 -1 移除集合中元素:zrem zset value 获取有序集合中指定区间内的元素个数(闭区间):zcount zset begin end
  • geospatial地理位置(底层zset):key-value(经度、维度、城市)
    添加地理位置(两极无法添加):geoadd key 116.40 39.90 beijing 获取指定城市的经纬度:geopos key beijing 获取两个指定位置的经纬度(m/km):geodist key beijing shanghai km 以给定的经纬度为中心,找出某一半径的元素(110 30:经纬度 radius:半径):georadius key 110 30 radius km 以给定元素经纬度为中心,找出某一半径的元素:georadiusbymember key beijing redius km 将经纬度转换为字符串,字符串越接近,则距离越近:geohash key beijing chongqing 查看地图中所有key:zrange key 0 -1 删除地图中指定的元素:zrem key beijing
  • Hyperloglog数据结构:基数(集合中不重复的元素)统计的算法(错误率0.81%)
    添加元素:pfadd key item1 item2 item3 集合合并(并集):pfmerge newkey oldkey1 oldkey2 统计集合内不重复的元素数量:pfcount key 应用:统计网页Uv
  • bitmap位图(按位存储):
    添加:setbit key 0(0-7) 1(0/1) 获取:getbit key 0(0-7) 统计1的个数:bitcount key

3、事务:

  • mysql事务原则:ACID原子性、一致性、隔离性、持久性
  • redis事务原则:redis单条命令保证原子性,但事务不保证原子性
  • redis事务本质:一组命令的集合,事务中的所有命令都会序列化,事务执行过程中,会按顺序执行。一致性、顺序性、排他性、
  • redis事务:
开启事务(multi)
 命令入队(...)
 执行事务(exec)
  • 放弃事务:
取消事务(discard)
  • 事务异常:
编译异常(执行事务报错,所有命令不执行)
 运行异常(错误的命令报错后,会往下正常执行其他命令)
  • 监控:watch实现乐观锁
悲观锁:认为无论干什么都加锁,处理完再解锁
 乐观锁:认为无论干什么都不加锁,更新时判断是否被修改过
 使用:开启事务,执行时,若key数据期间未变动,正常执行成功。若事务执行中,key数据变动,执行失败,解锁,后再加监视、执行事务。
 	a.监视key(watch key) 
 	b.开启事务(multi)
 	c....
 	d.执行事务(exec)
 	e.取消监视(解锁)(unwatch)
 	*重复a.b.c.d.步骤*

4、jedis:redis官方推荐的java连接开发工具、操作中间件
引入配置

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-autoconfigure -->
<dependency>
 <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
    <version>2.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
</dependency>

连接:

Jedis jedis = new Jedis("127.0.0.1",6379);
JSONObject jsonObject = new JSONObject();
jsonObject.put("name","zhangsan");
jsonObject.put("age",12);
String result = jsonObject.toJSONString();
//jedis.set("user1","111");
//jedis.watch(user1);
Transaction multi = jedis.multi();
try{
	multi.set("user1",result );
	multi.set("user2",result );
	multi.exec();
}catch(Exception e){
	//jedis.unwatch();
	multi.discardd();
	e.printStackTrace();
}finally{
	jedis.close();
}

5、springBoot整合

在springBoot2.x后,jedis被替换了lettuce
jedis:直连,多线程不安全,要避免,需用连接池;BIO模式
lettuce:采用netty,实例多线程共享,线程安全;NIO模式
PS:BIO模式(同步且阻塞)、NIO模式(同步非阻塞)、AIO(异步非阻塞)

导入依赖:Nosql-Spring Data Redis

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

配置连接:

spring.redis.host=127.0.0.1
spring.redis.port=6379

上手使用:
可以通过自定义一个redisTemplate来替换默认的;默认的RedisTemplate没有过多的设置,redis对象都需要序列化;redisTemplate两个范型都是<Object,Object>的,使用需要强制转换成<String,Object>的;默认的序列化方式是JDK序列化,会让字符串转义,在企业中,所有pojo都会用json序列化

//配置类
@Configuration
public class RedisConfig{
	//编写自己的RedisTemplate配置
	@Bean
	
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
    	//为开发方便,使用<String,Object>序列化
        RedisTemplate<String, Object> template = new RedisTemplate<String,Object>();
        template.setConnectionFactory(redisConnectionFactory);
        
        //序列化配置
        //json序列化
        Jackson2JsonRedisSerializer<Object> JsonRedisSerializer=new Jackson2JsonRedisSerializer<Object.class>;
        ObjectMapper om = new ObjectMapper();
      om.setVisibility(PropertyAccessor.All,JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
JsonRedisSerializer.setObjectMapper(om)
		//String序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

		//key采用String方式序列化
		template.setKeySerializer(StringRedisSerializer);
		//hash的key也采用Striing的序列化方式
		template.setHashKeySerializer(StringRedisSerializer);
		//value的序列化方式采用jackson
		template.setValueSerializer(JsonRedisSerializer);
		//hash的value的序列化方式采用jackson
		template.setHashValueSerializer(JsonRedisSerializer);
		
		template.afterPropertiesSet();
        return template;
    }
}
//注入
@Autowired
@Qualifier("redisTemplate")
private RedisTemplate redisTemplate;

//使用
//redisTemplate.opsForValue(操作字符串,类似String)
//redisTemplate.opsForList(list)
//redisTemplate.opsForSet(set)
//redisTemplate.opsForHash(hash)
//redisTemplate.opsForZSet(zset)
//redisTemplate.opsForGeo(geo)
//redisTemplate.opsForHyperLogLog(heperloglog)
//除了基本的操作,常用的方法都可直接通过redisTemplate进行操作,比如事务和基本的CRUD
//获取redis连接对象
//RedisConnection connection =redisTemplate.getConnectionFactory().getConnection();
//清除当前数据库,慎用,尽量不用
//connection.flushdb();
redisTemplate.opsForValue.set("name","zhangsan")
log.info(redisTemplate.opsForValue.get("name"));

6、配置

``bind 127.0.0.1 //绑定ip 远程访问*
protected-mode yes //保护模式
port 6379 //端口
daemonize yes//守护进程方式(后台方式)运行,默认是no,改为yes
pidfile /var/run/redis_6379.pid //以后台方式运行需指定pid文件
loglevel notice //日志级别
logfile //日志文件位置
datebase 16//数据库数量,默认16
always-show-logo//是否显示logo
save time keyNum//如果在time(s)内至少有keyNum个key进行了修改,就持久化到文件.rdb.aof
stop-writes-on-bgsave-error yes //持久化失败后,是否继续运行
rdbcompression yes //是否压缩rdb文件
rdbchecksum yes //保存rdb文件,是否检查错误
dir ./ //rdb文件位置
requirepass password //设置redis密码
maxcleants 100000//redis客户端最大连接数
maxmemory //redis最大内存
maxmemory-policy noeviction //内存达上限处理策略
volatile-lru//只对设置了过期时间的key进行lru(移除)
allkeys-lru//删除lru算法的key
volatile-random//随机删除即将过期的key
allkeys-random//随机删除
volatile-ttl//删除即将过期的
noeviction//永不过期,返回错误

appendonly no//默认不开启aof模式,默认使用rdb
appendfilename “appendonly.aof”//持久化文件名
appendfsync no //不执行同步,系统同步数据,速度快
always//每次修改都会同步,消耗性能,速度慢
everysec//默认项每秒执行同步,可能会丢失这1s的数据

``

7、持久化
RDB:
redis是内存数据库,如果不将内存的数据保存到磁盘,服务器进程停止,服务器中的redis数据库的状态也会丢失,需要持久化来解决这个问题。
工作原理:redis单独创建一个子进程,在指定时间间隔内,将内存中的数据写入磁盘覆盖之前的snapshot快照文件(dump.rdb),恢复时将快照文件读到内存。
缺点:rdb持久化最后一次的数据可能会丢失
触发机制:
save的规则满足,触发
退出redis,触发
flushall(别用),触发
恢复rdb文件:
将rdb文件放入redis启动目录,redis启动会自动检查
查询需要存放的地方:
获取目录:config get dir 优点:
适合大规模数据恢复
对数据完整性要求不高
缺点:
要一定的间隔时间

AOF:
将所有命令记录下来,恢复时把记录文件(appendonly.aof)全部执行一遍。
以日志形式记录redis执行过的每个操作(读操作不记录), 只追加操作记录,redis启动会读取改文件来重新执行命令构建数据。
默认不开启 appendonly no/yes,修改重启(生成appendonly.aof文件)生效同时开启AOF、RDB,优先使用AOF如果AOF文件有错,redis启动不了,需要用`rerdis-check-aof --fix filename`进行修复后,在进行修复 重写规则:默认aof文件大于64M,开启新的子进程写入新AOF文件
优点:
每次修改都同步,文件完整性优
每秒同步,可能丢失1秒数据
从不同步,效率最高
缺点:
aof数据文件远大于rdb,修复数据比rdb慢
aof运行效率比rdb慢

redis发布订阅
订阅频道(没有会创建,返回内容 消息,频道,内容):subscribe channelName
发布频道消息(value:内容):publish channelName  value