Redis学习-狂神教程

Redis

1.redis基础知识

切换数据库

select 3

查看数据库内存

DBSIZE

查看数据库所有的key

keys *

清空当前数据库内容

flushdb

清除所有数据库内容

flushall

2.redis五大数据类型

Redis-key

# 获取全部的key 
keys *
# 设置key-val
set name dhn
# 获取key对应的value
get name
# 移除key
move name 1
# 设置过期时间 10代表十秒
expire name 10
# 查看过期时间 (-2代表过期)
ttl name 
# 查看当前key的类型
type name
# 是否存在key
exists key

String类型

# 追加字符串,如果当前key不存在,相当于setkey
append key1 hello
# 自增
incr views
# 自减
decr views
# 设置步长
incrby views 10
decrby views 10
# 获取范围的字符串
getrange key1 0 3
# 替换字符串
setrange key2 1 xx
# setex (set with expire) 设置过期时间
# setnx (set if not exist) 如果不存在设置

# 设置多个key-value
mset k1 v1 k2 v2
# 获取多个
mget k1 k2

# 设计对象
mset user:1:name zhangsan user:1:age 18

# 先get再set,不存在值则为nil,如果存在先获取当前值再更改新值
getset db redis

List类型

所有的list命令都是用l开头

# 一个或多个插入列表头部
lpush list one
lpush list two
lpush list three
# 获取多个值
lrange list 0 -1 # 获取全部
# 从右边插入
rpush list right
# 从左边弹出
lpop list
# 从右边弹出
rpop list
# 用下标获取值
lindex list 0
# 获取长度
llen list
# 移除指定得值
lrem list 1 two # 移除一个two
# 截取值
ltrim list 1 2
# 移动列表的最后一个元素,将他移动到新的列表中
rpoplpush mylist myotherlist
# 将列表中指定下标的值替换为另外的值
lset list 0 item
# 在列表前后插入值
linsert list before/after   item2 item3

Set类型

不能重复添加

# 设置键值
sadd myset "hello"
# 读取
smembers myset
# 查看是否存在
sismember myset hello
# 获取元素个数
scard myset
# 移除某一个元素
srem myset hello
# 随机抽选一个元素
srandmember myset
# 随机移除元素
spop myset
# 将一个指定的值移动到另外的set中
smove myset myset2 hello
#################################
# 差集、交集、并集
sdiff key1 key2
sinter key1 key2
sunion key1 key2

Hash类型

Map集合,key-value

# 设置key value
hset myhash field1 dhn
# 获取值
hset myhash field1
# 设置多个key-value
hmset myhash field1 hello field2 world
# 获取多个key
hmget myhash field1 field2
# 获取hash中所有的key-value
hgetall myhash
# 删除指定的key字段
hrem myhash field1
# 获取长度
hlen myhash
# 判断hash中的指定字段是否存在
hexists myhash field2 
# 获取所有的字段和值
hkeys myhash
hvals myhash
# 自增
hincrby myhash field3 1
# 设置一个hash,如果不存在则创建
hsetnx myhash field4 hello 

Zset类型

有序集合,在set的基础上,增加了一个值,

# 设置值
zset myset 1 one
zset myset 2 two
# 获取某些下标的值
zrange myset 0 -1
# 获取范围的值
zadd salary 2500 zs
zadd salary 5000 ls
zadd salary 500 ww
zrangebyscore salary -inf +inf #获取所有的范围
# 读取带key的遍历范围,从小到大排序
zrangebyscore salary -inf +inf withscores
zrangebyscore salary -inf 5000 withscores
# 从大到小排序
zrevrange salary 0 -1 
# 移除指定元素
zrem salary zs
# 获取有序集合中的个数
zcard salary
# 计算区间变量的个数
zcount salary 2000 5000


3.Geospatial地理位置详解

# geoadd添加地理位置
127.0.0.1:6379> GEOADD china:city 116.40 39.90 beijing
(integer) 1
127.0.0.1:6379> GEOADD china:city 121.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> GEOADD china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen
(integer) 2
127.0.0.1:6379> GEOADD china:city 120.16 30.24 hangzhou 108.96 34.26 xian

# 获取指定城市的经度和纬度
geopos china:city shenzhen

# 返回两个给定位置之间的距离
GEODIST china:city beijing shanghai

# georadius以给定的经纬度为中心,找出某一半径内的元素
georadius china:city 110 30 1000 km
withdist:显示经度
withcoord:显示经度和纬度
count 1 限制查询一个

# georadiusbymember:找出指定范围内的元素,中心点是由给定的位置元素决定
georadiusbymember china:city shanghai 1000 km

