Redis学习总结

NoSQL
-不仅仅是数据
-没有固定的查询语言
-键值对存储,列存储,文档存储,图形数据库
-最终一致性
CAP定理和BASE
高性能和高可用高扩展

大数据的时代的三高
1.高并发
2.高可拓
3.高性能
大数据时代的3v
1.海量
2.多样
3.实时
真正在公司实践 NoSQL+RDBMS

1.商品的基本信息
名称、价格、商家信息
关系型数据库就可以解决了!mysql
2.商品的描述。评论(文字较多)
文档型数据库中。MongoDB
3.图片
分布式文件系统FastDFS
淘宝自己的TFS
google GFS
hadoop hdfs
阿里云 oss
4.商品的关键字(搜索)
-搜索引擎 solr elasticseatch
iseatch 布隆
商品热门的波段信息
内存数据库
Redis Tair Memche
商品的交易,外部的支付接口
三方应用

大型互联网应用问题:

  • 数据类型太多了!
  • 数据源繁多,经常重构!
  • 数据要改造,大面积改造?

NoSQL的四大分类

KV键值对:

  • 新浪:Redis
  • 美团:Redis+Tair
  • 阿里、百度:Redis+memecache

文档型数据库(bson格式和json一样)

  • MongoDB(一般必须掌握)是一个基于分布式文件存储的数据库,c++编写,主要用来处理大量文档
  • MongonDB是一个介于关系型数据库和非关系型数据库中间的产品MongonDB是非关系型数据库中功能最丰富,最像关系型数据库!
  • Conth

列存储
Hbase
分布式文件系统

何谓Redis

Redis(Remote Dictionary Server ),即远程字典服务

Redis能干嘛

1、内存存储、持久化,内存中断电即失、所以说持久化很重要rdb、aof
2、效率高,用于高速缓存
3、发布订阅系统
4、地图信息分析
5、

Windows安装

ping测试连接
set基本数值 key value
get key 获取值

Centos安装

先装c++环境

yum install gcc-c++

make
make intall

Redis的默认安装路径 /usr/local/bin
demolize 设置成yes

[root@admin bin]# pwd
/usr/local/bin
[root@admin bin]# redis-server config/redis.conf
10014:C 06 Jun 2021 09:47:07.965 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
10014:C 06 Jun 2021 09:47:07.965 # Redis version=5.0.12, bits=64, commit=00000000, modified=0, pid=10014, just started
10014:C 06 Jun 2021 09:47:07.965 # Configuration loaded
[root@admin bin]# redis-cli -p 6379 使用redis客户端进行连接
127.0.0.1:6379> 
127.0.0.1:6379> set name jackz
OK
127.0.0.1:6379> get jackz
(nil)
127.0.0.1:6379> get name
"jackz"
127.0.0.1:6379> keys *
1) "name"

查看Redis进程是否开启

# ps -ef|grep redis
root      10015      1  0 09:47 ?        00:00:00 redis-server 127.0.0.1:6379
root      10033   2562  0 09:48 pts/0    00:00:00 redis-cli -p 6379
root      10134  10084  0 09:53 pts/1    00:00:00 grep --color=auto redis

开启redis服务

 redis-server config/redis.conf

如何关闭redis

shutdown
exit

后面我们会使用redis进行集群测试

测试性能

