Redis学习笔记

Nosql概述:

NoSQL(Not Only SQL), "不仅仅是SQL",  泛指非关系型的数据库;
特点:
	易扩展;
	在大数据量下,NoSQL 数据库具有非常高的读写性能;
	多样灵活的数据模型;
RDBMS(关系型数据库)和NoSQL 比较:
	RDBMS:
		高度组织化结构化数据;
		结构化查询语言(SQL);
		数据和关系都存储在单独的表中;
		数据操作语言,数据定义语言;
		严格的一致性;
		基础事务;
	NoSQL:
		没有声明性查询语言;
		没有预定义的模式;
		键值对存储,列存储,文档存储,图形数据库;
		最终一致型,而非ACID属性;
		非结构化和不可预知的数据;
		CAP 定理;
		高性能,高可用性和可伸缩性,方便扩展;
	3V + 3高:
	大数据时代的3V(现象)
		海量(Volume)
		多样(Variety)
		实时(Velocity)
	互联网需求的3高(目的)
		高并发
		高可扩
		高性能
Nosql的数据模型:
	Bson:
		Bson 是一种类json的二进制形式的存储格式,即Binary JSON;
		支持内嵌的文档对象和数组对象;
	聚合模型:
		KV 键值
		Bson
		列族
		图形
	NoSQL 数据库的四大分类:
		KV键值: Redis等;
		文档型数据库(bson格式比较多): MongoDB,基于分布式文件存储的数据库;
		列存储数据库: HBase,分布式文件系统;
		图关系数据库: 存放社交网络,推荐系统等,专注于构建关系图谱;
在分布数据库中CAP原理
	CAP
		C:Consistency(强一致性)
		A:Availability(可用性)
		P:Partition tolerance(分区容错性)

CAP原理:

  1. CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时
    较好的满足两个;
  2. 分区容错性是必须要实现的;
  3. 根据CAP原理,将NoSQL数据库分成了满足CA原则,满足CP原则和满足AP原则三大类:
    • CA,单点集群,满足一致性,可用性的系统,通常在扩展性上不太强大;(传统Oracle数据库)
    • CP,满足一致性,分区容错性的系统,通常性能不是特别高;(Redis,Mongodb)
    • AP,满足可用性,分区容错性的系统,通常可能对一致性要求低一些;(大多数网站架构的选择)

img

BASE
	BASE 就是为了解决关系数据库强一致性引起的问题而引起的可用性降低,而提出的解决方案;
	BASE
		基本可用(Basically Available)
		软状态(Soft state)
		最终一致(Eventually consistent)
分布式:不同的多台服务器上面部署不同的服务模块(工程),它们之间通过Rpc/Rmi之间通信和调用,对外提供服务和组内协作;
集群:不同的多台服务器上面部署相同的服务模块,通过分布式调度软件进行统一的调度,对外提供服务和访问;

概述
Redis(Remote Dictionary Server ),即远程字典服务,
是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
持久化(rdb aof);
效率高,高速缓存;
发布订阅系统;
地图信息分析;
计时器计数器(浏览量);

安装:

2.打开cmd指令窗口
3.输入你刚才解压的文件路径
4.然后输入redis-server redis.windows.conf 命令

img

接下来部署Redis为windows下的服务 首先关掉上一个窗口再打开一个新的cmd命令窗口

然后输入指令redis-server --service-install redis.windows.conf

img

随后,进入右击此电脑–管理–服务和应用程序–服务 启动服务

img

Redis常用的指令
卸载服务:redis-server --service-uninstall
开启服务:redis-server --service-start
停止服务:redis-server --service-stop
测试redis,通过cd到我们解压的目录,输入指令通过Set get指令查看是否成功

img


Redis-benchmark性能测试:
序号选项描述默认值
1-h指定服务器主机名127.0.0.1
2-p指定服务器端口6379
3-s指定服务器 socket
4-c指定并发连接数50
5-n指定请求数10000
6-d以字节的形式指定 SET/GET 值的数据大小2
7-k1=keep alive 0=reconnect1
8-rSET/GET/INCR 使用随机 key, SADD 使用随机值
9-P通过管道传输 请求1
10-q强制退出 redis。仅显示 query/sec 值
11–csv以 CSV 格式输出
12-l生成循环,永久执行测试
13-t仅运行以逗号分隔的测试命令列表。
14-IIdle 模式。仅打开 N 个 idle 连接并等待。
实例