4.redis事务

Redis事务本质:一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行!

一次性、顺序性、排他性

Redis事务没有隔离级别的概念

Redis单条命令保存原子性,但是事务不保证原子性

Redis事务:

  • 开启事务()
  • 命令入队()
  • 执行事务()

正常执行事务

127.0.0.1:6379> MULTI  #开启事务
OK
# 命令入队
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> get k2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> exec #执行事务
1) OK
2) OK
3) "v2"
4) OK

放弃事务

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> DISCARD # 放弃事务

编译型异常(代码有问题!命令有错!),事务中的所有命令都不会被执行

127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> getset  k3 #错误的命令
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
# 所有的命令都不会被执行

运行时异常(1/0),如果事务队列中存在语法性,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> incr k1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK

5.Redis实现乐观锁

监控:Watch

  • 悲观锁:什么时候都会出问题,无论做什么都会加锁
  • 乐观锁:认为什么时候都不回出现问题,所以不会加锁,更新数据的时候去判断一下,在此期间是否修改过这个数据

正常执行成功

127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> DECRBY money 20
QUEUED
127.0.0.1:6379(TX)> INCRBY out 20
QUEUED
127.0.0.1:6379(TX)> exec # 事务正常结束,数据期间没有发生变动,这个时候就正常执行成功
1) (integer) 80
2) (integer) 20

测试多线程,使用watch可以当作redis的乐观锁操作

unwatch #解除监视

6.Jedis

我Jedis是redis官方推荐的java连接开发工具!使用java操作redis中间件。

1.导入对应的依赖

<dependencies>
        <!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>4.4.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.10</version>
        </dependency>
 </dependencies>

2.编码测试

  • 连接数据库
  • 操作命令
  • 断开连接
    public static void main(String[] args) {
        Jedis jedis = new Jedis("192.168.31.97",6379);
        jedis.set("k1","v1");
        System.out.println(jedis.get("k1"));
    }

7.Springboot集成Redis

1.导入依赖

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

2.配置连接

spring.redis.host=192.168.21.131
spring.redis.port=6379

3.测试

@Test
void contextLoads() {
    redisTemplate.opsForValue().set("mykey","dhn");
    String mykey = (String) redisTemplate.opsForValue().get("mykey");
    System.out.println(mykey);
}

8.自定义RedisTemplate

@Configuration
public class RedisConfig {
    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        
        //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;
    }
}

测试

    @Test
    public void test01() throws JsonProcessingException {
        User user = new User("代浩楠", 24);
//        String jsonUser = new ObjectMapper().writeValueAsString(user);
        redisTemplate.opsForValue().set("user",user);
        System.out.println(redisTemplate.opsForValue().get("user"));
    }

8.Redis.conf详解

  • 大小写不敏感

img

  • 可以包含多个配置文件(即,这些文件导入到主配置文件 Redis.conf 中)

    img

  • 网络

     
    bind 0.0.0.0 # IP(默认127.0.0.1)
    protected-mode no # 保护模式(默认yes)
    port 6379 # 端口设置(默认6379)
    
  • 通用

     
    daemonize yes # 以守护进程方式运行,即后台运行(默认no)
     
    pidfile /var/run/redis_6379.pid # 如果以后台运行,必须指定一个pid文件
     
    # 日志
    # Specify the server verbosity level.
    # This can be one of:
    # debug (大量信息, 使用于测试或开发阶段)
    # verbose (许多很少有用的信息,但不像调试级别那样混乱)
    # notice (比较冗长,你可能想在生产环境中使用)
    # warning (只有非常重要/关键的消息被记录下来)
    loglevel notice # 默认notice
    logfile "" # 日志的文件位置名
     
    databases 16 # 数据库的数量(默认16)
    always-show-logo yes # 是否开启 logo (默认yes)
    
  • 持久化,在规定时间内,执行了多少次操作,会被持久化到文件(.rdb,.aof)

     
    save 900 1 # 900秒内(15分钟),如果至少有1个Key进行修改,我们就进行持久化操作
    save 300 10 # 300秒内(5分钟),如果至少有10个Key进行修改,我们就进行持久化操作
    save 60 10000 # 60秒内(1分钟),如果至少有10000个Key进行修改,我们就进行持久化操作
     
    stop-writes-on-bgsave-error yes # 持久化如果出错,是否还需要继续工作(默认yes)
     
    rdbcompression yes # 是否压缩rdb文件(默认yes),会消耗一些CPU资源
     
    rdbchecksum yes # 保存rdb文件时,进行错误检查检验
     
    dir ./ # rdb文件保存的目录
    
    requirepass 你的密码 # 设置密码(默认被注释着需要自己解开注释)
    
  • 安全 security

    requirepass 你的密码 # 设置密码(默认被注释着需要自己解开注释)
    

    当然可以通过命令行配置(临时,服务重启失效)

    img

  • 客户端限制

    # maxclients 10000 # 限制最多10000个客户端访问(默认注释)
    
  • 内存管理

     
    # maxmemory <bytes> # 最大内存设置(默认注释)
     
    # maxmemory-policy noeviction # 内存达到上限之后的处理策略(默认noeviction)
    # 1、volatile-lru:只对设置了过期时间的key进行LRU(默认值)
    # 2、allkeys-lru : 删除lru算法的key
    # 3、volatile-random:随机删除即将过期key
    # 4、allkeys-random:随机删除
    # 5、volatile-ttl : 删除即将过期的
    # 6、noeviction : 永不过期,返回错误
    
  • APPEND ONLY MODE (AOF配置)

     
    appendonly no # 默认是不开启aof的,默认使用rdb方式持久化
    appendfilename "appendonly.aof" # 持久化的文件名
     
    # appendfsync always # 每次修改都会同步,销耗性能
    appendfsync everysec # 每秒执行一次同步,可能会丢失这1秒的数据
    # appendfsync no # 不同步,操作系统自己同步数据,速度最快
    

    9.redis持久化

    1.RDB(Redis DataBase)

    RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。 保存文件格式 dump.rdb

    img

    设置RDB文件保存条件

    img