redis-benchmark是一个压力测试工具!
管方自带的性能测试工具!
redis-benchmark命令参数
![image.png](https://img-blog.csdnimg.cn/img_convert/47792f06248f95ddfeced1dbb2065c91.png#clientId=uf1878a8c-6e05-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=655&id=u77dc551b&margin=[object Object]&name=image.png&originHeight=655&originWidth=712&originalType=binary&ratio=1&rotation=0&showTitle=false&size=51273&status=done&style=none&taskId=u9971d659-18f1-453f-99f6-7e9b807e4c6&title=&width=712)
我们来简单测试下
100个并发 10000个请求

redis-benchmark -h localhost -p 6379 -c 1 -n 10000

![image.png](https://img-blog.csdnimg.cn/img_convert/6b251a1eaac12e313198dc2b7094dc8a.png#clientId=uf1878a8c-6e05-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=767&id=u032a95e3&margin=[object Object]&name=image.png&originHeight=767&originWidth=807&originalType=binary&ratio=1&rotation=0&showTitle=false&size=146481&status=done&style=none&taskId=u34c668c4-2d8d-410b-b9af-4e55f8ceca8&title=&width=807)
如何查看这些分析呢?
![image.png](https://img-blog.csdnimg.cn/img_convert/b59bea6e3a7e4f61d5db6f697751dbce.png#clientId=uf1878a8c-6e05-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=244&id=u1aada11e&margin=[object Object]&name=image.png&originHeight=244&originWidth=777&originalType=binary&ratio=1&rotation=0&showTitle=false&size=48044&status=done&style=none&taskId=u5637ced6-3376-4a38-a15f-958815aeff9&title=&width=777)

redis有十六个特数据库 默认是第0个数据库
可以用sellect进行数据库切换

127.0.0.1:6379> select 3
OK
127.0.0.1:6379[3]> dbsize
(integer) 0
127.0.0.1:6379[3]> 
127.0.0.1:6379[3]> set name zzjj
OK
127.0.0.1:6379[3]> select 7
OK
127.0.0.1:6379[7]> get name
(nil)
127.0.0.1:6379[7]> 
127.0.0.1:6379[3]> keys *查看当前关键字
1) "name"
127.0.0.1:6379[3]> flushdb清楚当前库关键字
OK
127.0.0.1:6379[3]> keys *
(empty list or set)
127.0.0.1:6379[3]> 
FLUSHALL清空全部数据据库

明白Redis是很快的官方表示Redis时就与内存操作cpu不是Redis性能瓶颈redis的平静是根据机器的内存和网络贷款既然可以时候用但像成实现九四用但像成了所有就似乎用了单线程redisshic语言写的官方提供的数据为100000qpf完全不必同样是使用ket-valle的memecache差
redis为什么但形成还这么块
误区 高性能的服务器一定是多项城的?
误区 多线程一定比单线程效率搞?
核心:redis是将所有的数据全部放在内存中的所以说使用单线程操作i笑傲率就是最好的多线程队友内存系统来说如果没有上限问切换效率就是最搞得

redis key

String

exists name
(integer) 1 是否存在关键字

move name 1 从1好数据库去掉name

expire name 10设置多少秒之后失效 设置key的过期时间
(integer) 1
127.0.0.1:6379> ttl name 查看当前key的剩余时间
(integer) 4
127.0.0.1:6379> ttl name
(integer) 1
127.0.0.1:6379> ttl name
(integer) 0
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379>
type age 查看key类型给
string

127.0.0.1:6379> set key1 v1
OK
127.0.0.1:6379> get key1
“v1”
127.0.0.1:6379> kyes *
(error) ERR unknown command kyes, with args beginning with: *,
127.0.0.1:6379> keys *

  1. “age”
  2. “key1”
    127.0.0.1:6379> exists key1
    (integer) 1
    127.0.0.1:6379> append key1 hello 在字符串后面在拼上字符穿 如果当前 key不存在就相当于set key
    (integer) 7
    127.0.0.1:6379> get key1
    “v1hello”
    127.0.0.1:6379> strlen key1获取字符串长度
    (integer) 7

set views 0
OK
127.0.0.1:6379> get views
“0”
127.0.0.1:6379> incr views 自增一
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> get views
“2”
127.0.0.1:6379> decr views自减一
(integer) 1
127.0.0.1:6379> incrby views 10 增加10个
(integer) 11
127.0.0.1:6379> decrby views 10 减少10 个
(integer) 1

127.0.0.1:6379> set key1 “hello,zhangsan” 设置key1的值
OK
127.0.0.1:6379> get key1
“hello,zhangsan”
127.0.0.1:6379> getrange key1 0 3
“hell” 截取字符串[0,3]
127.0.0.1:6379> getrange key1 0 -1
“hello,zhangsan” 获取全部字符串

127.0.0.1:6379> set key2 abcdefg
OK
127.0.0.1:6379> get key2
“abcdefg”
127.0.0.1:6379> setrange key2 1 xx 替换指定位置开始的字符串
(integer) 7
127.0.0.1:6379> get key2
“axxdefg”
127.0.0.1:6379>

setex (set with expire) 设置过期时间
setnx (set ) 不存在设置

127.0.0.1:6379> setex key3 30 hellllo 设置key3的值未helllo 30秒后过期
OK
127.0.0.1:6379> ttl key3
(integer) 25
127.0.0.1:6379> ttl key3
(integer) 23
127.0.0.1:6379> ttl key3
(integer) 22
127.0.0.1:6379> ttl key3
(integer) 21
127.0.0.1:6379> ttl key3
(integer) 3
127.0.0.1:6379> ttl key3
(integer) 1
127.0.0.1:6379> ttl key3
(integer) -2
127.0.0.1:6379> get key3
(nil)
127.0.0.1:6379> setnx mykey "redis"如果mykey不存在创建mykey
(integer) 1
127.0.0.1:6379> setnx mykey mongodb 如果mykey存在创建失败
(integer) 0
127.0.0.1:6379> get mykey
“redis”

127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 同时设置多个值
OK
127.0.0.1:6379> keys *

  1. “k3”
  2. “mykey”
  3. “key2”
  4. “key1”
  5. “k2”
  6. “k1”
    127.0.0.1:6379> mget k1 k2 k3
  7. “v1”
  8. “v2”
  9. “v3”
    127.0.0.1:6379> mset k1 v1 k4 v4
    OK
    127.0.0.1:6379> get k4
    “v4”
    127.0.0.1:6379> msetnx key v1 k5 v5
    (integer) 1
    127.0.0.1:6379> msetnx key1 v1 k6 v6 是一个原子操作要么一起成功要么一起失败
    (integer) 0
    127.0.0.1:6379>

对象

这里的key是巧妙地设计 user:{id}:{filed}如此设计在REdis中是完全ok的
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age

  1. “zhangsan”
  2. “2”
    127.0.0.1:6379>

getset db redis 如果不存在值则放回nil
(nil)
127.0.0.1:6379> get db
“redis”
127.0.0.1:6379> getset db mogondb 如果存在获取原来的值 并设置新的值
“redis”
127.0.0.1:6379>

数据结构是相同的,未来的话,jedis
在redis中,我们可以把list完成站队列阻塞队列

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

127.0.0.1:6379> lpush list one 将一个值或多个值插入到列表头部
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange 0 -1
(error) ERR wrong number of arguments for ‘lrange’ command
127.0.0.1:6379> lrange list 0 -1

  1. “three”
  2. “two”
  3. “one”
    127.0.0.1:6379> lrange list 0 1
  4. “three”
  5. “two”

127.0.0.1:6379> rpush list right 放到列表的尾部了
(integer) 4
127.0.0.1:6379> lrange list 0 1

  1. “three”
  2. “two”
    127.0.0.1:6379> lrange list 0 -1
  3. “three”
  4. “two”
  5. “one”
  6. “right”

127.0.0.1:6379> lrange list 0 -1

  1. “three”
  2. “two”
  3. “one”
  4. “right”
    127.0.0.1:6379> lpop list 移除列表的第一个
    “three”
    127.0.0.1:6379>
    127.0.0.1:6379> rpop list 移除列表的末尾一个
    “right”
    127.0.0.1:6379> lrange list 0 -1
  5. “two”
  6. “one”

lindex
127.0.0.1:6379> lindex list 1 通过下标获取值
“one”
127.0.0.1:6379> lindex list 0
“two”

127.0.0.1:6379> lpush list one
(integer) 3
127.0.0.1:6379> lpush list two
(integer) 4
127.0.0.1:6379> lpush list three
(integer) 5
127.0.0.1:6379> llen list 获取长度
(integer) 5

移除

127.0.0.1:6379> lrem list 1 one 移除list中指定个数的value
(integer) 1
127.0.0.1:6379> lrange list 0 -1

  1. “three”
  2. “two”
  3. “two”
  4. “one”
    127.0.0.1:6379> lrem list 2 two
    (integer) 2
    127.0.0.1:6379> lrange list 0 -1
  5. “three”
  6. “one”

127.0.0.1:6379> rpush mylist hello
(integer) 1
127.0.0.1:6379> rpush mylist hello1
(integer) 2
127.0.0.1:6379> rpush mylist hello2
(integer) 3
127.0.0.1:6379> rpush mylist hello3
(integer) 4
127.0.0.1:6379> ltrim mylist 1 2 通过下表截取指定长度的下表,这个list已经改变了阶段了只剩下截取的元素
OK
127.0.0.1:6379> lrange mylist 0 -1

  1. “hello1”
  2. “hello2”

127.0.0.1:6379> rpush mylist hello
(integer) 1
127.0.0.1:6379> rpush mylist hello1
(integer) 2
127.0.0.1:6379> rpush mylist hello2
(integer) 3
127.0.0.1:6379> rpoplpush mylist myohterlist 移除列表最后一个元素并将它移动到新的列表中
“hello2”
127.0.0.1:6379> lrange mylist 0 -1

  1. “hello”
  2. “hello1”
    127.0.0.1:6379> lrange myotherlist 0 -1查看原来的列表
    (empty list or set)
    127.0.0.1:6379> keys *
  3. “mylist”
  4. “myohterlist”
    127.0.0.1:6379> lrange myohterlist 0 -1 查看目标列表,确实存在值
  5. “hello2”

127.0.0.1:6379> lset list 0 item 如果不存在列表我们去更新就会报错
(error) ERR no such key
127.0.0.1:6379> lpush list value1
(integer) 1
127.0.0.1:6379> lset list 0 item 如果存在更新当前下标值
OK
127.0.0.1:6379> lrange list 0 0

  1. “item”
    127.0.0.1:6379> lset list 1 other 如果不存在则会报错
    (error) ERR index out of range

将某个具体的value插入到列表中某个元素的前面或后面

127.0.0.1:6379> rpush mylist hello
(integer) 1
127.0.0.1:6379> rpush mylist world
(integer) 2
127.0.0.1:6379> linsert mylist before “world” “other”
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1

  1. “hello”
  2. “other”
  3. “world”

set

127.0.0.1:6379> sadd myset hello set集合中添加元素
(integer) 1
127.0.0.1:6379> sadd myset zhangsan
(integer) 1
127.0.0.1:6379> sadd myset lovezhangsan
(integer) 1
127.0.0.1:6379> smembers myset 查看指定set 中所有元素

  1. “lovezhangsan”
  2. “zhangsan”
  3. “hello”
    127.0.0.1:6379> sismember myset hello 查看hello’元素是否存在
    (integer) 1
    127.0.0.1:6379> sismember myset worlld 查看world是否存在
    (integer) 0

获取set集合中元素个数

127.0.0.1:6379> scard myset
(integer) 3

移除set中指定元素

127.0.0.1:6379> srem myset hello
(integer) 1
127.0.0.1:6379> scard myset
(integer) 2
127.0.0.1:6379> sismember myset hello
(integer) 0
127.0.0.1:6379> smembers myset

  1. “lovezhangsan”
  2. “zhangsan”

127.0.0.1:6379> srandmember myset 随机抽选出一个元素
“lovezhangsan”
127.0.0.1:6379> srandmember myset 2 随机抽选出指定个数的元素
“lovezhangsan”
127.0.0.1:6379> srandmember myset
“zhangsan”

随机删除key

127.0.0.1:6379> spop myset 随机删除key
“zhangsan2”
127.0.0.1:6379> smembers myset

  1. “lovezhangsan”
  2. “zhangsan”
    127.0.0.1:6379> spop myset
    “zhangsan”

将一个指定的值移动到另一个集合中

127.0.0.1:6379> sadd myset hello
(integer) 1
127.0.0.1:6379> sadd myset world
(integer) 1
127.0.0.1:6379> sadd myset zhangsan
(integer) 1
127.0.0.1:6379> sadd myset2 set2
(integer) 1
127.0.0.1:6379> smembers myset

  1. “world”
  2. “zhangsan”
  3. “hello”
    127.0.0.1:6379> smove myset myset2 zhangsan
    (integer) 1
    127.0.0.1:6379> smembers myset2
  4. “set2”
  5. “zhangsan”

交集 并集 差集

127.0.0.1:6379> sadd key1 a
(integer) 1
127.0.0.1:6379> sadd key1 b
(integer) 1
127.0.0.1:6379> sadd key1 c
(integer) 1
127.0.0.1:6379> sadd key2 c
(integer) 1
127.0.0.1:6379> sadd key2 d
(integer) 1
127.0.0.1:6379> sadd key2 e
(integer) 1
127.0.0.1:6379> sdiff key1 key2 差集

  1. “a”
  2. “b”
    127.0.0.1:6379> sinter key1 key2交集
  3. “c”
    127.0.0.1:6379> sunion key1 key2并集
  4. “e”
  5. “b”
  6. “c”
  7. “d”
  8. “a”

微博 a用户将所有关注的人放在一个set集合中将他的粉丝也放在同一个集合中

hash

map集合 keymap 时候这个值是一个map集合set myhash field 张三
本质和string类型没有太大区别还是一个简单的key-value

127.0.0.1:6379> hset myhash field1 zhangsan set一个具体的key -value
(integer) 1
127.0.0.1:6379> hget myhash field1
“zhangsan”
127.0.0.1:6379> hmset myhash field1 hello field2 world set多个key --value
OK
127.0.0.1:6379> hmget myhash field1 field2 获取多个字段值

  1. “hello”
  2. “world”
    127.0.0.1:6379> hgetall myhash获取全部数据
  3. “field1”
  4. “hello”
  5. “field2”
  6. “world”

127.0.0.1:6379> hdel myhash field1 删除hash指定key的字段 对应的vallue值也消失了
(integer) 1
127.0.0.1:6379> hgetall myhash

  1. “field2”
  2. “world”

127.0.0.1:6379> hgetall myhash

  1. “field2”
  2. “world”
  3. “field1”
  4. “hello”
    127.0.0.1:6379> hlen myhash 获取hash表的字段数量
    (integer) 2

127.0.0.1:6379> hexists myhash field1 判断hash中指定字段是否存在
(integer) 1
127.0.0.1:6379> hexists myhash field3
(integer) 0
127.0.0.1:6379> hkeys myhash只获得所有field

  1. “field2”
  2. “field1”
    127.0.0.1:6379> hvals myhash 只获得所有value
  3. “world”
  4. “hello”

incr indecr

127.0.0.1:6379> hset myhash field3 5
(integer) 1
127.0.0.1:6379> hincrby myahsh field3 1 指定增i昂
(integer) 1
127.0.0.1:6379> hincrby myahsh field3 -1
(integer) 0
127.0.0.1:6379> hsetnx myhash field4 hello 如果不存在则可以设置
(integer) 1
127.0.0.1:6379> hsetnx myhash field4 world 如果存在则不能设置
(integer) 0

hash变更的数据user name age

Zset 有序集合

在set的基础上增加一个值 set k1 v1 k2 v2

127.0.0.1:6379> zadd myset 1 one 添加一个值
(integer) 1
127.0.0.1:6379> zadd myset 2 two 3 three 添加多个值
(integer) 2
127.0.0.1:6379> zrange myset 0 -1

  1. “one”
  2. “two”
  3. “three”

排序如何实现

127.0.0.1:6379> zadd salary 2500 xiaohong 添加三个用户薪水
(integer) 1
127.0.0.1:6379> zadd salary 5000 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 500 kuangshen
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf 排序从最小到最大

  1. “kuangshen”
  2. “xiaohong”
  3. “zhangsan”
    127.0.0.1:6379> zrangebyscore salary -inf +inf withscores显示所有用户并且附带成绩
  4. “kuangshen”
  5. “500”
  6. “xiaohong”
  7. “2500”
  8. “zhangsan”
  9. “5000”
    127.0.0.1:6379> zrangebyscore salary -inf 2500 withscores 显示工资小于2500员工的降序排序
  10. “kuangshen”
  11. “500”
  12. “xiaohong”
  13. “2500”

移除rem中的元素

127.0.0.1:6379> zrem salary xiaohong移除指定元素
(integer) 1
127.0.0.1:6379> zrange salary 0 -1

  1. “kuangshen”
  2. “zhangsan”
    127.0.0.1:6379> zcard salary获取个数
    (integer) 2

127.0.0.1:6379> zadd myset 1 hello 2 world 3 zhangsan
(integer) 3
127.0.0.1:6379> zcount myset 1 3 获取指定区间的成员个数
(integer) 3
127.0.0.1:6379> zcount myset 1 2
(integer) 2

三种特殊的数据类型

geospatiall地理位置
朋友定位 附近的人 打车位置

添加地点  经度纬度 名称

参数key 值

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
(integer) 1
127.0.0.1:6379> geoadd china:city  114.05 22.52 shenzhen
(integer) 1

获得当前定位

127.0.0.1:6379> geopos china:city beijing

    1. “116.39999896287918091”
    2. “39.90000009167092543”

127.0.0.1:6379> geodist china:city beijing shanghai 获取两城市之间距离长度
“1067378.7564”
127.0.0.1:6379> geodist china:city beijing shanghai km
“1067.3788”
127.0.0.1:6379> geodist china:city beijing chongqing
“1464070.8051”
127.0.0.1:6379> geodist china:city beijing chongqing km
“1464.0708”

我附近的人?
georadius已给定的经纬为中心某一半径画园(用的坐标)

127.0.0.1:6379> georadius china:city 110 30 500 km

  1. “chongqing”
    127.0.0.1:6379> georadius china:city 110 30 500 km withdist 带着距离
    1. “chongqing”
    2. “341.9374”

这个是指定某一城市周为多少千米有多少城市

127.0.0.1:6379> georadiusbymember china:city beijing 1000 km

  1. “beijing”
    127.0.0.1:6379> georadiusbymember china:city beijing 2000 km
  2. “chongqing”
  3. “shenzhen”
  4. “shanghai”
  5. “beijing”

127.0.0.1:6379> geohash china:city beijing chongqing 将二维的字符串转为一维空间的距离

  1. “wx4fbxxfke0”
  2. “wm5xzrybty0”

geo底层原理就是zset我们可以用zset的命令来操作geo

hyperloglog

什么是基数
集合中不重复的元素
网站的uv(一个人访问多次网站还是一个人访问的**)**
传统的方式set保存用户id然后就可以统计set的元素个数来统计
记录大量的id会很费劲我们的目的是为了计数不是为了存id

127.0.0.1:6379> pfadd mykey a b c d e f g h i j 创建第一组元素
(integer) 1
127.0.0.1:6379> pfcount mykey 统计mykey基数的数量
(integer) 10
127.0.0.1:6379> pfadd mykey2 i j z x c b n m 创建第二组元素mykey2
(integer) 1
127.0.0.1:6379> pfcount mykey2
(integer) 8
127.0.0.1:6379> pfmerge mykey3 mykey mykey2 合并mykey1和mykey2=>mykey3
OK
127.0.0.1:6379> pfcount mykey3
(integer) 14

如果允许容错,那么一定使用hyperloglog
如果不允许容错,那么使用set或自定义数据类型

位存储Btimaps

打卡 ,统计用户信息,活跃不活跃
使用bitmaps记录打卡天数
周一 1 周二 0 周三 。。。。。

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 6
(integer) 0
127.0.0.1:6379> getbit sign 3
(integer) 1

统计操作打卡天数

127.0.0.1:6379> bitcount sign
(integer) 3

Redis的事务

开启事务 multi
命令入队
执行事务 exec
锁:

正常执行事务

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 获取不到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” 其他命令可以运行

监控,watch

悲观锁:什么时候对会出问题,无论做什么都要加锁
乐观锁:什么时候都不会出现问题,所以不会加锁,更新数据要去判断一下,是否有人修改过这个数据version
获取version
更新的时候比较version

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
    127.0.0.1:6379>

Jredis

使用java操作redis

1.导入对应的依赖

<dependencies>
<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**>

</dependencies>

2.编码测试
连接数据库
操作命令
断开连接

远程连接

![image.png](https://img-blog.csdnimg.cn/img_convert/3ac34dcb18485cecb0d5d896215954b0.png#clientId=u66235aab-2136-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=407&id=ua6517a8d&margin=[object Object]&name=image.png&originHeight=407&originWidth=948&originalType=binary&ratio=1&rotation=0&showTitle=false&size=297993&status=done&style=none&taskId=u819277fd-47ff-458e-ac0c-fa9de8afcb5&title=&width=948)

一,在redis开发中遇到下面的错误

Exception in thread “main” redis.clients.jedis.exceptions.JedisConnectionException: Failed connecting to host XXXX:6379 at redis.clients.jedis.Connection.connect(Connection.java:204) at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:100) at redis.clients.jedis.Connection.sendCommand(Connection.java:125) at redis.clients.jedis.Connection.sendCommand(Connection.java:120) at redis.clients.jedis.BinaryClient.multi(BinaryClient.java:523) at redis.clients.jedis.BinaryJedis.multi(BinaryJedis.java:1877) at com.redis.TestTX.main(TestTX.java:19) Caused by: java.net.SocketTimeoutException: connect timed out at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at redis.clients.jedis.Connection.connect(Connection.java:181) … 6 more

二,解决办法
1)修改配置文件
注释掉bind,protected-mode为no
![](https://img-blog.csdnimg.cn/img_convert/44190950a27c655ca26b87fd42d2936d.png#clientId=ub6f7b20a-c8cb-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ud6fea3fa&margin=[object Object]&originHeight=592&originWidth=993&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u2aad94de-8bd1-4830-a9cc-f9aba4a5859&title=)
2)查看远程服务器的防火墙状态
systemctl status firewalld
![](https://img-blog.csdnimg.cn/img_convert/c54ad77af215c7bbd8e14d02b3d8117f.png#clientId=ub6f7b20a-c8cb-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u2f675079&margin=[object Object]&originHeight=259&originWidth=1195&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u38d82cf5-566c-4d92-96de-7fea667a410&title=)
防火墙为开启状态;
3)按照步骤执行一下命令
//查看防火墙状态
firewall-cmd --state

//开放6379端口
firewall-cmd --permanent --add-port=6379/tcp
//查看端口,执行
firewall-cmd --permanent --query-port=6379/tcp
firewall-cmd --permanent --list-ports //重启防火墙 firewall-cmd --reload
4)重启redis
redis-cli -p 6379 shutdown
redis-server /opt/redis/back_config/redis.conf
注释:back_config是我存放redis.conf的地方,请根据自己的实际情况执行
5)测试一下连接是否成功
Jedis jedis = new Jedis(“IP”,6379); System.out.println(jedis.ping());
![](https://img-blog.csdnimg.cn/img_convert/b01c84acfdc5fec4b1d49885b4e31f64.png#clientId=ub6f7b20a-c8cb-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u46e78d9c&margin=[object Object]&originHeight=63&originWidth=619&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=uf4ac9272-5a81-4429-bf74-ef6f2a73081&title=)

Springboot整合

springboot操作数据:spring-data jpa mogondb
Springdata也是与springboot其名的项目

jedis采用的是直连,多个线程操作的话是不安全的,如果想要避免不安全 采用jedis pool连接池

lettuce采用netty实例可以在多个多个线程中共享,不存在线程不安全的的情况可以减少线程数量了,更像nio模式

1.导入依赖

<dependency>
<groupId>org.springframework.boot</groupId>

<**artifactId**>spring-boot-starter-data-redis

</artifactId>
</dependency>

2.配置连接

spring.redis.host=192.168.1.7
spring.redis.port
=**6379

**

3.测试
4

Redis.config

网络

bind 127.0.0.1 绑定的ip
protected-mode no 保护模式
port 6379 端口设置

通用

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 数据库的数量默认是16个
always-show-logo yes 是否总显示logo

快照

持久化,在规定的时间内,执行了多少次操作,则会持久化到文件 。rdb 。aof
redis是内存数据库如果没有持久化那么数据库断电即失

save 900 1
如果在900s内,如果至少一个key进行了修改,我们就进行持久化操作
save 300 10
如果300s内,如果进行了至少10key的修改,我们就进行持久化操作
save 60 10000
如果60内,如果进行了至少10000key的修改,我们就进行持久化操作
stop-writes-on-bgsave-error yes持久化如果出错,是否还要继续工作。

rdbcompression yes 是否压缩rdb文件,需要消耗cpu资源
rdbchecksum yes 保存rdb文件时进行校验
dir ./ rdb文件目录

安全

requirepass foobared 可以在这里设置密码 默认是没有密码的

限制客户端

maxclients 10000 能连接redis最大客户端数量
maxmemory 配置最大内存数量
maxmemory-policy noeviction 内存达到上线之后的处理策略

aof模式

appendonly no 默认是不开启这个模式
appendfilename “appendonly.aof” 持久化文件的名字
appendfsync everysec 每秒执行一次同步,可能会丢失这1s内的数据
always 每修改一次都执行一次
no 不同步

持久化之rdb操作

触发机制

1、save的规则满足的情况下,会自动触发rdb规则
2、执行flushall命令也会触发我们的rdb规则
3、推出redis,也会产生rdb规则
备份就会自动生成一个dump.rdb

如果恢复rdb文件

1、只需要将rdb文件放在我们redis启动目录就可以,redis启动时会检测dump。rdb回复其中的数据
2、查看需要存在的位置

config get dir
“dir”
/usr/local/bin 如果在这个目录下存在dump.rdb文件,启动就会自动恢复数据

AOF

默认是不开启的,需要手动配置将appendonly 改为yes

Redis发布订阅

![](https://img-blog.csdnimg.cn/img_convert/483bc67e4b24d5ad18284a4a58abf640.png#clientId=ud9b9b9df-1ec0-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u87edb7d0&margin=[object Object]&originHeight=198&originWidth=319&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u20b4da50-fc90-42e4-b2df-b882fb7bb84&title=)![](https://img-blog.csdnimg.cn/img_convert/63e12f1782d850e70539d744cd41a62a.png#clientId=ud9b9b9df-1ec0-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u5839ae1d&margin=[object Object]&originHeight=285&originWidth=315&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u6c7608ad-f964-4530-a3dd-1765e5cd869&title=)

Redis 发布订阅命令

下表列出了 redis 发布订阅常用命令:

序号命令及描述
1PSUBSCRIBE pattern [pattern …]

订阅一个或多个符合给定模式的频道。 |
| 2 | PUBSUB subcommand [argument [argument …]]

查看订阅与发布系统状态。 |
| 3 | PUBLISH channel message

将信息发送到指定的频道。 |
| 4 | PUNSUBSCRIBE [pattern [pattern …]]

退订所有给定模式的频道。 |
| 5 | SUBSCRIBE channel [channel …]

订阅给定的一个或多个频道的信息。 |
| 6 | UNSUBSCRIBE [channel [channel …]]

指退订给定的频道。 |

测试

![image.png](https://img-blog.csdnimg.cn/img_convert/82036e80d1a9d9544cfe6e761dab4d13.png#clientId=ud9b9b9df-1ec0-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=400&id=ud54c7247&margin=[object Object]&name=image.png&originHeight=580&originWidth=1685&originalType=binary&ratio=1&rotation=0&showTitle=false&size=121975&status=done&style=none&taskId=u6a38bbfe-167d-442f-8961-c8cf27703cc&title=&width=1162)

Redis集群环境搭建

127.0.0.1:6379> info replication 查看当前信息

Replication

role:master 角色master
connected_slaves:0没有从机
master_replid:2a3a4a2734336c14c38edcce25ad919ee795c96d
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

复制三个配置文件修改对应配置信息
1、端口
2、pid名字
3、log文件名字
4、dump.rdb名字

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值