javascript:void(O)
在网页编程中,一般让一个超链接点击后不链接到任何地方,而鼠标移上去仍然显示手指形状的图标,就用javascript:void(0)。然后真实执行的操作,是在这个a标签后面加οnclick="xxxxx"(就是鼠标单击后执行某个Javascript函数进行具体的操作)。这样可以做更多的事情,比如根据某个值进行判断跳转到不同的页面等等。
Html:
<li class="layui-nav-item"><a onclick="logout();" href="javascript:void(0);">退出</a></li>
//onclick的事件是真正执行的操作 //href点击后不跳转到任何地方
JavaScript:
function logout() {
layer.confirm('是否确定退出?', {icon: 3, title:'提示'}, function(index){
location.href='/logout';
});
}
RedisDemo项目:
1.导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.3.2.RELEASE</version>
</dependency>
但是只导入redis依赖启动服务器时会出现Error creating bean with name ‘redisConnectionFactory‘ defined in class path resource错误,原因是因为只引入了starter-redis启动依赖。解决:引入commons-pool2依赖即可:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2.application.yml配置文件
spring:
redis:
database: 0 #使用几号数据库
host: 127.0.0.1 #ip地址
port: 6379 #端口号
password: # 密码(默认为空)
timeout: 6000 # 连接超时时长(毫秒)
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 1
# 连接池中的最大空闲连接
max-idle: 100
# 连接池的最大数据库连接数
max-active: 100
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: 10s
timeout: 10000
database: 0
3.序列化问题
储存键值出现乱码问题,获取到的值为springboot\xac\xed\x00\x05t\x00\x04use,这时候需要使用StringRedisTemplate来解决问题,StringRedisTemplate的构造方法:
public StringRedisTemplate() {
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
setKeySerializer(stringSerializer);
setValueSerializer(stringSerializer);
setHashKeySerializer(stringSerializer);
setHashValueSerializer(stringSerializer);
}
或者手动使用这种方法来进行序列化:
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
StringRedisTemplate和RedisTemplate的区别
两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。
其实他们两者之间的区别主要在于他们使用的序列化类:
RedisTemplate使用的是JdkSerializationRedisSerializer 存入数据会将数据先序列化成字节数组然后在存入Redis数据库。
StringRedisTemplate使用的是StringRedisSerializer
使用时注意事项:
当你的redis数据库里面本来存的是字符串数据或者你要存取的数据就是字符串类型数据的时候,那么你就使用StringRedisTemplate即可。
但是如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择。
RedisTemplate使用时常见问题:
redisTemplate 中存取数据都是字节数组。当redis中存入的数据是可读形式而非字节数组时,使用redisTemplate取值的时候会无法获取导出数据,获得的值为null。可以使用 StringRedisTemplate 试试。
Redis的数据类型:
String:
Strings 数据结构是简单的key-value类型,value其实不仅是String,也可以是数字.
常用命令: set,get,decr,incr,mget 等。
应用场景:String是最常用的一种数据类型,普通的key/ value 存储都可以归为此类.即可以完全实现目前 Memcached 的功能,并且效率更高。还可以享受Redis的定时持久化,操作日志及 Replication等功能。一般做一些复杂的计数功能的缓存
Hash
常用命令:hget,hset,hgetall 等。
应用场景:在Memcached中,我们经常将一些结构化的信息打包成HashMap,在客户端序列化后存储为一个字符串的值,比如用户的昵称、年龄、性别、积分等,这时候在需要修改其中某一项时,通常需要将所有值取出反序列化后,修改某一项的值,再序列化存储回去。这样不仅增大了开销,也不适用于一些可能并发操作的场合(比如两个并发的操作都需要修改积分)。而Redis的Hash结构可以使你像在数据库中Update一个属性一样只修改某一项属性值。一般做单点登录(在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统)
List
常用命令:lpush,rpush,lpop,rpop,lrange等。
应用场景:
Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现。做简单的消息队列的功能,如朋友圈点赞
Lists 就是链表,相信略有数据结构知识的人都应该能理解其结构。使用Lists结构,我们可以轻松地实现最新消息排行等功能。Lists的另一个应用就是消息队列,
可以利用Lists的PUSH操作,将任务存在Lists中,然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作Lists中某一段的api,你可以直接查询,删除Lists中某一段的元素。
Set
常用命令:
sadd,spop,smembers,sunion 等。
应用场景:
Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。一般用来做 做全局去重的功能
Sets 集合的概念就是一堆不重复值的组合。利用Redis提供的Sets数据结构,可以存储一些集合性的数据,比如在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。
Sorted Set
常用命令:
zadd,zrange,zrem,zcard等
使用场景:
Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。一般用来做 做排行榜应用,取TopN操作;延时任务;做范围查找
另外还可以用Sorted Sets来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。
类型 | 简介 | 特性 | 场景 |
---|---|---|---|
String (字符串) | Redis的字符串是动态字符串,是可以修改的字符串,它的内部表示就是一个字符数组, 内部结构的实现类似于Java的ArrayList 它的内部结构是一个带长度信息的字节数组 | 可以包含任何数据,比如jpg图片或者序列化的对象,规定字符串的长度不得超过512MB。 Redis的字符串有两种存储方式,在长度特别短时,使用embstr形势存储,而长度超过44字节时候,使用raw形势存储 | 1、访问量统计:每次访问博客和文章使用 INCR 命令进行递增 2、将数据以二进制序列化的方式进行存储 |
Hash (字典) | Redis的字典相当于Java语言里面的HashMap 字典结构内部包含了两个Hashtable,通常情况下只有一个Hashtable是有值的, 但是在字典扩容缩容时候,需要重新分配新的Hashtable,然后进行渐进式搬迁,这时候两个Hashtable存储的分别是旧的Hashtable和新的Hashtable;待搬迁结束后,旧的Hashtable被删除,新的Hashtable取而代之 | 适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去)。 大字典的扩容是比较耗时的,需要重新申请新的数组,然后将旧字典所有链表中的元素重新挂接到新的数组下面,这是一个O(n)级别的操作,作为单线程的Redis很难承受这样耗时的过程,所以Redis使用渐进式rehash小步搬迁虽然慢一点,但是肯定可以搬完。 | 1、存储、读取、修改对象属性,比如:用户(姓名、性别、爱好),文章(标题、发布时间、作者、内容) |
List (列表) | Redis的列表相当于Java的LinkedList List的结构底层实现不是一个简单的LinkedList,而是快速链表(quicklist)。 首先在列表元素较少的情况下,会使用一块连续的内存存储,这个结构是ziplist,即压缩列表。它将所有的元素彼此紧挨着一起存储,分配的是一块连续的内存;当数据量比较多的时候才会改成quicklist。 | 增删快,提供了操作某一段元素的API 普通的链表需要的附加指针空间太大,会浪费空间,加重内存的碎片化。Redis将链表和ziplist结合起来组成了quicklist,也就是将多个ziplist使用双向指针串联起来使用,既满足了快速的插入删除性能,又不会出现太大的空间冗余 | 1、最新消息排行等功能(比如朋友圈的时间线) 2、消息队列 |
Set (集合) | Redis的集合相当于Java语言里面的HashSet,内部的键值对是无须的、唯一的 Set的结构底层实现是字典,只不过所有的value都是NULL,其他的特性和字典一摸一样。 | 1、添加、删除、查找的复杂度都是O(1) 2、为集合提供了求交集、并集、差集等操作 当set集合容纳的元素都是整数并且元素个数较少时,Redis会使用intset来存储集合元素。intset是紧凑的数组结构,同时支持16位,32位和64位整数 | 1、共同好友 2、利用唯一性,统计访问网站的所有独立ip 3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐 |
Sorted Set (有序集合) | Redis有序列表类似于Java的SortedSet和HashMap的结合体, 一方面是一个set,保证内部value的唯一性,另一方面可以给每个value赋予一个score,代表这个value的排序权重。 它的内部实现是一个Hash字典 + 一个跳表。 | 数据插入集合时,已经进行天然排序 Redis的跳表共有64层,能容纳2的64次方个元素。 Redis之所以用跳表来实现有序集合 1. 插入、删除、查找以及迭代输出有序序列这几个操作,红黑树都能完成,时间复杂度跟跳表是一样的。但是按照区间来查找数据,红黑树的效率就没有跳表高 2. 跳表更容易代码实现,比起红黑树来说还是好懂、好写很多,可读性好,不容易出错 3. 跳表更加灵活,可以通过改变索引构建策略,有效平衡执行效率和内存消耗 | 1、排行榜,取TopN操作 2、带权重的消息队列 |