Rumah  >  Artikel  >  pangkalan data  >  Perkara yang perlu dilakukan tentang ketidakkonsistenan sesi teragih dalam redis

Perkara yang perlu dilakukan tentang ketidakkonsistenan sesi teragih dalam redis

青灯夜游
青灯夜游ke hadapan
2021-11-12 10:47:142600semak imbas

Apa yang perlu dilakukan jika sesi yang diedarkan tidak konsisten? Artikel berikut akan memperkenalkan kepada anda penyelesaian kepada ketidakkonsistenan sesi yang diedarkan dalam redis. Saya harap ia akan membantu anda!

Perkara yang perlu dilakukan tentang ketidakkonsistenan sesi teragih dalam redis

Penyelesaian ketidakkonsistenan sesi yang diedarkan

1.

  • Sesi ialah teknologi penjejakan sesi komunikasi antara pelanggan dan pelayan Pelayan dan pelanggan mengekalkan maklumat sesi asas keseluruhan komunikasi. [Cadangan berkaitan: Tutorial video Redis]

  • Apabila pelanggan mengakses pelayan buat kali pertama, pelayan akan membalas dengan sessionId dan menyimpannya secara setempat kuki, lawatan seterusnya akan meletakkan sessionId dalam kuki ke dalam pengepala permintaan untuk mengakses pelayan

  • Jika data yang sepadan tidak ditemui melalui sessionId ini, maka pelayan akan membuat satu. sessionId baharu dan memberi respons kepada pelanggan.

2.

Dalam aplikasi web pelayan tunggal, maklumat sesi hanya perlu disimpan dalam pelayan Ini adalah cara paling biasa kami berhubung dengannya dalam beberapa tahun lalu

Tetapi dalam beberapa tahun kebelakangan ini, dengan populariti sistem yang diedarkan, satu sistem tidak lagi dapat memenuhi keperluan berjuta-juta pengguna yang semakin meningkat Pelayan yang digunakan dalam kelompok telah digunakan dalam banyak syarikat

Apabila permintaan konkurensi tinggi tiba di pelayan, pengimbangan beban digunakan diedarkan kepada pelayan dalam kelompok, yang boleh menyebabkan berbilang permintaan daripada pengguna yang sama diedarkan ke pelayan berbeza dalam kelompok, dan data sesi tidak boleh diperoleh, jadi sesi perkongsian menjadi Satu persoalan.

Perkara yang perlu dilakukan tentang ketidakkonsistenan sesi teragih dalam redis

3. Bagaimanakah pengelompokan perkhidmatan dilakukan?

  • Projek SpringBoot, kemudian hanya tukar nombor port untuk memulakan beberapa, dan kemudian gunakan nginx sebagai proksi songsang bersatu.
  • Projek perkhidmatan mikro SpringCloud, maka pada masa ini, anda boleh menggunakan pengimbangan beban tempatan reben.

4. Perbezaan antara pengimbangan beban nginx dan pengimbangan beban reben

  • pengimbangan beban nginx ialah beban sebelah pelayan mengimbangi , mengakses satu alamat secara seragam, dan memutuskan pelayan yang hendak diakses berdasarkan algoritma pengimbangan beban.
  • imbangan beban reben, iaitu pengimbangan beban tempatan (pengimbangan beban pelanggan), cache dan merekodkan alamat pelanggan yang menyediakan perkhidmatan dan melaksanakan pengimbangan beban berdasarkan algoritma tempatan.

5. Penyelesaian konsistensi sesi

1 >

Perkara yang perlu dilakukan tentang ketidakkonsistenan sesi teragih dalam redisIdea: Berbilang pelayan menyegerakkan sesi antara satu sama lain, supaya setiap pelayan mengandungi semua sesi

Kelebihan: Fungsi yang disokong oleh pelayan, aplikasi tidak tidak perlu mengubah suai kod

Kelemahan:

Penyegerakan sesi memerlukan penghantaran data, yang menduduki lebar jalur intranet dan mempunyai kelewatan
  • semua Pelayan mengandungi semua sesi data. Jumlah data dihadkan oleh memori dan tidak boleh dikembangkan secara mendatar

Kaedah storan pelanggan

Perkara yang perlu dilakukan tentang ketidakkonsistenan sesi teragih dalam redisIdea: Pelayan menyimpan sesi semua pengguna, yang menggunakan banyak memori Sesi boleh disimpan dalam kuki penyemak imbas Setiap hujung hanya perlu menyimpan data seorang pengguna

Kelebihan: Pelayan tidak perlu menyimpan

Kelemahan:

Setiap permintaan http membawa sesi, yang merangkumi lebar jalur rangkaian luaran data disimpan pada penghujung dan dalam Penghantaran rangkaian mempunyai risiko keselamatan seperti kebocoran, gangguan dan kecurian
  • Saiz data yang disimpan dalam sesi dan bilangan kuki nama domain adalah terhad
  • Nota: Walaupun penyelesaian ini tidak biasa digunakan, Ia sememangnya satu cara berfikir.

3. Konsistensi cincang proksi songsang

Idea: Untuk memastikan ketersediaan tinggi, pelayan mempunyai berbilang proksi terbalik yang berlebihan Bolehkah lapisan lakukan sesuatu supaya permintaan daripada pengguna yang sama dijamin mendarat pada pelayan yang sama?

Pilihan 1: Cincang proksi empat lapisan

Lapisan proksi terbalik menggunakan IP pengguna untuk pencincangan untuk memastikan IP yang sama permintaan jatuh pada pelayan yang sama

Perkara yang perlu dilakukan tentang ketidakkonsistenan sesi teragih dalam redis

Pilihan 2: Cincang proksi tujuh lapisan

Proksi terbalik menggunakan atribut perniagaan tertentu dalam protokol http untuk pencincangan, seperti sid, city_id, user_id, dll., yang boleh melaksanakan strategi cincangan dengan lebih fleksibel untuk memastikan permintaan daripada pengguna penyemak imbas yang sama jatuh pada pelayan yang sama .

Kelebihan:

  • Hanya perlu menukar konfigurasi nginx, tidak perlu mengubah suai kod aplikasi
  • Pengimbangan beban, selagi atribut cincang adalah seragam , beban berbilang pelayan adalah Seimbang
  • boleh menyokong pengembangan mendatar pelayan (kaedah penyegerakan sesi tidak mungkin, tertakluk kepada had memori)

Kelemahan:

  • Jika pelayan dimulakan semula , beberapa sesi akan hilang, menyebabkan kesan perniagaan Sebagai contoh, sesetengah pengguna akan log masuk semula
  • Jika pelayan dikembangkan secara mendatar dan sesi diedarkan semula selepas rehash, sesetengah pengguna. tidak akan dihalakan ke sesi yang betul

Sesi umumnya mempunyai tempoh sah kedua-dua kelemahan itu boleh dianggap bersamaan dengan kegagalan sesi separa Secara umumnya, masalahnya tidak besar.

Sama ada cincangan empat lapisan atau cincang tujuh lapisan, saya secara peribadi mengesyorkan yang pertama: biarkan perisian profesional melakukan perkara profesional, dan proksi terbalik bertanggungjawab untuk pemajuan. Cuba untuk tidak memperkenalkan perniagaan lapisan aplikasi atribut melainkan anda perlu (seperti , kadangkala berbilang bilik komputer dan berbilang pelayan perlu dihalakan ke pelayan dalam bilik komputer yang berbeza mengikut atribut perniagaan).

Perbezaan antara pengimbangan beban empat lapisan dan tujuh lapisan

Storan terpusat bersatu bahagian belakang

Perkara yang perlu dilakukan tentang ketidakkonsistenan sesi teragih dalam redis

Kelebihan:

  • Tiada risiko keselamatan
  • Boleh dikembangkan secara mendatar, pangkalan data/cache boleh dibahagikan secara mendatar
  • Perkhidmatan Tidak akan ada kehilangan sesi apabila pelanggan dimulakan semula atau dikembangkan

Kelemahan: Panggilan rangkaian ditambah dan kod aplikasi perlu diubah suai

Untuk storan db atau cache, saya secara peribadi mengesyorkan yang terakhir: sesi Kekerapan membaca akan menjadi sangat tinggi, dan tekanan pangkalan data akan agak tinggi. Jika terdapat keperluan untuk ketersediaan tinggi sesi, cache boleh disediakan dengan sangat baik, tetapi dalam kebanyakan kes sesi boleh hilang, dan secara amnya tidak perlu mempertimbangkan ketersediaan tinggi.

Ringkasan

Kaedah biasa reka bentuk seni bina untuk memastikan konsistensi sesi:

  • Kaedah penyegerakan sesi: berbilang peranti Pelayan menyegerakkan data antara satu sama lain
  • Kaedah storan sisi pelanggan Pengguna hanya menyimpan datanya sendiri
  • Konsistensi cincang proksi terbalik kedua-dua pencincangan empat lapisan dan pencincangan tujuh lapisan boleh dilakukan pastikan permintaan pengguna. Ia jatuh pada pelayan
  • Pelayan storan bersatu bahagian belakang dimulakan semula dan dikembangkan, dan sesi tidak akan hilang (storan bersatu cache bahagian belakang disyorkan)