9.Redis订阅发布

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。微信、微博、关注系统!

Redis客户端可以订阅任意数量的频道

订阅/发布消息图:

下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:

当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:

命令
这些命令被广泛用于构建即时通信应用,比如网络聊天室(chatroom)和实时广播、实时提醒等。

在这里插入图片描述

测试

# 订阅端
SUBSCRIBE dhn
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "dhn"
3) (integer) 1
1) "message"
2) "dhn"
3) "hahhaha"
# 发布端
127.0.0.1:6379> publish dhn hahhaha
(integer) 1

10.Redis主从复制

概念

主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master/Leader),后者称为从节点(Slave/Follower), 数据的复制是单向的!只能由主节点复制到从节点(主节点以写为主、从节点以读为主)。

img

主从复制的主要作用

数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余的方式。
故障恢复:当主节点故障时,从节点可以暂时替代主节点提供服务,是一种服务冗余的方式
负载均衡:在主从复制的基础上,配合读写分离,由主节点进行写操作,从节点进行读操作,分担服务器的负载;尤其是在多读少写的场景下,通过多个从节点分担负载,提高并发量。
高可用基石:主从复制还是哨兵和集群能够实施的基础。

一般来说,要将Redis运用与工程项目中,只使用一台Redis是万万不能的(避免宕机,一主二从),原因如下:

从结构上,单个Redis服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大
从容量上,单个Redis服务器内存容量有限,就算一台Redis服务器内存容量为256G,也不能将所有内存用作Redis存储内存,一般来说,单台服务器最大使用内存不超过20G。

环境配置

只配置从库,不用配置主库

127.0.0.1:6379> info replication  # 查看当前库的信息
# Replication
role:master # 角色 master
connected_slaves:0  # 没有从机
master_failover_state:no-failover
master_replid:826a2581d6908aad3410e0f1b2f6dbd60ca4d6db
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余的方式。
故障恢复:当主节点故障时,从节点可以暂时替代主节点提供服务,是一种服务冗余的方式
负载均衡:在主从复制的基础上,配合读写分离,由主节点进行写操作,从节点进行读操作,分担服务器的负载;尤其是在多读少写的场景下,通过多个从节点分担负载,提高并发量。
高可用基石:主从复制还是哨兵和集群能够实施的基础。

一般来说,要将Redis运用与工程项目中,只使用一台Redis是万万不能的(避免宕机,一主二从),原因如下:

从结构上,单个Redis服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大
从容量上,单个Redis服务器内存容量有限,就算一台Redis服务器内存容量为256G,也不能将所有内存用作Redis存储内存,一般来说,单台服务器最大使用内存不超过20G。

环境配置

只配置从库,不用配置主库

127.0.0.1:6379> info replication  # 查看当前库的信息
# Replication
role:master # 角色 master
connected_slaves:0  # 没有从机
master_failover_state:no-failover
master_replid:826a2581d6908aad3410e0f1b2f6dbd60ca4d6db
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值