以下实例我们使用了多个参数来测试 redis 性能:

$ redis-benchmark -h 127.0.0.1 -p 6379 -t set,lpush -n 10000 -q

SET: 146198.83 requests per second
LPUSH: 145560.41 requests per second

以上实例中主机为 127.0.0.1,端口号为 6379,执行的命令为 set,lpush,请求数为 10000,通过 -q 参数让结果只显示每秒执行的请求数。


基本知识:
默认16个数据库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aETc2JYC-1607855942050)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201210164934960.png)]

切换数据库: select index(0–15)

查看数据库大小:dbsize

清空数据库(当前):flushdb

清空全部数据库:flushall

redis是基于内存操作的,cpu不是redis性能的瓶颈,他的性能瓶颈是内存和网络带宽;
redis是c写的,完全不比memecache差
将所有的数据存到内存,cpu的多线程会进行上下文切换的操作,这样会损耗资源,因此单线程对于内存来所处理的效率是最快的;

基本的数据类型:
String
Redis—key
String
Hash
List
Set
ZSet
127.0.0.1:6379> keys *  #查看所有的key
(empty list or set)
127.0.0.1:6379> set name qingdao # set key
OK
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> set date 2020
OK
127.0.0.1:6379> keys *
1) "date"
2) "name"
127.0.0.1:6379> exists name #查看key是否存在
(integer) 1  #1表示存在,0表示不存在
127.0.0.1:6379> exists age
(integer) 0
127.0.0.1:6379> exists date
(integer) 1
127.0.0.1:6379> move name 2   #移除key
(integer) 1
127.0.0.1:6379> keys *
1) "date"

append [key ] [value]

127.0.0.1:6379> set name 1234
OK
127.0.0.1:6379> get name
"1234"
127.0.0.1:6379> append name qwer  #追加value的值
(integer) 8
127.0.0.1:6379> get name
"1234qwer"
127.0.0.1:6379> append age 18
(integer) 2
127.0.0.1:6379> get age
"18"
127.0.0.1:6379> strlen name  #获取value的长度
(integer) 8

append实在原来key的基础上追加value的值;

strlen获取key对应value的长度;

127.0.0.1:6379> get name
"1234qwer"
127.0.0.1:6379> getrange name 4 7  #获取一段字符串
"qwer"
127.0.0.1:6379> getrange name 0 -1 #获取全部字符串
"1234qwer"
127.0.0.1:6379> get name
"1234qwer"
127.0.0.1:6379> setrange name 4  qq  #替换字符串
(integer) 8
127.0.0.1:6379> get name
"1234qqer"
127.0.0.1:6379>
#批量设置值:
127.0.0.1:6379> mset name xiaoming age 20 sex man
OK
127.0.0.1:6379> keys *
1) "age"
2) "sex"
3) "name"
127.0.0.1:6379> get age
"20"
127.0.0.1:6379> get name
"xiaoming"
127.0.0.1:6379> get sex
"man"
127.0.0.1:6379>
#批量获取多个值
127.0.0.1:6379> mget name age sex
1) "xiaoming"
2) "20"
3) "man"
127.0.0.1:6379>
#设置一个用户
127.0.0.1:6379> mset user:1:name zhangshan user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangshan"
2) "2"
127.0.0.1:6379>
127.0.0.1:6379> getset db redis  #先进行get再set
(nil)
127.0.0.1:6379> get db  #可以进行替换更新的操作
"redis"
127.0.0.1:6379> getset db mongodb
"redis"
127.0.0.1:6379>

List

在list里面,我们可以吧list玩成栈、队列、阻塞队列;

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

list里面可以有重复值

