06-Redis
2021-09-18 本文已影响0人
XAbo
一、Redis基础
NoSQL 数据库分类NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。是非关系型数据库的补充。
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。
- Redis 支持多种类型的数据结构,如字符串
string
,散列hashe
,列表list
,集合set
,有序集合sorted set
与范围查询,bitmap
,hyperloglog
和地理空间geospatial
索引半径查询。 - Redis 内置了复制replication,LUA脚本Lua scripting,LRU驱动事件LRU eviction,事务transactions和不同级别的磁盘持久化persistence, 并通过Redis哨兵Sentinel和自动分区Cluster提供高可用性high availability。
- Redis 是单线程的。
二、Redis数据存储类型
2.1 string
# 添加/修改数据
#key的设置约定
#表名:主键名:主键值:字段名
set key value
# 获取数据
get key
# 删除数据
del key
# 添加/修改多个数据
mset key1 value1 key2 value2
# 获取多个数据
get key1 key2
# 获取数据字符个数
strlen key
# 追加信息到原始信息后,若原始信息不存在则新建
append key value
#####string的扩展操作######
#设置数值数据增加指定范围的值
incr key
incrby key increment
incrbyfloat key increment
#设置数值数据减少指定范围的值
decr key
decrby key increment
#设置数据具有指定的生命周期
setex key seconds value
psetex key milliseconds value
key的命名规范
2.2 hash
hash类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性。但hash设计初衷不是为了存储大量对象而设计的,切记不可滥用,更不可将hash作为对象列表使用。
#添加/修改数据
hset key field value
#获取数据
hget key field
hgetall key
#删除数据
hdel key field1 [field2]
#添加/修改多个数据
hmset key field1 value1 field2 value2
#获取多个数据
hmget key field1 field2
#获取哈希表中字段的数量
hlen key
#获取哈希表中是否存在指定的字段
hexists key field
#####hash的扩展操作######
#获取哈希表中所有的字段名或字段值
hkeys key
hvals key
#设置指定字段的数值数据增加指定范围的值
hincrby key field increment
hincrbyfloat key field increment
hash存储场景1
hash存储场景2 hash存储场景优化1
hash存储场景优化2
redis存json数据时选择string还是hash
- 如果你的业务类型中对于缓存的读取缓存的场景更多,并且更新缓存不频繁(或者每次更新都更新json数据中的大多数key),那么选择string类型作为存储方式会比较好。
- 如果你的业务类型中对于缓存的更新比较频繁(特别是每次只更新少数几个键)时, 或者我们每次只想取json数据中的少数几个键值时,我们选择hash类型作为我们的存储方式会比较好。
2.3 list
#添加/修改数据
lpush key value1 [value2]
rpush key value1 [value2]
#获取数据
lrange key start stop
lindex key index
llen key
#获取并移除
lpop key
rpop key
######list扩展操作######
#规定时间内获取并移除数据
bloop key1 [key2] timeout
broop key1 [key2] timeout
#移除指定数据
lrem key count value
2.4 set
hash结构set结构
#添加数据
sadd key member1 [member2]
#获取全部数据
smembers key
#删除数据
srem key member1 [member2]
#获取集合数据总量
scard key
#判断集合中是否包含指定数据
sismember key member
#####set扩展操作#####
#随机获取集合中指定数量的数据
srandmember key [count]
#随机获取集合中的某个数据并将该数据移除集合
spop key
#求两个集合的交、并、差集
sinter key1 [key2]
sunion key1 [key2]
sdiff key1 [key2]
#求两个集合的交、并、差集并存储到指定集合中
sinterstore destination key1 [key2]
sunionstore destination key1 [key2]
sdiffstore destination key1 [key2]
#将指定数据从原始集合中移动到目标集合中
smove source destination member
2.5 sorted_ sets
image.pngimage.png
#添加数据
zadd key score1 member1 [score2] [member2]
#获取全部数据
zrange key start stop [withscores]
zrevrange key start stop [withscores]
#删除数据
zrem key member [member ...]
#按条件获取数据
zrangebyscore key min max [withscores] [limit]
zrevrangebyscore key max min [withscores]
#条件删除数据
zremrangeby key start stop
zremrangebyscore key min max
#获取集合数据总量
zcard key
zcount key min max
#集合交、并操作
zinterstore destination numkeys key [key ...]
zunionstore destination numkeys key [key ...]
#获取数据对应的索引
zrank key member
zrevrank key member
#score值获取与修改
zscore key member
zincrby key increment member
三、Redis通用指令
- key的操作
#删除指定的key
del key
#获取key是否存在
exists key
#获取key的类型
type key
##key的扩展操作###
#为指定key设置有效值
expire key seconds
pexpire key milliseconds
expireat key timestamp
pexpireat key milliseconds-timestamp
#获取key的有效时间
ttl key
pttl key
#切换key从时效性转换为永久性
persist key
#查询key
keys pattern
#key重命名
rename key newkey
renamex key newkey
#对所有key排序
sort
#其他key通用操作
help @genric
pattern
数据库
- 数据库的操作
#切换数据库
select index
#其他操作
quit
ping
echo message
#数据移动
move key db
#数据清除
dbsize
flushdb
flushall
四、jedis
连接池:
public final class RedisUtil {
//Redis服务器IP
private static String ADDR = "192.168.0.100";
//Redis的端口号
private static int PORT = 6379;
//访问密码
private static String AUTH = "admin";
//可用连接实例的最大数目,默认值为8;
//如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
private static int MAX_ACTIVE = 1024;
//控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
private static int MAX_IDLE = 200;
//等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
private static int MAX_WAIT = 10000;
private static int TIMEOUT = 10000;
//在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
private static boolean TEST_ON_BORROW = true;
private static JedisPool jedisPool = null;
/**
* 初始化Redis连接池
*/
static {
try {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxActive(MAX_ACTIVE);
config.setMaxIdle(MAX_IDLE);
config.setMaxWait(MAX_WAIT);
config.setTestOnBorrow(TEST_ON_BORROW);
jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, AUTH);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取Jedis实例
* @return
*/
public synchronized static Jedis getJedis() {
try {
if (jedisPool != null) {
Jedis resource = jedisPool.getResource();
return resource;
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 释放jedis资源
* @param jedis
*/
public static void returnResource(final Jedis jedis) {
if (jedis != null) {
jedisPool.returnResource(jedis);
}
}
}
基本操作:
public class TestRedis {
private Jedis jedis;
@Before
public void setup() {
//连接redis服务器,192.168.0.100:6379
jedis = new Jedis("192.168.0.100", 6379);
//权限认证
jedis.auth("admin");
}
/**
* redis存储字符串
*/
@Test
public void testString() {
//-----添加数据----------
jedis.set("name","xinxin");//向key-->name中放入了value-->xinxin
System.out.println(jedis.get("name"));//执行结果:xinxin
jedis.append("name", " is my lover"); //拼接
System.out.println(jedis.get("name"));
jedis.del("name"); //删除某个键
System.out.println(jedis.get("name"));
//设置多个键值对
jedis.mset("name","liuling","age","23","qq","476777XXX");
jedis.incr("age"); //进行加1操作
System.out.println(jedis.get("name") + "-" + jedis.get("age") + "-" + jedis.get("qq"));
}
/**
* redis操作Map
*/
@Test
public void testMap() {
//-----添加数据----------
Map<String, String> map = new HashMap<String, String>();
map.put("name", "xinxin");
map.put("age", "22");
map.put("qq", "123456");
jedis.hmset("user",map);
//取出user中的name,执行结果:[minxr]-->注意结果是一个泛型的List
//第一个参数是存入redis中map对象的key,后面跟的是放入map中的对象的key,后面的key可以跟多个,是可变参数
List<String> rsmap = jedis.hmget("user", "name", "age", "qq");
System.out.println(rsmap);
//删除map中的某个键值
jedis.hdel("user","age");
System.out.println(jedis.hmget("user", "age")); //因为删除了,所以返回的是null
System.out.println(jedis.hlen("user")); //返回key为user的键中存放的值的个数2
System.out.println(jedis.exists("user"));//是否存在key为user的记录 返回true
System.out.println(jedis.hkeys("user"));//返回map对象中的所有key
System.out.println(jedis.hvals("user"));//返回map对象中的所有value
Iterator<String> iter=jedis.hkeys("user").iterator();
while (iter.hasNext()){
String key = iter.next();
System.out.println(key+":"+jedis.hmget("user",key));
}
}
/**
* jedis操作List
*/
@Test
public void testList(){
//开始前,先移除所有的内容
jedis.del("java framework");
System.out.println(jedis.lrange("java framework",0,-1));
//先向key java framework中存放三条数据
jedis.lpush("java framework","spring");
jedis.lpush("java framework","struts");
jedis.lpush("java framework","hibernate");
//再取出所有数据jedis.lrange是按范围取出,
// 第一个是key,第二个是起始位置,第三个是结束位置,jedis.llen获取长度 -1表示取得所有
System.out.println(jedis.lrange("java framework",0,-1));
jedis.del("java framework");
jedis.rpush("java framework","spring");
jedis.rpush("java framework","struts");
jedis.rpush("java framework","hibernate");
System.out.println(jedis.lrange("java framework",0,-1));
}
/**
* jedis操作Set
*/
@Test
public void testSet(){
//添加
jedis.sadd("user","liuling");
jedis.sadd("user","xinxin");
jedis.sadd("user","ling");
jedis.sadd("user","zhangxinxin");
jedis.sadd("user","who");
//移除noname
jedis.srem("user","who");
System.out.println(jedis.smembers("user"));//获取所有加入的value
System.out.println(jedis.sismember("user", "who"));//判断 who 是否是user集合的元素
System.out.println(jedis.srandmember("user"));
System.out.println(jedis.scard("user"));//返回集合的元素个数
}
@Test
public void test() throws InterruptedException {
//jedis 排序
//注意,此处的rpush和lpush是List的操作。是一个双向链表(但从表现来看的)
jedis.del("a");//先清除数据,再加入数据进行测试
jedis.rpush("a", "1");
jedis.lpush("a","6");
jedis.lpush("a","3");
jedis.lpush("a","9");
System.out.println(jedis.lrange("a",0,-1));// [9, 3, 6, 1]
System.out.println(jedis.sort("a")); //[1, 3, 6, 9] //输入排序后结果
System.out.println(jedis.lrange("a",0,-1));
}
@Test
public void testRedisPool() {
RedisUtil.getJedis().set("newname", "中文测试");
System.out.println(RedisUtil.getJedis().get("newname"));
}
}
五、持久化
5.1RDB
RDB:当前快照会保存在XXX.rdb文件中。
save
指令:手动执行一次保存操作。
手动save配置
手动save原理
bgsave
指令:手动启动后台保存操作,但不是立即执行。
save second changes
指令:自动执行保存操作。
自动save
自动save的配置
自动save原理 三种RDB对比
RDB其他启动方式
RDB优缺点
5.2AOF
AOF:记录操作记录XXX.aof文件。
AOF写数据
AOF写数据的策略
AOP功能开启
AOP的问题
AOP的重写
AOP自动重写
AOP重写原理
AOP与RDB
六、事务
基本操作基本操作
工作流程
注意事项
锁
分布式锁
分布式锁的问题
解决方案
七、删除策略
时效性数据7.1 定时删除
定时删除7.2 惰性删除
惰性删除7.3 定期删除
定期删除7.4 逐出策略
逐出策略逐出算法
逐出配置
调优
八、redis基础配置
12
3
4
九、其他数据类型
bitmaps基础操作bitmaps扩展操作
bitmaps扩展操作
HyperLogLog基础操作
HyperLogLog说明
GEO基础类型
GEO基础类型
十、主从复制
10.1 前言
服务器串联主从复制简介
主从复制作用
10.2 主从复制流程
总述第一阶段
第一阶段:连接命令
第一阶段:断开命令
第一阶段:授权
第二阶段
第二阶段:master
第二阶段:slave
复制缓存区原理
第二和三阶段
全阶段
十一、哨兵
简介哨兵作用
配置哨兵
第一阶段
第二阶段
第三阶段:1
第三阶段:2
第三阶段:3
十二、集群
作用存储设计1
存储设计2
存储设计3
集群配置1
集群配置2