资讯详情

Redis详解

Redis基本知识

redis-server #启动redis服务 

在这里插入图片描述

shutdown #停止redis服务 

redis-cli -p 6379 #使用redis连接客户端 

使用redis客户命令

keys * #查看所有key 

flushdb ##清空当前数据库的内容 
flushall ##清空所有数据库的内容 
select 3 #切换数据库 
DBSIZE #查看DB大小 

redis-benchmark性能测试

redis-benchmark -h localhost -p 6379 -c 100 -n 100000 

Redis是单线程!

官方表示,Redis基于内存操作,CPU不是Redis的性能瓶颈

Redis是C语言写的,官方数据是1万 的QPS,完全不同于同样的使用key-value的Memecache差!

1.误区1:高性能服务器必须多线程?

2.误区2:多线程(CPU一定比单线程效率高!

先去CPU>内存>了解硬盘的速度!

EXISTS name #判断当前情况Key是否存在 
move name 1 #移除当前Key 
EXPIRE name 10 #设置Key过期时间为10秒 
ttl name #查看当前key的过期时间 
type name #查看当前key的类型 

String(字符串)

set key1 v1 #设置值 
get key1 #获得值 
EXISTS name #判断当前情况Key是否存在 
APPEND key1 "hello" #添加字符串,如果目前key不存在,相当于setkey 
STRLEN key1 #获取字符串的长度 
set views 0 #初始浏览量为0 
incr views #自增1 浏览量变为1 
decr views #自减1 浏览量变为0 
INCRBY views 10 #可设置步长,指定增量! 
#字符串范围 range  GETRANGE key1 0 3 #截取字符串 [0,3]  GETRANGE key1 0 -1 #截取所有字符串 (与get key1一样) 
#替换   SETRANGE key2 1 xx #替换指定位置开始的字符串! 
setex(set with expire) #设置过期时间 setnx(set if exist) #没有再设置 (常用于分布式)  setex key3 30 "hello" #设置key的值为hello,30秒后过期  setnx mykey "redis" #如果mykey不存在,创造mykey  setnx mykey "MongoDB" #如果mykey存在,创建m失败 
#mset  mget  mset k1 v1 k2 v2 k3 v3 #同时创建多个值  mget k1 v1 k2 v2 k3 v3 #同时获得多个值  msetnx k1 v1 k4 k4 #msetnx是原子操作,要么一起成功,要么一起失败 
#对象 set user:1 {name:zhangsan,age:3} #设置一个user:1 对象 值为json保存对象的字符!  mset user:1:name zhangsan user:1:age 2 #设置多个对象值  mget user:1:name user:1:age #获取多个对象值 
#getset  getset db redis #如果不存在,则返回nil,并设置值  getset db mongodb #如果存在值,获得原始值并设置新值 

List(列表)

LPUSH list one #将一个或多个值插入列表头部(左)  RPUSH list one #一个或多个值,插入列表头(右)  LRANGE list 0 -1 #获取list中值  LRANGE list 0 1 #获取list中具体的值  ########################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################  LPOP list #移除list第一个元素(左)  RPOP list #移除list第一个元素(右)  LINDEX list 0 #通过下标获得list一个值!  Llen list #返回列表长度  lrem list 1 three #移除list集合中指定个数的value,精确匹配 
#trim  ltrim mylist 1 2 #通过下标截取指定长度,此list已经改变,其他元素只被截取! 
#rpoplpush 将列表的最后一个元素移动到新列表中  rpoplpush mylist myotherlist #将列表的最后一个元素移动到新列表中 
lset #用另一个值替换列表中指定的标的值,更新操作  lset list 0 item 如果没有列表,我们会更新它们  lset list 0 item #如果存在,更新当前下表值 
linsert #特定的value插入列把你的元素的前面或后面!  linsert mylist before "world" "other" (前面)  linsert mylist after "world" "new" (后面) 

Set(无序无重复集合)

sadd myse "hello" #set集合中添加元素

SMEMBERS myset #查看指定set的所有值

SISMEMBER myset hello #判断某一个值是不是在set集合中

scard myset #获取set集合中内容元素个数

srem myset hello #移除set集合中的指定元素

srandmember myset #随机抽选出一个元素

srandmember myset 2 #随机抽选出指定个数的元素

spop myset #随机删除一些set集合中的元素

smove myset myset2 "kuangshen" #将一个指定的值移动到另外一个set集合中

SDIFF key1 key2 #差集

SINTER key1 key2 #交集 共同好友就可以这样实现

SUNION key1 key2 #并集

Hash

hset myhash field1 change #set一个具体key-value

hget myhash field1 #获取一个字段值

hmset myhash field1 change field2 hello #set多个key-value,如果value存在会被覆盖,与String同理

hmget myhash field1 field2 #获取多个字段值

hgetall myhash #获取全部的数据

hdel myhash field1 #删除hash指定的key字段,对应的value值也会随之消失

hlen myhash #获取hash表的字段数量

hexists myhash field1 #判断hash里的指定字段是否存在

hkeys myhash #只获得所有field

hvals myhash #只获得所有value

hset myhash field3 5 #指定增量

HINCRBY myhash field3 1 #为hash指定的字段增加数量

HINCRBY myhash field3 -1 #为hash指定的字段减少数量

hsetnx myhash field4 hello #如果不存在则可以设置

hsetnx myhash field4 world #如果存在则不能设置

hset user:1:name zhangsan user:1:age 2 #设置多个对象值

hget user:1:name user:1:age #获取多个对象值

Zset (有序集合)

zadd myset 1 one #添加一个值

zadd myset 1 one 2 two #添加多个值

zrange myset 0 -1 #获取所有的值

zrangebyscore salary -inf +inf #显示全部的用户 从小到大

zrevrange salary 0 -1 #显示全部的用户 从大到小

zrangebyscore salary -inf +inf withscores #显示全部的用户 并且附带工资

zrangebyscore salary -inf 2500 withscores #显示工资小于2500员工的升序排序

zrem salary change #移除有序集合中的指定元素

zcard salary #获取有序集合的个数

zcount myset 1 2 #获取指定区间的成员数量

三种特殊数据类型

geospatial 地理位置

GEOADD

# getadd 添加地理位置
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 150.45 22.23 chongqing 
(integer) 1

GEOPOS

127.0.0.1:6379> geopos china:city beijing #获取指定的城市的经度和纬度
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"

GEODIST

两人之间的距离!

单位:

· m 表示单位为米

· km 表示单位为千米

· mi 表示单位为英里

· ft 表示单位为英尺

127.0.0.1:6379> geodist china:city beijing shanghai km #查看上海到北京的直线距离
"1067.3788"

GEORADIUS

GEORADIUS china:city 121 31 1000 km #以121,31为中心,寻找方圆1000km内的城市
127.0.0.1:6379> georadius china:city 121 31 500 km
1) "shanghai"