127.0.0.1:6379> lpush list 1  #添加元素
(integer) 1
127.0.0.1:6379> lpush list 2
(integer) 2
127.0.0.1:6379> Lpush list 3
(integer) 3
127.0.0.1:6379> Lrange list 0  -1  #获取全部元素
1) "3"
2) "2"
3) "1"
127.0.0.1:6379> Lrange list 0 0  #获取特定元素
1) "3"
127.0.0.1:6379> Rpush list 0  #右边添加一个元素
(integer) 4
127.0.0.1:6379> Lrange list 0 -1 
1) "3"
2) "2"
3) "1"
4) "0"
127.0.0.1:6379>

添加的顺序:

1

2 1

3 2 1

3 2 1 0

Lpush表示左边添加一个值

Rpush表示右边添加一个值

127.0.0.1:6379> lrange list 0 -1
1) "3"
2) "2"
3) "1"
4) "0"
127.0.0.1:6379> lindex list 0 #通过下标获取一个值
"3"
127.0.0.1:6379> lindex list 2
"1"
127.0.0.1:6379> Llen list  #获取当前列表的长度
(integer) 4
127.0.0.1:6379> lrem list 1 0  #list移除元素的值  个数  值
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "3"
2) "2"
3) "1"
127.0.0.1:6379> flushdb  #清空当前的数据库
OK
127.0.0.1:6379> lpush list 1
(integer) 1
127.0.0.1:6379> lpush list 2
(integer) 2
127.0.0.1:6379> lpush list 3
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "3"
2) "2"
3) "1"
127.0.0.1:6379> ltrim list 1 2    #只保留截取的list(反向删除)
OK
127.0.0.1:6379> lrange list 0 -1
1) "2"
2) "1"
127.0.0.1:6379>
#替换
127.0.0.1:6379> lpush list 1 
(integer) 1
127.0.0.1:6379> exists list  #查看list是否存在
(integer) 1
127.0.0.1:6379> lrange list 0 -1  #查看所有的list
1) "1"
127.0.0.1:6379> lset list 0 nnnnnn   #替换特定位置的list的内容
OK
127.0.0.1:6379> lrange list 0 -1  #1被替换成了nnnnnn
1) "nnnnnn"
127.0.0.1:6379>
#在元素的后面或前面添加一个元素
127.0.0.1:6379> lpush list 12\
(integer) 1
127.0.0.1:6379> lpush list 13
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "13"
2) "12\\"
127.0.0.1:6379> linsert list before 13 12  #在13 的前面添加一个12
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "12"
2) "13"
3) "12\\"
127.0.0.1:6379> linsert list after 13 12  #在元素13 的后面添加一个12 
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "12"
2) "13"
3) "12"
4) "12\\"
127.0.0.1:6379>
#   after  before 指的是插入的前后顺序

Set(集合)

#sadd:添加元素格式是:sadd set的key item的项值,item项可以有多个。
127.0.0.1:6379> sadd set 1 2 3 4  #添加值   可以添加多个值
(integer) 4
127.0.0.1:6379> smembers set  #获取set的所有的值
1) "1"
2) "2"
3) "3"
4) "4"
127.0.0.1:6379> sismember set 5 #判断元素是否在集合中
(integer) 0  #不在
127.0.0.1:6379> sismember set 4
(integer) 1  #在
127.0.0.1:6379> srem set 4  #删除某个值
(integer) 1
127.0.0.1:6379> smembers set  #获取set的全部值
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> scard set  #获取当前集合的长度
(integer) 3  #集合的长度

srandmember:随机获取集合中的元素,格式是:srandmember set的key[数量]。(数量为正数时,会随机获取这么多个不重复的元素;如果数量大于集合元素个数,返回全部;如果数量为负,会随机获取这么多个元素,可能有重复。)