6 Amalan kes: SpringSession redis menyelesaikan masalah ketidakkonsistenan sesi yang diedarkan

Langkah 1: Tambah pakej pergantungan bagi SpringSession dan redis

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

Langkah 2: Fail konfigurasi

# 为某个包目录下 设置日志
logging.level.com.ljw=debug

# 设置session的存储方式,采用redis存储
spring.session.store-type=redis
# session有效时长为10分钟
server.servlet.session.timeout=PT10M

## Redis 配置
## Redis数据库索引(默认为0)
spring.redis.database=0
## Redis服务器地址
spring.redis.host=127.0.0.1
## Redis服务器连接端口
spring.redis.port=6379
## Redis服务器连接密码(默认为空)
spring.redis.password=

Langkah 3: Konfigurasikan pemintas

@Configuration
public class SessionConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SecurityInterceptor())
                //排除拦截的2个路径
                .excludePathPatterns("/user/login")
                .excludePathPatterns("/user/logout")
                //拦截所有URL路径
                .addPathPatterns("/**");
    }
}
@Configuration
public class SecurityInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
        HttpSession session = request.getSession();
        //验证当前session是否存在,存在返回true true代表能正常处理业务逻辑
        if (session.getAttribute(session.getId()) != null){
            log.info("session拦截器,session={},验证通过",session.getId());
            return true;
        }
        //session不存在,返回false,并提示请重新登录。
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        response.getWriter().write("请登录!!!!!");
        log.info("session拦截器,session={},验证失败",session.getId());
        return false;
    }
}
  • Pemintas Pengendali
    • preHandle: Dipanggil sebelum pemproses perniagaan memproses permintaan. Prapemprosesan boleh melakukan pengekodan, kawalan keselamatan, pengesahan kebenaran, dsb.;
    • postHandle: dilaksanakan selepas pemproses perniagaan melengkapkan pemprosesan permintaan dan sebelum menjana paparan. Pemprosesan pasca (Perkhidmatan dipanggil dan ModelAndView dikembalikan, tetapi halaman tidak diberikan), terdapat peluang untuk mengubah suai ModelAndView
    • afterCompletion: dipanggil selepas DispatcherServlet telah memproses permintaan sepenuhnya, dan boleh digunakan untuk membersihkan sumber, dsb. Kembali ke pemprosesan (halaman telah diberikan)

Langkah 4: Pengawal

@RestController
@RequestMapping(value = "/user")
public class UserController {

    Map<String, User> userMap = new HashMap<>();

    public UserController() {
        //初始化2个用户,用于模拟登录
        User u1=new User(1,"user1","user1");
        userMap.put("user1",u1);
        User u2=new User(2,"user2","user2");
        userMap.put("user2",u2);
    }

    @GetMapping(value = "/login")
    public String login(String username, String password, HttpSession session) {
        //模拟数据库的查找
        User user = this.userMap.get(username);
        if (user != null) {
            if (!password.equals(user.getPassword())) {
                return "用户名或密码错误!!!";
            } else {
                session.setAttribute(session.getId(), user);
                log.info("登录成功{}",user);
            }
        } else {
            return "用户名或密码错误!!!";
        }
        return "登录成功!!!";
    }

    /**
     * 通过用户名查找用户
     */
    @GetMapping(value = "/find/{username}")
    public User find(@PathVariable String username) {
        User user=this.userMap.get(username);
        log.info("通过用户名={},查找出用户{}",username,user);
        return user;
    }

    /**
     *拿当前用户的session
     */
    @GetMapping(value = "/session")
    public String session(HttpSession session) {
        log.info("当前用户的session={}",session.getId());
        return session.getId();
    }

    /**
     * 退出登录
     */
    @GetMapping(value = "/logout")
    public String logout(HttpSession session) {
        log.info("退出登录session={}",session.getId());
        session.removeAttribute(session.getId());
        return "成功退出!!";
    }

}

Langkah 5: Kelas entiti

@Data
public class User implements  Serializable{

    private int id;
    private String username;
    private String password;

    public User(int id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

}

Langkah 6: Ujian akses

Log dahulu :http://127.0.0.1:8080/user/login?username=user1&password=user1

Soal semulahttp://127.0.0.1:8080/user /find /user1

7 Analisis prinsip redis SpringSession

Langkah 1: Analisis. data redis bagi Struktur SpringSession

127.0.0.1:6379> keys *
1) "spring:session:sessions:9889ccfd-f4c9-41e5-b9ab-a77649a7bb6a"
2) "spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b"
3) "spring:session:expirations:1635413520000"
4) "spring:session:sessions:expires:9889ccfd-f4c9-41e5-b9ab-a77649a7bb6a"
5) "spring:session:expirations:1635412980000"
6) "spring:session:sessions:d3434f61-4d0a-4687-9070-610bd7790f3b"