georadius china:city 121 31 500 km withdist #显示到中间距离的位置
127.0.0.1:6379> georadius china:city 121 31 500 km withdist
1) 1) "shanghai"
   2) "51.5509"
   
georadius china:city 121 31 500 km withcoord #显示他人的定位信息
127.0.0.1:6379> georadius china:city 121 31 500 km withcoord
1) 1) "shanghai"
   2) 1) "121.47000163793563843"
      2) "31.22999903975783553"
      
georadius china:city 121 31 500 km withdist withcoord count 1
#筛选出指定的结果!
127.0.0.1:6379> georadius china:city 121 31 500 km withdist withcoord count 1
1) 1) "shanghai"
   2) "51.5509"
   3) 1) "121.47000163793563843"
      2) "31.22999903975783553" 

GEORADIUSBYMEMBER

#找出位于指定元素周围的其他元素!
georadiusbymember china:city beijing 1000 km
127.0.0.1:6379> georadiusbymember china:city beijing 1000 km
1) "beijing"                                                            

GEOHASH 命令 -返回一个或多个位置元素的GEOHASH表示

#将二维的经纬度转换为一维的字符串,如果两个字符串越接近,那么距离越近
geohash china:city beijing
127.0.0.1:6379> geohash china:city beijing
1) "wx4fbxxfke0"

GEO底层的实现原理其实就是Zset 我们可以使用Zset命令来操作GEO

zrange china:city 0 -1
127.0.0.1:6379> zrange china:city 0 -1
1) "shanghai"
2) "beijing"
3) "chongqing"

