Set (集合)
set中的值是不能重复的。 sadd myset "hello" #添加一个值 smembers myset # 查看指定set值
sismember myset hello #判断某一个元素是否在set中 scard myset # 获取集合中的元素个数值 srem
myset a1 #移除set指定元素 set是无序,不重复集合 srandmember myset #随机抽set元素 spop
myset #随机删除set元素 smove sa sb a1 #将一个库里指定的值移动到另一个库里 微博、B站,共同关注!(并集)
数字集合类: • 差集 sdiff k1 k2 • 交集 sinter k1 k2 • 并集 sunion k1 k2
微博,A用户将所有关注的人放到一个set集合中!将他的粉丝也放到一个集合中 共同关注、共同爱好、二度好友(六度分割理论)
Hash (哈希)
适合对象的存储,string 更加适合字符串存储。
map集合,key-<key,value>(集合)
hset myhash filed1 kuang #存储
hget myhash filed1 #获取
hmset myhash filed1 f1 filed2 f2 #存储多个值
hmget myhash filed1 filed2 #获取多个值
hgetall myhash #获取所有的值
hdel myhash filed1 #删除hash指定的段
hlen myhash #获取hash表的字段数量
hexists myhash filed1 #指定值是否存在
hkeys myhash #获取所有的key
hvals myhash #获取所有的值
hincrby myhash mynumber 1 #数量累加
hincrby myhash mynumber -1 #数量累减
hsetnx myhash fi4 ff #如果不存在则可以设置,存在不可设置 list
ZSet(有序集合)
比set多了排序,存储班级成绩表,工资表等 普通消息,1 重要消息 2 权重判断 排行榜 范围查询
zset k1 score v1 #在set基础上增加了一个值
zadd salary 2500 xiaoming #添加值
zrangebyscore salary -inf +inf #从小到大排序,显示名称
zrevrange salary 0 -1 #从大到小排序,显示名称
zrangebyscore salary -inf +inf withscores #从小到大排序,显示值和名称 zrangebyscore salary -inf 2000 withscores #2000一下值升序 zrem salary liu
#移除值 zrange salary 0 -1 #查看集合所有值
zcard salary #获取有序集合的个数
zcount salary 1 10000 #获取指定区间的指定数量
geospatial(地理位置)
思考:朋友的定位,附近的人,打车的距离计算?
规则:两级无法直接添加,我们一般会下载城市数据,直接通过java程序一次性导入!
有效的纬度从-85.05112878度到85.05112878度。
当坐标位置超出上述指定范围时,改命令会返回一个错误
ERR invalid longitude,latitude pair 31.230000,121.470000
添加数据: 值 纬度 经度 名称
geoadd china:city 116.40 39.90 beijing
geoadd china:city 121.47 31.23 shanghai
geoadd china:city 106.50 29.53 chongqi 114.05 22.52 shengzhen
geoadd china:city 120.16 30.24 hangzhou 108.96 34.26 xian
geopos china:city beijing #获取指定城市的经度和纬度
geodist china:city beijing shanghai km #查看北京到上海直线距离m km
我附近的人?(获得所有人的地址,定位。)通过半径进行搜索
georadius china:city 110 30 500 km #获取指定经度纬度 500km以内数据
georadius china:city 110 30 500 km withdist #展示具体距离
georadius china:city 110 30 500 km withcoord #展示经度纬度
georadius china:city 110 30 500 km withcoord count 1 #显示指定数量数据
georadiusbymember china:city beijing 1000 km #找出指定位置周围的其他元素
geohash china:city beijing chongqi#将二维的字符串转换为一维的字符串
GEO底层就是zset!所以我们可以使用zset命令实现。
hyperloglog
简介:
redis 2.8.9 就更新了 hyperloglog数据结构!
基数统计算法!
页面访问量,
一个人访问一个网站多次,但是还是算作一个人。
传统方式 set用户id,自动去重
如果保存大量用户id,则比较麻烦。我们的目的是记数,而不是保存用户id。
优点:占用的内存是固定的,2^ 64 不同的元素基数,只需要费12kb内存!
如果要从内存角度考虑,hyperloglog就是首选
0.81% 错误率,统计UV任务,可以忽略不计的!
pfadd mykey a b c d e f g h i j #创建一组元素
pfcount mykey #查询一组元素数量
pfmerge mykey3 mykey myketto #合并两组元素生成新一组,去重,并集
如果允许容错,那么一定使用hyperloglog !
如果不允许容错,就使用set或自己的数据类型即可。
bitmaps
位运算。
统计疫情感染人数: 0 00 0 1 0 1 0
统计用户信息,活跃人数,不活跃,登陆,未登录人数。
位图(数据结构)操作二进制位来进行记录,0 1 两个状态
setbit sign 0 0 # 周一打卡
setbit sign 1 0 # 周二打卡
getbit sign 4 #查看指定天数打卡情况
bitcount sign #显示打卡天数
事务命令版
原子性:mySql:ACID 要么全部成功,要么全部失败
Redis单条命令是保证原子性了,但Redis事务是不支持原子性的。
事务的本质:一组命令的集合!
悲观锁:很悲观,认为什么时候都会出问题,无论做什么都会加锁。
乐观锁:很乐观认为什么都不会出问题,所以不会上锁,更新数据的时候去判断一下,在此期间是否有人修改数据
获取version ,更新时比较version
监视:watch 可以写乐观锁,本身就是乐观锁
jedis
是官网推荐java开发工具,使用Java操作Redis的一个中间键先说说jedis(底层)
- 导入jedis包
<dependencies>
<!--导入jedis包-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
</dependencies>
2.编码测试
• 连接数据库
• 操作命令
• 断开连接 jedis.close();
事务代码版
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1",6379);
//所有的命令就是之前所有指令,掌握指令很重要
System.out.println(jedis.ping());//测试连接 PONG
JSONObject jsonObject = new JSONObject();
jsonObject.put("hello","www");
jsonObject.put("name","kkk");
jedis.flushDB();
Transaction multi = jedis.multi();//开启事务
String string = jsonObject.toJSONString();
try {
multi.set("user1",string);
multi.set("user2",string);
int i = 1/0;//代码跑出异常事务,执行失败!
multi.exec();//执行事务
} catch (Exception e) {
multi.discard();//放弃事务
e.printStackTrace();
} finally {
System.out.println(jedis.get("user1"));
System.out.println(jedis.get("user2"));
jedis.close();
}
}
springboot整合
springboot操作数据:spring-data jpa jebc mongodb redis!
springDate和SpringBoot也是齐名的项目!
springboot 所有配置类都在 spring-boot-autoconfigure-2.5.3.jar 中 spring.factories 文件里
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")//我们可以自己定义一个redisTemplate来替换这个默认的
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
//默认的RedisTemplate 没有过多配置,redis对象都是需要序列化的!
//两个泛型都是object,object类型,后使用需要强制转换,<string,object>
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
//由于string类型是很常用的类型,所以就单独提出一个bean
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
整合测试一下
- 导入依赖
<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
-
测试!
默认为jdk序列化!
首先redis存储需要进行序列化,使用jar包自带 redisTemple 默认使用的是jdk进行序列化代理,可充写redisTemple方法更换序列化模式,序列化后存储key为非其他格式拼接字符,正常存储
@Configuration
public class RedisConfig {
@Bean
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;
}
}
所有的Redis操作,对于开发者来说,十分简单,更重要的是去理解redis的思想和每一种数据结构的用处和作用场景!
Redis.conf详解
配置文件 unit单位对大小写不敏感
包含文件、就好比我们学的spring 、import 、include 导入文件
bind 绑定ip
protected-mode yes #保护模式
port 6379 #端口设置
GENERAL #通用配置
daemonize yes #以守护进程的方式运行,默认是no
pidfile /var/run/redis_6379.pid #如果以后台方式运行,我们就需要指向一个pid文件!
默认 notice #生产环境
logfile "" #日志的文件路径名
databases 16 #默认16个数据库
always-show-logo no #是否总是显示LOGO
SNAPSHOTTING 快照 (持久化)
在规定的时间内,执行了多少操作,则会持久化一个文件,.rdb .aof 文件
redis是内存数据库,如果没有持久化,那么数据就会断电即失!
如果在3600秒内 至少有1个key进行了修改,我们就进行持久化操作
# save 3600 1
如果在300秒内 至少有100个key进行了修改,我们就进行持久化操作
# save 300 100
如果在60秒内 至少有10000个key进行了修改,我们就进行持久化操作
# save 60 10000
我们之后学习持久化,会定义这个测试!
stop-writes-on-bgsave-error yes #持久化如果出错,是否还需要工作
rdbcompression yes #是否压缩rdb文件,需要消耗cpu文件
rdbchecksum yes #保存rdb文件时,检查校验
dbfilename dump.rdb #rdb文件保存目录
REPLICATION 复制,~主从复制再扯
SECURITY 安全 默认无密码
CLIENTS 客户端
maxclients 10000 #最大客户端连接数量
maxmemory <bytes> #redis配置最大内存容量
maxmemory-policy noeviction #内存到达上线处理策略
redis 中的默认的过期策略是 volatile-lru
1、volatile-lru:只对设置了过期时间的key进行LRU(默认值)
2、allkeys-lru : 删除lru算法的key
3、volatile-random:随机删除即将过期key
4、allkeys-random:随机删除
5、volatile-ttl : 删除即将过期的
6、noeviction : 永不过期,返回错误
Redis持久化
Redis发布订阅
Redis主从复制(哨兵模式)
Redis缓存穿透和雪崩