Redis是一个开源的高性能Key-Value数据库,和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型),主要用来实现缓存,也可以用来实现分布式锁。 Redis的简单操作:
- 1、set key value 用于增加数据到数据库中
- 2、setnx key value 用于添加键值对,如果该key值不存在,则成功添加并返回1,如果该key值存在则不操作并返回0
- 3、del key value 用于删除指定的key-value对
- 4、expire key seconds 用于为指定Key值设定过期时间,单位是秒
- 5、pexpire key milliseconds 用于为指定的Key值设定过期时间,单位是毫秒
- 6、keys * 用于查看当前数据库中存在的Key-value对
Redis是一种基于内存的高性能key-value数据库,具有以下优点: a.单线程,利用redis队列技术并将访问变为串行访问,消除了传统数据库串行控制的开销 b.redis具有快速和持久化的特征,速度快,因为数据存在内存中。 c.分布式 读写分离模式 d.支持丰富数据类型 e.支持事务,操作都是原子性,所谓原子性就是对数据的更改要么全部执行,要不全部不执行。 f.可用于缓存,消息,按key设置过期时间,过期后自动删除 其单线程和原子性操作保是其可以作为分布式锁是实现方案的基础。 实现Redis分布式锁主要基于三条操作
setnx key value
expire key seconds
del key value
我们设计一个车票秒杀平台,假设车票剩余100个,每个顾客都是一个线程,都仅尝试购买一张票,模拟120个并发的线程,将有100个线程获得资源并抢到车票,剩余线程将显示无法没有剩余车票。
当余票大于0时,才会卖出车票,并且库存减1。
用来模拟顾客买票的线程 该类中定义了一个静态的JedisPool的类,以及静态配置,使不同的是线程使用相同的连接配置,而无需生个多个配置类。 其中jedis是一个JAR包,用来使java与jedis构建连接。可以使用如下配置导入
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
如果不适用maven也可以手动导入JAR包。 jedis的具体安装过程非常简单,只需下载解压就可以。 ###3、设计一个分布式锁类 该类需要继承于Lock类,并实现其三个主要方法TryLock、Lock和unlock。
- 该类用于设置锁的KEY值和Value值,当初考虑一个线程不能unlock其他线程的锁,所以每个线程的value是不同的,在unlock之前首先判断是否为自己的锁,但是由于该类继承于Lock类,因此具有互斥性,所以此处的value用静态的也没有问题。
- 为了避免抢到锁的线程挂掉而导致死锁,需要为ke设置生存时间
- 获取到连接后执行完相应操作记得释放链接,避免连接资源不足。
- 打印一个执行信息,使程序的执行过程更加直观。
设置120个并发线程,CyclicBarrier的存在是为了实现120个线程真正的同时开始。 注释中的程序是为了与JVM锁Lock和synchronized机制对比,在此不详细说明。
1、无法连接数据库的错误
原因是没有打开redis服务,需要手动开启
2、连接资源不足的问题
原因:可能是程序中忘了释放链接,或者线程数多于配置信息中的最大连接数