1.redis是什么:
Redis是一个非常流行的基于内存的轻量级键值数据库,Redis是一个高性能的kv对(键值)缓存和内存NoSql数据库
2.redis的应用场景
1) 用来做缓存--redis的所有的数据都是放在内存中(内存数据库)
2) 可以用于实现简单的队列系统
3) 在离线批处理数据中,可以作为外部字典的知识库,来实现分布式计算过程中的外部数据查询
可以在某些特定应用场景下替代传统数据库解决一些特定需求
——比如社交类的应用(共同好友,使用了某项功能的人数统计)
——session共享、购物车
3. redis的特点
- Redis数据访问速度快(数据在内存中,并有优化的存储结构设计)
- Redis相比其他缓存工具(ehcach/memcached),有一个鲜明的优势:支持丰富的数据结构
- Redis有数据持久化机制,持久化机制有两种:
定期将内存数据dump到磁盘;(耗费运行时性能,但是宕机后的恢复过程快)
每一次更新操作,一旦出现灾难事件,可以通过日志重放来恢复整个数据库(耗费运行时性能小,但是宕机后的恢复过程慢)
集群模式(容量可以线性扩展)
4. redis 的数据结构类型
4.1 String类型的数据
1) 插入和读取一条string 类型的数据
set key1 value1
get key1
2) 对string 类型的数据进行增减(前提是这条数据的value可以看成是数字)
DECRBY key decrement :对 value减去一个自己指定的数字
INCRBY key increment:对value 增加一个自己指定的数字
3) 一次性插入多条数据和一次性获取多条数字
MSET key1 value1 key2 value2 …..
MGET key1 key2
4) 对插入的string 类型的数据可以指定一个存活期
setex key1 10 zss 这条数据在10秒之后就会被自动的删除
4.2 用java客户端插入对象到redis中
/**
* 测试将对象序列化之后写入到redis中
*
* @throws IOException
*/
@Test
public void testObjectPerson() throws IOException {
Jedis jedis = new Jedis("linux01", 6379);
Person p1 = new Person("zss", 18, "男");
Person p2 = new Person("lss", 28, "女");
Person p3 = new Person("ww", 38, "女");
Person p4 = new Person("hh", 48, "男");
//将对象放入集合中方便一次性写入到redis 中
ArrayList<Person> list = new ArrayList<Person>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
//将对象序列化成字节数组
ByteArrayOutputStream ba = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(ba);
//用对象序列化流来将p对象序列化,然后把序列化之后的二进制数据写到ba流中
oos.writeObject(p4);
//将ba流转成byte数组
byte[] pBytes = ba.toByteArray();
//将对象序列化之后的byte数组存到redis的string结构数据中
jedis.set("list1".getBytes(), pBytes);
jedis.close();
}
/**
* 将序列化写入到redis中的对象反序列化读取出来
*
* @throws Exception
*/
@Test
public void deObjectPerson() throws Exception {
//将redis 中的对象通过反序列化读取出来
Jedis jedis = new Jedis("linux01", 6379);
//根据key从redis中读入出数据
byte[] bytes = jedis.get("list".getBytes());
//将bytes反序列化出来
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
//从对象读取流中读取出数据
Object o = ois.readObject();
System.out.println(o);
jedis.close();
}
5. redis 中的list数据类型
从头部(左边)插入数据
redis>LPUSH key value1 value2 value3
从尾部(右边)插入数据
redis>RPUSH key value1 value2 value3
读取list中指定范围的values
redis>LRANGE key start end
redis> lrange task-queue 0 -1 读取整个list
从头部弹出一个元素
LPOP key
从尾部弹出一个元素
RPOP key
从一个list的尾部弹出一个元素插入到另一个list
RPOPLPUSH key1 key2 ## 这是一个原子性操作
6.redis中的hash数据类型
6.1 往redis库中插入一条hash类型的数据
redis> HSET key field value
redis 127.0.0.1:6379> hset user001:zhangsan iphone 6
redis 127.0.0.1:6379> hset user001:zhangsan xiaomi 7
redis 127.0.0.1:6379> hset user001:zhangsan meizu 8
插入redis中的结果展示:
6.2 取出一条hash类型数据中所有field-value对
redis 127.0.0.1:6379> hgetall user001:zhangsan
1) "iphone"
2) "6"
3) "xiaomi"
4) "7"
5) "meizu"
6) "8"
6.3 取出hash数据中所有fields
redis 127.0.0.1:6379> HKEYS user001:zhangsan
1) "iphone"
2) "xiaomi"
3) "meizu"
6.4 取出hash数据中所有的value
redis 127.0.0.1:6379> hvals user001:zhangsan
1) "6"
2) "7"
3) "8"
6.5 取出hash数据中一个指定field的值
redis 127.0.0.1:6379> hget user001:zhangsan xiaomi
"8"
6.6 为hash数据中指定的一个field的值进行增减
redis 127.0.0.1:6379> HINCRBY
6.7 从hash数据中删除一个字段field及其值
redis 127.0.0.1:6379> HDEL user001:zhangsan iphone
7. Set数据结构功能
set数据类型的特点:无序,无重复元素
7.1 插入一条set数据
redis 127.0.0.1:6379> sadd frieds:zhangsan bingbing baby fengjie furong ruhua tingting
(integer) 6
redis 127.0.0.1:6379> scard frieds:zhangsan 求总人数
(integer) 6
7.2 获取一条set数据的所有members
redis 127.0.0.1:6379> smembers frieds:zhangsan
7.3 判断一个成员是否属于某条指定的set数据 是返回1 不是返回0
redis 127.0.0.1:6379> sismember frieds:zhangsan liuyifei #如果不是,则返回0
(integer) 0
redis 127.0.0.1:6379> sismember frieds:zhangsan baby #如果是,则返回1
(integer) 1
7.4 求两个set数据的差集(集合A有的元素而集合B中没有的元素)
1. redis 127.0.0.1:6379> sdiff frieds:zhangsan friends:xiaotao
1) "furong"
2) "fengjie"
3) "ruhua"
4) "feifei"
2. 求差集,并将结果存入到另一个set
redis 127.0.0.1:6379> sdiffstore zhangsan-xiaotao frieds:zhangsan friends:xiaotao
(integer) 4
7.5 求交集,求并集
#求交集
redis 127.0.0.1:6379> sinterstore zhangsan:xiaotao frieds:zhangsan friends:xiaotao
(integer) 2
redis 127.0.0.1:6379> smembers zhangsan:xiaotao
1) "bingbing"
2) "baby"
#求并集
redis 127.0.0.1:6379> sunion frieds:zhangsan friends:xiaotao
1) "fengjie"
2) "tangwei"
3) "liuyifei"
4) "bingbing"
5) "ruhua"
6) "feifei"
7) "baby"
8) "songhuiqiao"
9) "furong"
10) "yangmi"
8. SortedSet(有序set集合)数据结构
SortedSet 结构的简述: sortedset中存储的成员都有一个附带的分数值,而redis就可以根据分数来对成员进行各种排序(正序、倒序)
8.1 往redis库中插入一条sortedset数据
redis 127.0.0.1:6379> zadd nansheng:yanzhi:bang 70 liudehua 90 huangbo 100 weixiaobao 250 yangwei 59 xiaotao
(integer) 5
8.2 从redis 中查询SortedSet 结果
#正序结果
redis 127.0.0.1:6379> zrange
1) "xiaotao"
2) "liudehua"
3) "huangbo"
4) "weixiaobao"
5) "yangwei"
#倒序结果
redis 127.0.0.1:6379> zrevrange nanshen:yanzhi:bang 0 4
1) "yangwei"
2) "weixiaobao"
3) "huangbo"
4) "liudehua"
5) "xiaotao"
8.3 查询某个成员的名次
#在正序榜中的名次
redis 127.0.0.1:6379> zrank
(integer) 0
#在倒序榜中的名次
redis 127.0.0.1:6379> zrevrank nanshen:yanzhi:bang xiaotao
(integer) 4
8.4 修改成员的分数
redis 127.0.0.1:6379> zincrby nanshen:yanzhi:bang 300 xiaotao
"359"
redis 127.0.0.1:6379> zrevrank nanshen:yanzhi:bang xiaotao
(integer) 0
9. GEO数据结构
geo数据结构的特点:GEO数据类型支持便捷的geo地理位置计算
1. 添加地点及gps坐标:
doitedu03:6379> GEOADD CN:DIS 121.896321 46.8723843 JS:NT:TN 121.896533 46.872622 JS:NT:NN
(integer) 2
2. 获取指定地点的gps坐标
doitedu03:6379> GEOPOS CN:DIS JS:NT:NN
1) "121.89653187990188599"
2) "46.87262258451151808"
3. 查询指定地点指定半径内的相邻点
linux01:6379> GEORADIUS CN:DIS 121.896341 46.8723853 1 km
1) "JS:NT:TN"
2) "JS:NT:NN"
linux01:6379>
10 BitMap数据结构
10.1 Bitmap基本使用
位图(也称为位数组或位向量)是由比特位(bit)组成的数组。Redis 中的位图并不是一种新的数据类型,它实际的底层数据类型是字符串。因为字符串本质上是二进制大对象(BLOB,BinaryLarge OBject ),所以可以将其视做位图。同时,因为位图存储的是布尔信息,所以在某些情况下可以节省大量的内存空间。
11 HyperLogLog数据结构
11.1 HyperLogLog算法介绍:
在Redis 中,如果我们不需要获取数据集的内容,而只是想得到不同值的个数,那么就可以使用HyperLogLog( HLL)数据类型来优化使用集合类型时存在的内存和性能问题。Reids中 HLL的优势在于能够使用固定数量的内存(每个HyperLogLog 类型的键只占用12KB内存,却最多可以计算264个不同元素的基数)和常数时间复杂度O(1)不过,由于HLL算法返回的基数(译者注:HLL和常数时间复杂度(每个键O(1))进行唯一计数。不过,由于HLL算法返回的基数可能不准确(标准差小于1%),因此在决定是否使用HLL时需要进行权衡。
11.2 HyperLogLog的核心思想
利用一个元素的hashcode的最左边连0个数,来倒推你扔了多少个元素,比如:
扔到目前,我记录的最大左连0个数为3,那么我就有一定的依据推测你扔了23个元素
但是,hyperloglog为了让推算更准确,它采用了一个分桶的机制,我会用很多个桶来分别记录该桶中出现过的最大连零数,然后,利用每个桶的最大连0数倒推基数,并最后将每个桶的倒推基数结果求调和平均值,作为最终推测基数;
12. redis中的订阅和发布
订阅者:
linux01:6379>subscribe channel1
发布者:
linux01:6379> publish channel1 aaa
13 pipeline
13.1 popeline的通信原理:
Redis客户端和服务器之间典型的通信过程可以看作:
- 客户端向服务器发送一个命令。
- 服务器接收该命令并将其放入执行队列(因为Redis是单线程的执行模型)。
- 命令被执行。
- 服务器将命令执行的结果返回给客户端。
13.2 将一批命令放入一个文件中,通过管道的方式将它们一次性发送,而不再等待每个单独命令的执行结果
1.准备一个文件,用来存放一批命令
[root@doitedu01 ~]# cat pipeline.txt
set a 111
set b 222
sadd set:x v1 v2
get a
scard myset
2.使用redis-cli的--pipe选项,通过管道发送命令:
[root@linux01 redis6]# cat /root/pipeline.txt | bin/redis-cli -h linux01 --pipe
All data transferred. Waiting for the last reply...
Last reply received from server.