redis全称:reomote Dictionary Server (远程字典服务),是一个开源的,使用ANSI C语言来编写。是基于内存来存储key-value的数据库,还可以持久化的保存在磁盘上。redis是NoSQL类型的数据库的一种。支持大多数主流的开发,如java、c、python等。
NoSQL:(Not Only SQL)泛指非关系型数据。NoSQL不仅仅是一个概念,还泛指非关系型数据库,区别于关系型数据库,他们不保证ACID特性。NoSQL是一种全新的数据库革命性运动,能够解决关系型数据库难以完成的操作,还具有已扩展,高可读写的性能,特别是当数据量大的时候,同样表现优秀。
redis默认有16个数据库。(默认选中0,名字从0开始)
切换数据库 select 1
:这样就切换到名字为1的数据库
查看key:keys patten
:patten是查询key的规则,使用*表示查看当前数据库中所有的key。
redis中的key-value中的value也是有数据类型的。数据类型有String,List,Hash,Set,SortedSet。
常见的命令操作有如下:
set key value
:设置一个key,值为value,值类型为String的键值对,若key不存在则创建,若key已存在,则更新value。返回 1成功,0失败。get key
:获取key对应的value,若key不存在,则返回nil。mget key1 key2 key3
:获取多个value。incr key
:将key的数字加1,若key不存在则会创建一个,并初始化为0,然后数值加1。若key的value不是一个数字,则会报错。incr key increment
:可以设置每次执行加的次数(increment)。decr key
:将key的数值减1,若key不存在,先创建并初始化为0,再执行减1操作,若不存在则报错。decrby key increment
:可以设置每次执行减的次数(increment)。append key value
:若key存在,则在后面最加value,若key不存在,则执行set
的操作。help @String
:查看string类型的帮助文档。String类型的应用场景:朋友圈的点赞,微博的点赞,直播的在线点赞等。
解决了多线程的问题:redis是单线程的,读写的速度非常快,不存在处理不过来的问题。比如窗口卖票是多线程的线程锁解决卖票的不一致问题,操作复杂。而redis却能简单的解决卖票的线程问题。
list类型使用的是一个双向链表的数据结构,只能对两边的数据进行增删。这样做到增删快的操作。添加还保持了顺序。
位置:从左往右是从0开始的。
从右往左是从-1开始的。
常见的命令操作有如下:
lpush key value1 value2 value3
:从左边推进去,存入的顺序是value1,value2,value3,而在第一位的是value3。rpush key value1 value2
:从右边开始推 值进去,如果key存在,则从右边开始存值进去,顺序是value1,value2,而value2的位置在-1。llen
:返回key的list长度。lindex key index
:根据下标查找元素,从0开始,从左往右。lrange key start stop
:查找指定范围的key,如lrange key 0 -1
,查询所有的key。lpop
:从左边移除第一个元素,返回第一个元素。rpop
:从右边移除第一个元素,返回移除的元素。(最后一个元素)list类型使用场景:处理排名类的业务,楼层的回帖,聊天室等。
常用的命令如下:
hset key field value
:设置hash field为指定值,若key不存在,则会创建,若key存在,则会更新数据。hget key field
:获取指定的hash field。hmget key field...
:获取指定多个的hash field。hmset key field value1...fieldN valueN
:同时设置hash的多个field。hexists key field
:判断指定的field是否存在,存在返回true,不存在返回false。hdel key field
:删除指定的hash field。hlen key
:返回指定hash的field数量。hkeys key
:返回hash的所有field。hvals key
:返回hash的所有value。hgetall key
:返回hash的所有field和value。hash的用途:
节约内存空间
redis每创建一个键(key),都会为这个键储存一些附加的管理信息(比如这个键的类型,这个键最后一次被访问的时间等等)
redis的key相对于值来说,更珍贵!!!
value类似于一个Map集合的数据结构。解决多条数据key前部分相同,而后面部分不同,比如装一个实体类pojo,装数据库中的一条记录,只需要一个key就可以了,而用字符串,则会使key的数量增加,影响查询效率。
不适用场景:
如果我们仅仅只对一个字段设置过期,就不建议使用hash。
Redis的key的过期功能只能对键操作,而Hash结构不能单独对某一个filed设置过期功能。
说明:在实际开发中,能使用hash的时候,尽量使用hash!!
特点:
常用命令如下:
sadd key member[member...]
:添加一个set类型的value,若key不存在则会创建,若key存在,如果是一个set类型的则将不同的添加进去,相同的则会被忽略,如果不是set类型,返回一个错误。smembers key
:返回集合key中的所有成员。不存在的key则视为空集合。spop key
:移除并返回集合中一个随机的元素。被移除的元素是随机的。当key不存在或key是空集时,返回nil。scard key
:返回集合key的基数(集合元素的个数)。当key不存在时,返回0。sinter key[key...]
:返回一个几个的全部成员,该集合是所有给定集合的交集。不存在视为空集。sunion key[key...]
:返回一个集合的全部成员,该集合的所有给定集合的并集。不存在视为空集。sdiff key [key...]
:返回一个集合的全部成员,该集合是所有第一个集合的差集。不存在视为空集。应用场景:qq的共同好友,可能认识的人。新浪微博的共同关注等。
常用的命令如下:
zadd key [sort member sort member...]
:增加值,如zadd set1 1.0 zhangshan 2.0 lisi
zrange key start end
:根据指定的索引查询范围的值。如 zrange set1 0 -1
zcout key start end
:统计一个范围内元素的个数。根据分值查找。返回有序集 key 中, score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量。zcard key
:统计元素的个数。如zcard set1
。zrank key
:返回成员的索引号。如zrank set1 lucy
zrem key [member...]
:删除成员。如zrem set1 zhangsan
适用场景:适用于需要有序且唯一的业务。
比如网易云音乐的排行榜。
注意事项:必须要放开redis允许启动主机访问。
注释/etc/redis.conf 的 bind 127.0.0.1 这个句话 或者 设置为 bind *
项目结构
Jedis连接redis服务端
@Test public void testJedis() { // 连接redis Jedis jedis = new Jedis("192.168.6.100", 6379); // 连接密码 jedis.auth("root"); // ping // System.out.println("ping : "+jedis.ping());//PONG // System.out.println(jedis.info()); }
1)ip绑定问题
Connection refused: connect
把Redis的配置文件redis.conf里的
bind localhost(或者bind 127.0.0.1,表明只有该主机才能访问)注释掉。
或者修改为:
bind ip 表明,只能通过ip访问。
保护模式
DENIED Redis is running in protected mode because protected mode is enabled…
redis处于保护模式,只能本地链接,我们需要修改配置文件redis.conf,将protected-mode yes改成no
Key的测试
@Test public void testJedis() { // 连接redis Jedis jedis = new Jedis("192.168.6.100", 6379); // 连接密码 jedis.auth("root"); // ping // System.out.println("ping : "+jedis.ping());//PONG // System.out.println(jedis.info()); // 操作redis jedis.flushAll();//删除当前所有的key-value // ==============String类型================= jedis.set("name", "lihua2"); String name = jedis.get("name"); System.out.println("name : " + name);// 返回OK // jedis.incr("dz"); // System.out.println(jedis.get("dz")); jedis.incrBy("dz", 10); jedis.decr("dz"); // System.out.println(jedis.get("dz")); // =================List类型========================= jedis.lpush("boys", "孙悟空", "猪八戒", "唐僧", "白龙马", "沙僧"); List<String> boys = jedis.lrange("boys", 0, -1); System.out.println(boys.getClass().getName()); System.out.println(boys); // ==================hash类型======================== jedis.hset("users", "id", "1"); jedis.hset("users", "name", "悟空"); jedis.hset("users", "age", "1000"); String id = jedis.hget("users", "id"); System.out.println(id); Map<String, String> users = jedis.hgetAll("users"); System.out.println(users.getClass().getName()); System.out.println(users); // =====================set类型================================= jedis.sadd("girls", "lili", "lucy", "lihua", "xiaohong"); jedis.sadd("girls2", "zhanjun", "lucy", "baibai", "xiaohong"); Set<String> sinter = jedis.sinter("girls", "girls2"); System.out.println(sinter.getClass().getName()); System.out.println(sinter); // ========================sortedSet类型=============== jedis.zadd("fuirt", 1.0, "西瓜"); jedis.zadd("fuirt", 2.0, "蜜桃"); jedis.zadd("fuirt", 2.5, "香蕉"); jedis.zadd("fuirt", 3.0, "哈密瓜"); jedis.zadd("fuirt", 10.0, "娃娃菜"); Set<String> fuirt = jedis.zrangeByScore("fuirt", 1.0, 2.0); System.out.println(fuirt.getClass().getName()); System.out.println(fuirt); }