redis理解和用法(写的辣鸡勿喷,没有教程,都是自己的理解)
作者:互联网
一.前因:面试的时候问到一个问题怎么解决秒杀问题,秒杀不至于mysql崩盘
一般问安全就涉及三种方式
1.串行:这个其实学过操作系统的朋友都知道这个其实相当消息队列,一个一个解决,但是用什么方法调度就由程序实现.
2.多线程+同步锁:举个例子其实就是相当于Hibernate的sessionfactory一样,这个可以理解为单例模式
3.单线程+多路IO复用:多路IO复用技术类似于拨开关,多个任务通过拨开关的方式共用一条线程,哪个任务需要了开关就拨到哪个任务,避免了CPU在不同的线程中切换,提高效率。也就是我们的redis
redis快的原因:
1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);
要想了解HashMap,Hashset,其实Hashset的底层就是new了一个HashMap.所以HashMap要想理解就必须理解HashTable
HashTable其实就是链表加数组:下面就来附上HashTable源码(手撸)
package datastructure.HashTable; /** * 缓存工具 1).哈希表 数组+链表 数组+二叉树 2)提升数据的查找速度 3).现在市场上有的redis,像hibermate , * ibatis都有缓存功能 * * @author whr * */ public class HashTableDemo { public static void main(String[] args) { HashTable hashTable = new HashTable(7); hashTable.add(new Emp(15, "015")); hashTable.add(new Emp(2, "005")); hashTable.add(new Emp(14, "014")); hashTable.add(new Emp(100, "100")); hashTable.add(new Emp(20, "020")); hashTable.add(new Emp(51, "051")); hashTable.add(new Emp(38, "038")); /* * Emp emp = hashTable.findEmpById(1000); System.out.println(emp); */ hashTable.list(); Emp temp = hashTable.findEmpById(100); System.out.println("找到的用户信息为:"+temp); } } // 创建Hashtable class HashTable { private EmpLinkedList[] empLinkedLists; private int size; // 构造器:初始化链表 public HashTable(int size) { this.size = size; empLinkedLists = new EmpLinkedList[size]; // 初始化每一条链表,每一条链表都需要初始化不然会报空指针异常 for (int i = 0; i < size; i++) { empLinkedLists[i] = new EmpLinkedList(); } } // 添加 public void add(Emp emp) { // 根据员工的Id计算出所在的链表 int index = hashFun(emp.id); // 将Emp加入到对应的链表上面去 empLinkedLists[index].add(emp); } // 编写一个散列函数,使用取模法 public int hashFun(int id) { return id % size; } // 遍历展示HashTable public void list() { int count = 0; for (int i = 0; i < size; i++) { System.out.println("第" + (++count) + "条链表的信息如下:"); empLinkedLists[i].list(); System.out.println("================================="); } } // 根据id查找雇员 // 如果查找到,就返回Emp,否则返回null public Emp findEmpById(int id) { int index = hashFun(id); EmpLinkedList empLinkedList = empLinkedLists[index]; Emp emp = empLinkedList.FindEmpById(id); return emp; } // 根据雇员id找到雇员并修改其基本信息 public void updateEmpById(int id, String name) { Emp emp = findEmpById(id); if (emp == null) { System.out.println("对不起,要修改的用户不存在~~~~"); return; } emp.name = name; } } /** * 创建EmpLinkedList表示一条链表 * * @author whr * */ class EmpLinkedList { private Emp head;// 头指针,指向第一个emp,所以head是有效的 // 添加雇员到链表 // 假定添加雇员的时候就将员工添加到链表末尾,id是自增长的 public void add(Emp emp) { // 添加第一个雇员让头结点等于emp if (head == null) { head = emp; return; } else { Emp current = head; while (current.next != null) { current = current.next; } current.next = emp; } } // 找到Emp通过id public Emp FindEmpById(int id) { Emp temp = head; while (temp != null) { if (id == temp.id) { return temp; } temp = temp.next; } System.out.println("对不起,没有找到编号为:"+id+"的雇员"); return null; } // 遍历链表的雇员信息 public void list() { if (head == null || head.next == null) { System.out.println(head); return; } Emp current = head; while (current != null) { System.out.println(current); current = current.next; } } } // 雇员类 class Emp { public int id;// 员工Id public String name;// 员工名字 public Emp next;// 下一个员工 public Emp() { } public Emp(int id, String name) { // TODO Auto-generated constructor stub this.id = id; this.name = name; } @Override public String toString() { return "Emp [id=" + id + ", name=" + name + "]"; } }
2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;
3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
4、使用多路I/O复用模型,非阻塞IO;
5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
三.为什么设计时是单线程?
Redis设计为单线程的因素是因为单线程状态下,Redis基于内存就已经很快了,没必要设计为多线程。
四.安装使用
官网下载,一般会安装在linux上面,安装使用网上有教程
五.应用
在电商项目中秒杀,登录如果是cookie不安全,这个是重点需要自己练习,所以赶紧练习去吧,朋友们!!!!
标签:int,辣鸡,redis,id,链表,理解,Emp,public,emp 来源: https://www.cnblogs.com/whr-blogs/p/12809251.html