127.0.0.1:6379> sadd myset 1 2 3 4 5 6 7
(integer) 7
127.0.0.1:6379> smembers myset
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
127.0.0.1:6379> srandmember myset 2  #随机挑选2个不同的数
1) "2"
2) "5"
127.0.0.1:6379> srandmember myset 2  #和上面的不一样
1) "5"
2) "6"
127.0.0.1:6379> srandmember myset 12  #正常顺序返回全部的集合
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
127.0.0.1:6379> srandmember myset 12 #验证上面
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
127.0.0.1:6379> srandmember myset -4  #随机挑选4个值,可能是重复的
1) "6"
2) "7"
3) "3"
4) "6"
127.0.0.1:6379>  srandmember myset -4
1) "3"
2) "1"
3) "7"
4) "6"
127.0.0.1:6379> spop myset 7  #抛出元素后面可以跟抛出的个数
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
127.0.0.1:6379> smembers myset  #集合是空
(empty list or set)
127.0.0.1:6379> sadd myset 1 2 3 4 5  #添加元素
(integer) 5
127.0.0.1:6379> smove myset other 1  #将指定的元素移动到其他的集合中
(integer) 1
127.0.0.1:6379> smembers myset  #查看集合中的所有元素
1) "2"
2) "3"
3) "4"
4) "5"
127.0.0.1:6379> smembers other  #元素已经被移动
1) "1"
127.0.0.1:6379>

sdiff:差集,返回在第一个set里面而不在后面任何一个set里面的项。格式是:sdiff set的key 用来比较的多个set的key

127.0.0.1:6379> sadd myset 1 2 3
(integer) 3
127.0.0.1:6379> smembers myset
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> sadd myset1 2 3 4
(integer) 3
127.0.0.1:6379> smembers myset1
1) "2"
2) "3"
3) "4"
127.0.0.1:6379> sdiff myset myset1
1) "1"
127.0.0.1:6379>

sdiffstore:差集并保留结果,格式是:sdiffstore 存放结果的set的key set的key 用来比较的多个set的key

127.0.0.1:6379> sadd myset1 1 2 3 4 5
(integer) 5
127.0.0.1:6379> sadd myset2 3 467
(integer) 2
127.0.0.1:6379> saDD myset3 1
(integer) 1
127.0.0.1:6379> sdiffstore store myset1 myset2 myset3
(integer) 3
127.0.0.1:6379> smembers store
1) "2"
2) "4"
3) "5"
127.0.0.1:6379>
127.0.0.1:6379> sadd myset 1 2 3
(integer) 3
127.0.0.1:6379> sadd myset1 2 3 4
(integer) 3
127.0.0.1:6379> sadd myset3 3 4 5
(integer) 3
127.0.0.1:6379> sinter myset myset1
1) "2"
2) "3"
127.0.0.1:6379> sinter myset myset1 myset3
1) "3"
127.0.0.1:6379>
#sinter:交集,返回多个set里面都有的项。格式是:sinter 多个set的key 

sinterstore:交集并保留结果。格式是:sinterstore 存放结果的key 多个set的key

127.0.0.1:6379> sadd myset 1 2 3
(integer) 3
127.0.0.1:6379> sadd myset1 2 3 4
(integer) 3
127.0.0.1:6379> sadd myset2 3 4 5
(integer) 3
127.0.0.1:6379> sinterstore myset3 myset1 myset2 myset
(integer) 1
127.0.0.1:6379> smembers myset3
1) "3"
127.0.0.1:6379>

sunionstore:并集并保留结果。格式是:sunionstore 存放结果的set的key 多个set的key