zrem china:city beijing #移除指定元素

Hypeloglog 统计不重复

PFADD mykey
PFADD mykey a b c d e f g h i j #创建第一组元素 mykey
PFCOUNT mykey #统计mykey并集数量
#因为第一组不存在重复的值,因此统计出的并集数量为10

PFADD mykey2 i j z x c v b n m #创建第二组元素 mykey2
PFCOUNT mykey2 #统计mykey2并集数量

PFNERGE mykey3 mykey mykey2 #使用mykey3将mykey和mykey2整合在一起并统计

PFOUNT mykey3 #再次统计并集数量

如果允许容错,那么一定可以使用Hypeloglog!

如果不允许容错,就使用set或者自己的数据类型即可!

Bitmap

位存储

统计用户信息,活跃,不活跃!登录、未登录!打卡、365打卡!两个状态的,都可以使用Bitmap!

Bitmap 位图,数据结构!都是操作二进制来进行记录,就只有0和1两个状态!

365 天 = 365 bit 1字节 = 8bit 46个字节左右!

使用bitmap来记录 周一到周日的打卡!
周一:1 周二:0 周三:0 周四:1 ...
127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 1 0
(integer) 0
127.0.0.1:6379> setbit sign 2 0
(integer) 0
127.0.0.1:6379> setbit sign 3 1
(integer) 0
127.0.0.1:6379> setbit sign 4 1
(integer) 0
127.0.0.1:6379> setbit sign 5 0
(integer) 0
127.0.0.1:6379> setbit sign 6 0
(integer) 0

查看某一天是否有打卡
127.0.0.1:6379> getbit sign 3
(integer) 1
127.0.0.1:6379> getbit sign 6
(integer) 0

统计操作,统计打卡的天数
127.0.0.1:6379> bitcount sign #统计这周的打卡记录,就可以看到是否有全勤!
(integer) 3

事务

执行事务

127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> exec #执行事务
1) OK
2) OK
3) OK

放弃事务

127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> discard #取消事务
OK
127.0.0.1:6379> get k4 #事务队列中命令都不会被执行!
(nil)

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

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> getset k3 #错误的命令
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> set k5 v5
QUEUED
127.0.0.1:6379> exec #执行事务,发现事务中有错误!
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k5 #所有的命令都没有被执行!
(nil)

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

127.0.0.1:6379> set k1 "v1"
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr k1 #会执行的时候失败!
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> get k3
QUEUED
127.0.0.1:6379> exec
1) (error) ERR value is not an integer or out of range #虽然第一条命令报错了,但是依旧正常执行成功了!
2) OK
3) OK
4) "v3"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379> get k3
"v3"

监控

悲观锁:

​ · 很悲观,认为什么时候都会出问题,无论做什么都会加锁!

乐观锁:

​ · 很乐观,认为什么时候都不会出问题,所以不会上锁!更新数据的时候去判断一下,在此期间是否有人修改过这个数据,

​ · 获取version

​ · 更新的时候比较 version

Redis测监视测试

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 #监视 money对象
OK
127.0.0.1:6379> multi #事务正常结束,数据期间没有发生变动,这个时候就正常执行成功!
OK
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
127.0.0.1:6379> exec
1) (integer) 80
2) (integer) 20

测试多线程修改值,使用watch当做redis的乐观锁操作!

127.0.0.1:6379> watch money #监视 money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 10
QUEUED
127.0.0.1:6379> incrby out 10
QUEUED
127.0.0.1:6379> exec #执行之前另外一个线程修改了我们的值,这个时候,就会导致事务执行失败
(nil)

如果修改失败,获取最新的值就好
127.0.0.1:6379> unwatch #如果大仙事务执行失败,就先解锁
OK
127.0.0.1:6379> watch money #获取最新的值,再次监视,select version
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> DECRBY money 1
QUEUED
127.0.0.1:6379> incrby money 1
QUEUED
127.0.0.1:6379> exec #对比监视的值是否发生了变化,如果没有变化,那么可以执行成功,如果变量就执行失败!
1) (integer) 999
2) (integer) 1000

Jedis (使用java来操作Redis)

测试