Perkara biasa: 3 kekunci semuanya bermula dengan spring:session:, mewakili data redis SpringSession.

Jenis pertanyaan

127.0.0.1:6379> type spring:session:sessions:d3434f61-4d0a-4687-9070-610bd7790f3b
hash
127.0.0.1:6379> hgetall spring:session:sessions:d3434f61-4d0a-4687-9070-610bd7790f3b
// session的创建时间
1) "creationTime"
2) "\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x01|\xc5\xdb\xecu"
// sesson的属性,存储了user对象
3) "sessionAttr:d3434f61-4d0a-4687-9070-610bd7790f3b"
4) "\xac\xed\x00\x05sr\x00\x1ecom.ljw.redis.controller.User\x16\"_m\x1b\xa0W\x7f\x02\x00\x03I\x00\x02idL\x00\bpasswordt\x00\x12Ljava/lang/String;L\x00\busernameq\x00~\x00\x01xp\x00\x00\x00\x01t\x00\x05user1q\x00~\x00\x03"
//最后的访问时间
5) "lastAccessedTime"
6) "\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x01|\xc5\xe1\xc7\xed"
//失效时间 100分钟
7) "maxInactiveInterval"
8) "\xac\xed\x00\x05sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x17p"

Langkah 2: Analisis strategi tamat tempoh redis SpringSession

Untuk data tamat tempoh , secara amnya terdapat tiga strategi pemadaman:

  • Pemadaman berjadual, iaitu semasa menetapkan masa tamat tempoh kunci, cipta pemasa dan padamkannya serta-merta apabila masa tamat tempoh kunci tiba. .

  • Pemadaman malas, iaitu, apabila mengakses kunci, ia dinilai sama ada kunci telah tamat tempoh, dan kemudian dipadamkan jika ia tamat tempoh, jika tidak, nilai kunci dikembalikan.

  • 定期删除,即每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。

  • redis删除过期数据采用的是懒性删除+定期删除组合策略,也就是数据过期了并不会及时被删除。

  • 但由于redis是单线程,并且redis对删除过期的key优先级很低;如果有大量的过期key,就会出现key已经过期但是未删除。

  • 为了实现 session 过期的及时性,spring session 采用了定时删除+惰性删除的策略。

定时删除

127.0.0.1:6379> type spring:session:expirations:1635413520000
set
127.0.0.1:6379> smembers  spring:session:expirations:1635413520000
1) "\xac\xed\x00\x05t\x00,expires:d3434f61-4d0a-4687-9070-610bd7790f3b"

Perkara yang perlu dilakukan tentang ketidakkonsistenan sesi teragih dalam redis

2) "spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b" 
3) "spring:session:expirations:1635413520000" 
6) "spring:session:sessions:d3434f61-4d0a-4687-9070-610bd7790f3b"
  • 1635412980000 是时间戳,等于 2021-10-28 17:23:00,即是该可以在这个时刻过期
  • springsession 定时(1分钟)轮询,删除spring:session:expirations:[?] 的过期成员元素,例如:spring:session:expirations:1635413520000
  • springsesion 定时检测超时的key的值,根据值删除seesion,例如key:spring:session:expirations:1635413520000,值为(sessionId):d3434f61-4d0a-4687-9070-610bd7790f3b的seesion

惰性删除

127.0.0.1:6379> type spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b
string
127.0.0.1:6379> get spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b
""
127.0.0.1:6379> ttl spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b
(integer) 3143
127.0.0.1:6379>
  • 访问 spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b的时候,判断key是否过期,过期则删除,否则返回改进的值。
  • 例如 访问spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b的时候,判断 ttl 是否过期,过期就直接删除
2) "spring:session:sessions:expires:d3434f61-4d0a-4687-9070-610bd7790f3b" 
3) "spring:session:expirations:1635413520000" 
6) "spring:session:sessions:d3434f61-4d0a-4687-9070-610bd7790f3b"

更多编程相关知识,请访问:编程视频!!

Atas ialah kandungan terperinci Perkara yang perlu dilakukan tentang ketidakkonsistenan sesi teragih dalam redis. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:juejin.cn. Jika ada pelanggaran, sila hubungi admin@php.cn Padam