Hash
127.0.0.1:6379> hset test name xiaoming  #设置值
(integer) 1
127.0.0.1:6379> hset test age 20
(integer) 1
127.0.0.1:6379> hset test sex man
(integer) 1
127.0.0.1:6379> hmset test1 name xiaohong age 21 sex woman  #设置多个值
OK
127.0.0.1:6379> hget test name  #取值
"xiaoming"
127.0.0.1:6379> hmget test name  age sex   #取多个值
1) "xiaoming"
2) "20"
3) "man"
127.0.0.1:6379> hmget test1 name age sex
1) "xiaohong"
2) "21"
3) "woman"
127.0.0.1:6379> hgetall test   #获取全部的值
1) "name"
2) "xiaoming"
3) "age"
4) "20"
5) "sex"
6) "man"
127.0.0.1:6379> hgetall test1
1) "name"
2) "xiaohong"
3) "age"
4) "21"
5) "sex"
6) "woman"
127.0.0.1:6379> hdel test age  #删除某个值
(integer) 1
127.0.0.1:6379> hgetall test
1) "name"
2) "xiaoming"
3) "sex"
4) "man"
127.0.0.1:6379> hlen test  #获取键值对的长度
(integer) 2
127.0.0.1:6379> hlen test2
(integer) 0
127.0.0.1:6379> hlen test1
(integer) 3
127.0.0.1:6379> hexists test age  #判断键值对是否存在
(integer) 0  #不存在
127.0.0.1:6379> hexists test name
(integer) 1 #存在
127.0.0.1:6379> hkeys test  #获取item里面所有的keys
1) "name"
2) "sex"
127.0.0.1:6379> hkeys test1  
1) "name"
2) "age"
3) "sex"
127.0.0.1:6379> hvals test  #获取items里面所有的values
1) "xiaoming"
2) "man"
127.0.0.1:6379> hincrby test id -1
(integer) -1
127.0.0.1:6379> hgetall test
1) "name"
2) "xiaoming"
3) "sex"
4) "man"
5) "id"
6) "-1"
127.0.0.1:6379> hincrby test qw 4
(integer) 4
127.0.0.1:6379> hgetall test
1) "name"
2) "xiaoming"
3) "sex"
4) "man"
5) "id"
6) "-1"
7) "qw"
8) "4"
#hincrby : 增减整数数字,格式是:hincrby Hash的key 项的key 正负整数
#incrbyfloat :增减float数值,格式是:hincrbyfloat Hash的key 项的key 正负float
#hsetnx : 如果项不存在则赋值,存在时什么都不做,格式是:hsetnx Hash的key 项的key 项的值

Sorted set(Zset)
127.0.0.1:6379> zadd test 10 t1  #添加元素
(integer) 1
127.0.0.1:6379> zadd test 20 t2
(integer) 1
127.0.0.1:6379> zadd test 30 t3 40 t4   #添加多个元素
(integer) 2
127.0.0.1:6379> zrange test 0 -1  #获取全部元素
1) "t1"
2) "t2"
3) "t3"
4) "t4"
127.0.0.1:6379> zrange test 0 -1 withscores  #获取全部元素+score
1) "t1"
2) "10"
3) "t2"
4) "20"
5) "t3"
6) "30"
7) "t4"
8) "40"
127.0.0.1:6379> zadd test 9 t5
(integer) 1
127.0.0.1:6379> zrange test 0 -1 withscores  #按照score的大小存放的
 1) "t5"
 2) "9"
 3) "t1"
 4) "10"
 5) "t2"
 6) "20"
 7) "t3"
 8) "30"
 9) "t4"
10) "40"
127.0.0.1:6379> zrangebyscore test 0 30   #获取一定范围的值
1) "t5"
2) "t1"
3) "t2"
4) "t3"
127.0.0.1:6379> zrangebyscore test 0 30 withscores
1) "t5"
2) "9"
3) "t1"
4) "10"
5) "t2"
6) "20"
7) "t3"
8) "30"
127.0.0.1:6379> zrem test t5  #删除某个值
(integer) 1
127.0.0.1:6379> zrange test 0 -1
1) "t1"
2) "t2"
3) "t3"
4) "t4"
127.0.0.1:6379> zcard test   #获取集合中元素的个数
(integer) 4
127.0.0.1:6379> zincrby test 20 t1 #正数表示增加元素的score
"30"
127.0.0.1:6379> zrange test 0 -1
1) "t2"
2) "t1"
3) "t3"
4) "t4"
127.0.0.1:6379> zincrby test -10 t3  #负数表示减少元素的score
"20"
127.0.0.1:6379> zrange test 0 -1 withscores
1) "t2"
2) "20"
3) "t3"
4) "20"
5) "t1"
6) "30"
7) "t4"
8) "40"
127.0.0.1:6379> zcount test 0 100  #获取0 100 元素的score在这个区间的元素的个数
(integer) 4
127.0.0.1:6379> zrank test t1  #获取元素的索引值
(integer) 2
127.0.0.1:6379> zscore test t1  #获取元素的score值
"30"、
127.0.0.1:6379> zrevrank test t4  #获取逆序的索引值
(integer) 0
#zremrangebyrank:删除索引区间内的元素
#zremrangebyscore:删除分数区间内的元素,格式是:zremrangebysocre zset的key 起始score 终止score
#交集zinterstore
#并集zunionstore
特殊得到数据类型:

Geo

可以将位置的地理信息存储,对信息进行处理;
GEO常用语LBS(Location Based Service),基于位置的服务。
127.0.0.1:6379> geoadd city 120.20000 30.26667 hangzou 116.41667 39.91667 beijing  121.47 31.23 shanghai  #添加城市的地理位置信息
(integer) 3
127.0.0.1:6379> geopos city hangzou beijing shanghai  #显示城市的地理位置信息
1) 1) "120.20000249147415"
   2) "30.266670658987586"
2) 1) "116.41667157411575"
   2) "39.916670952735892"
3) 1) "121.47000163793564"
   2) "31.229999039757836"
127.0.0.1:6379> geodist city beijing shanghai km  #获取两个位置点的距离   m、km、ml(英里)、ft(尺)
"1068.3890"
127.0.0.1:6379> georadiusbymember city beijing 2000 km   WITHCOORD WITHDIST WITHHASH ASC COUNT  10
#获取北京两千km内10个城市按照距离的排序
#WITHDIST : 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。
#WITHCOORD : 将位置元素的经度和维度也一并返回。
#WITHHASH : 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。
#ASC : 根据中心的位置, 按照从近到远的方式返回位置元素。DESC : 根据中心的位置, 按照从远到近的方式返回位置元素。
1) 1) "beijing"
   2) "0.0000"
   3) (integer) 4069885649163649
   4) 1) "116.41667157411575"
      2) "39.916670952735892"
2) 1) "shanghai"
   2) "1068.3890"
   3) (integer) 4054803462927619
   4) 1) "121.47000163793564"
      2) "31.229999039757836"
3) 1) "hangzou"
   2) "1126.8937"
   3) (integer) 4054134205316048
   4) 1) "120.20000249147415"
      2) "30.266670658987586"
127.0.0.1:6379> geohash city beijing
1) "wx4g14s53n0"#将经纬度转换成为geohash的字符串

存储结构主要是redis的zset(有序集合)

127.0.0.1:6379> zrange city 0 -1 withscores
1) "hangzou"
2) "4054134205316048"  #GeoHash的52位整数值
3) "shanghai"
4) "4054803462927619"
5) "beijing"
6) "4069885649163649"
127.0.0.1:6379>

geohash的核心思想就是将球体转化成为球面,区块转换成为一个点

三位的地球转换成为二维的坐标;

二维的坐标转换成为一维的点块;

一维的点块转换成为base32 的编码

拓展

目前很多数据存储引擎都支持Geo的处理,如MongoDB、MySql、PgSql、Elasticsearch等

HyperLogLog

基数统计的算法;
网页的uv(用户的访问量)(一个人访问多次但是是一个人);
占用的内存是固定的;
127.0.0.1:6379> pfadd test 1 23 3 4 5 6 7 8 3 4   #添加元素的数量
(integer) 1
127.0.0.1:6379> pfcount test  #统计集合中元素的基数
(integer) 8
127.0.0.1:6379> pfadd test1 q w e r t y u
(integer) 1
127.0.0.1:6379> pfcount test2
(integer) 0
127.0.0.1:6379> pfcount test1
(integer) 7
127.0.0.1:6379> pfmerge test2 test test1  #两个集合取并集
OK
127.0.0.1:6379> pfcount test2
(integer) 15
127.0.0.1:6379>

如果允许容错,一定可以使用HyperLogLog;

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


BitMaps

位存储(对立面 0 1);

位图 数据结构 二进制位进行记录,只有01 两个状态;

#记录一周的打卡记录
127.0.0.1:6379> setbit sign 0 1  #设置值
(integer) 0
127.0.0.1:6379> setbit sign 1 1
(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 1
(integer) 0
(integer) 0
127.0.0.1:6379> getbit sign 1   #获取值
(integer) 1
127.0.0.1:6379> getbit sign 6
(integer) 1
127.0.0.1:6379> bitcount sign  #统计打卡的天数(1)
(integer) 5
127.0.0.1:6379>

事务:

redis的单条命令是保证原子性的,但是事务是不保证原子性的;

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

一次性 顺序性 排他性;

三个阶段:

开启事务;multi

命令入队;

执行事务;exec

127.0.0.1:6379> multi   #开启事务
OK
127.0.0.1:6379> set k1 1
QUEUED
127.0.0.1:6379> set k2 2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec  #执行事务
1) OK
2) OK
3) "2"
127.0.0.1:6379>