1.导入对应的依赖

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.2.0</version>
        </dependency>


        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>

2.编码测试

· 连接数据库

· 操作命令

· 断开连接

package com.change;

import redis.clients.jedis.Jedis;

public class TestPing { 
        
    public static void main(String[] args) { 
        
        Jedis jedis = new Jedis("127.0.0.1",6379);
        System.out.println(jedis.ping());

    }
}

输出:

PONG

常用的API

String

List

Set

Hash

Zset

SpringBoot整合

整合测试

1.导入依赖

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

2.配置连接

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

3.代码测试

@SpringBootTest
class Redis02SpringbootApplicationTests { 
        

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void contextLoads() { 
        
        //操作字符串
        redisTemplate.opsForValue().set("myk","change");
        System.out.println(redisTemplate.opsForValue().get("myk"));
    }

}

源码分析:

@Bean
    @ConditionalOnMissingBean(
        name = { 
        "redisTemplate"}
    )
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { 
        
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) { 
        
        return new StringRedisTemplate(redisConnectionFactory);
    }

关于对象的保存:

    @Test
    void test() throws JsonProcessingException { 
        
        User user = new User("change",18);
            String json = new ObjectMapper().writeValueAsString(user); //这条语句的意思是将对象序列化,没有这条语句会导致运行报错,
            redisTemplate.opsForValue().set("user",json);
            System.out.println(redisTemplate.opsForValue().get("user"));
    }

我们自己编写的RedisTempleat

@Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { 
        
        RedisTemplate<String, Object> template = new RedisTemplate<String,Object>();
        template.setConnectionFactory(redisConnectionFactory);
        //配置具体的序列化方式
        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);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        template.setKeySerializer(stringRedisSerializer);

        template.setHashKeySerializer(stringRedisSerializer);

        template.setValueSerializer(jackson2JsonRedisSerializer);

        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        template.afterPropertiesSet();
        
        return template;

Redis.conf详解

单位

1.配置文件 unit单位 对大小写不敏感

包含

可以使用多个配置文件

网络

bind 127.0.0.1 #绑定的ip
protected-mode yes #保护模式
port 6379 #端口

通用 GENERAL

daemonize yes #以守护进程的方式运行,默认是no,我们需要自己手动改为yes

pidfile /var/run/redis_6379.pid #如果以后台的方式运行,我们就需要指定一个pid文件

# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel notice #日志级别

logfile "" #日志的文件位置名

databases 16 #数据库的数量

always-show-logo yes #是否总是显示log

快照

持久化,在规定的时间内,执行了多少次操作,则会持久化到文件.rdb .aof

redis是内存数据库,如果没有持久化,那么数据断电即失!

#如果900内,如果至少一个key进行了修改,我们将持久化操作
save 900 1
#如果300内,如果至少十个key进行了修改,我们将持久化操作
save 300 10
#如果60内,如果至少一万个key进行了修改,我们将持久化操作
save 60 10000

stop-writes-on-bgsave-error yes #持久化如果出错,是否还需要继续工作!

rdbcompression yes #是否压缩rdb文件,需要消耗一些cpu资源!

rdbchecksum yes #保存rdb文件的时候,进行错误的检查校验!

dir ./ #rdb文件保存的目录!

REPLICATION 复制

SECURITY 安全

可以在这里设置redis的密码,默认是没有密码!

127.0.0.1:6379> config set requirepass "123456" #设置redis的密码
ok
127.0.0.1:6379> config get requirepass #发现所有的命令都没有权限了
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth 123456 #使用密码进行登录
ok
127.0.0.1:6379> config get requirepass
1)"requirepass"
2)"123456"

CLIENTS 限制

maxclients 10000 #设置能连接上redis的最大客户端的数量

maxmemory <bytes> #redis 配置最大的内存容量

maxmemory-policy 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 模式 aof配置

appendonly no #默认是不开启aof模式的,默认是使用rdb方式持久化的,在大部分的情况下,rdb完全够用!
appendfilename "appendonly.aof" #持久化的文件的名字

# appendfsync always #每次修改都会 sync 消耗性能
appendfsync everysec #每秒执行一次 sync 可能会丢失1s的数据!
# appendfsync no #不执行sync,这个时候操

标签: k5连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台