127.0.0.1:6379> multi  #开启事务
OK
127.0.0.1:6379> set t1 1
QUEUED
127.0.0.1:6379> discard  #取消事务
OK
127.0.0.1:6379> get t1   #可以看到我们的set t1 1 没有执行
(nil)
127.0.0.1:6379>
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set t1 1
QUEUED
127.0.0.1:6379> set t2 2
QUEUED
127.0.0.1:6379> set t3 3
QUEUED
127.0.0.1:6379> getset t4 4
QUEUED
127.0.0.1:6379> getset t5  #代码的语句是错误的
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379> get t4
QUEUED
127.0.0.1:6379> exec  #代码的语句是错误的,那么我们的整个事务是不执行的
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379>
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set t1 "qw"
QUEUED
127.0.0.1:6379> incr t1
QUEUED
127.0.0.1:6379> set t2 2
QUEUED
127.0.0.1:6379> get t2
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) ERR value is not an integer or out of range  #语法性错误
#我们的代码用法格式上没有错误,但是我们的语法出现错误,但是不会影响我们的事务的执行;
3) OK
4) "2"
127.0.0.1:6379> get t1
"qw"
#事务的单条语句是原子性的但是事务整体是没有原子性的,
#结果可以验证 我们的incr t1 没有执行  但是整个事务执行了;

监控 watch

乐观锁;认为什么时候都不会出现问题在更行数据的是时候判断数据是否被修改,

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  #监视钱数
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>

多线程操作:(开启多个client)

127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
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
1) (integer) 90
2) (integer) 10
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  #在这个事务执行的时候我们的另一个客户端执行  set money  100的操作,

QUEUED
127.0.0.1:6379> exec  #执行事务,在执行这个事务的会进行money(当前)和watch money记录的值进行比较,如果不一致那么我们的事务就不执行;

Jedis

conf详解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rfOQBj7h-1607855942051)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201212201744213.png)]

对大小写不敏感;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fZg0fXHA-1607855942051)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201212201844637.png)]

可以导入其他的配置;


RDB和AOF

持久化之RDB

定义:在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)

*RDB 的优点*

1.RDB 是一个非常紧凑(compact)的文件,它保存了 Redis 在某个时间点上的数据集。 这种文件非常适合用于进行备份:

*2.RDB 非常适用于灾难恢复(disaster recovery)*:它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心,或者亚马逊 S3 中。

*3.RDB 可以最大化 Redis 的性能*:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。

4.RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

***RDB 的缺点


如果你需要尽量避免在服务器故障时丢失数据,那么 RDB 不适合你。 虽然 Redis 允许你设置不同的保存点(save point)来控制保存 RDB 文件的频率, 但是, 因为RDB 文件需要保存整个数据集的状态, 所以它并不是一个轻松的操作。 因此你可能会至少 5 分钟才保存一次 RDB 文件。 在这种情况下, 一旦发生故障停机, 你就可能会丢失好几分钟的数据。

每次保存 RDB 的时候,Redis 都要 fork() 出一个子进程,并由子进程来进行实际的持久化工作。 在数据集比较庞大时, fork() 可能会非常耗时,造成服务器在某某毫秒内停止处理客户端; 如果数据集非常巨大,并且 CPU 时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒。 虽然 AOF 重写也需要进行 fork() ,但无论 AOF 重写的执行间隔有多长,数据的耐久性都不会有任何损失。

AOF 的优点

***1.使用 AOF 持久化会让 Redis 变得非常耐久(much more durable)***:你可以设置不同的 fsync 策略,比如无 fsync ,每秒钟一次 fsync ,或者每次执行写入命令时 fsync 。 AOF 的默认策略为每秒钟 fsync 一次,在这种配置下,Redis 仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据( fsync 会在后台线程执行,所以主线程可以继续努力地处理命令请求)。

AOF 文件是一个只进行REDIS持久化之RDB和AOF的区别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值